[clang] [llvm] Clang/buildFMulAdd: Use negated attribute (PR #121038)
YunQiang Su via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 24 01:02:09 PST 2024
https://github.com/wzssyqa created https://github.com/llvm/llvm-project/pull/121038
Use negated attribute if negMul or negAdd. So that we can lower
fneg+fmuladd to fmul+fsub if needed.
1) It can save one machine instruction:
fneg/fmul/fadd vs fmul/fsub
2) In strict mode, `c-a*b` may be different with `c+(-a)*b`.
>From c474a905f473d0844caf6ad7dd7b6ff338d01d34 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 24 Dec 2024 04:16:16 +0000
Subject: [PATCH 1/6] Support attribute negated
---
llvm/docs/LangRef.rst | 8 ++++++++
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 1 +
llvm/include/llvm/IR/Attributes.td | 3 +++
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 ++
.../SelectionDAG/SelectionDAGBuilder.cpp | 20 ++++++++++++++++++-
llvm/lib/Transforms/Utils/CodeExtractor.cpp | 1 +
6 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7e01331b20c570..9e5f39530b1679 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1573,6 +1573,14 @@ Currently, only the following parameter attributes are defined:
| pinf | Positive infinity | 512 |
+-------+----------------------+---------------+
+``negated``
+ The function parameter marked with this attribute is negated from
+ its opposite number by the frontend like Clang. The middle end or
+ backend should convert it back if possible. For example, `c-a*b`
+ is different with `c+(-a)*b`. Since we have only `fmuladd`,
+ this attribute on `a` is to mark that we are working on `c-a*b`.
+ So that we can convert `c+(-a)*b` to `fmsub` instruction
+ or `fmul`/`fsub`.
``alignstack(<n>)``
This indicates the alignment that should be considered by the backend when
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 21fd27d9838db7..7e9d174db22026 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -788,6 +788,7 @@ enum AttributeKindCodes {
ATTR_KIND_NO_EXT = 99,
ATTR_KIND_NO_DIVERGENCE_SOURCE = 100,
ATTR_KIND_SANITIZE_TYPE = 101,
+ ATTR_KIND_NEGATED = 102,
};
enum ComdatSelectionKindCodes {
diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
index 61955cf883c3f1..baeca5d53f3c46 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -162,6 +162,9 @@ def Memory : IntAttr<"memory", IntersectCustom, [FnAttr]>;
/// Forbidden floating-point classes.
def NoFPClass : IntAttr<"nofpclass", IntersectCustom, [ParamAttr, RetAttr]>;
+/// Converted from the opposite number
+def Negated : EnumAttr<"negated", IntersectAnd, [ParamAttr, RetAttr]>;
+
/// Function must be optimized for size first.
def MinSize : EnumAttr<"minsize", IntersectPreserve, [FnAttr]>;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index b4efd3928a2e6f..e87c9d2e13883d 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -755,6 +755,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_MEMORY;
case Attribute::NoFPClass:
return bitc::ATTR_KIND_NOFPCLASS;
+ case Attribute::Negated:
+ return bitc::ATTR_KIND_NEGATED;
case Attribute::Naked:
return bitc::ATTR_KIND_NAKED;
case Attribute::Nest:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f8d7c3ef7bbe71..a9de7e25a4eb6a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8360,10 +8360,28 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
// Break fmuladd into fmul and fadd.
if (TM.Options.AllowFPOpFusion == FPOpFusion::Strict ||
!TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), VT)) {
+ auto PrevNode = FPI.getPrevNode();
+ bool convertToFMULSUB = false;
+ if (PrevNode && PrevNode->getOpcode() == Instruction::FNeg) {
+ if (PrevNode->getName() == FPI.getOperand(0)->getName() &&
+ FPI.getAttributes().getParamAttrs(0).hasAttribute(
+ Attribute::Negated)) {
+ Opers[1] = DAG.getNode(ISD::FNEG, sdl, VT, Opers[1]).getValue(0);
+ convertToFMULSUB = true;
+ } else if (PrevNode->getName() == FPI.getOperand(1)->getName() &&
+ FPI.getAttributes().getParamAttrs(1).hasAttribute(
+ Attribute::Negated)) {
+ Opers[2] = DAG.getNode(ISD::FNEG, sdl, VT, Opers[2]).getValue(0);
+ convertToFMULSUB = true;
+ }
+ }
Opers.pop_back();
SDValue Mul = DAG.getNode(ISD::STRICT_FMUL, sdl, VTs, Opers, Flags);
pushOutChain(Mul, EB);
- Opcode = ISD::STRICT_FADD;
+ if (convertToFMULSUB)
+ Opcode = ISD::STRICT_FSUB;
+ else
+ Opcode = ISD::STRICT_FADD;
Opers.clear();
Opers.push_back(Mul.getValue(1));
Opers.push_back(Mul.getValue(0));
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
index 7ddb9e22c83441..4e1a8c560078aa 100644
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -918,6 +918,7 @@ Function *CodeExtractor::constructFunctionDeclaration(
case Attribute::PresplitCoroutine:
case Attribute::Memory:
case Attribute::NoFPClass:
+ case Attribute::Negated:
case Attribute::CoroDestroyOnlyWhenComplete:
case Attribute::CoroElideSafe:
case Attribute::NoDivergenceSource:
>From 73c85b212be0b2950e27ea3fdd4b83cc51714e76 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 24 Dec 2024 12:44:22 +0800
Subject: [PATCH 2/6] Add testcase
---
llvm/test/CodeGen/Mips/attribute-negated.ll | 54 ++++++++++++++++
llvm/test/CodeGen/X86/attribute-negated.ll | 72 +++++++++++++++++++++
2 files changed, 126 insertions(+)
create mode 100644 llvm/test/CodeGen/Mips/attribute-negated.ll
create mode 100644 llvm/test/CodeGen/X86/attribute-negated.ll
diff --git a/llvm/test/CodeGen/Mips/attribute-negated.ll b/llvm/test/CodeGen/Mips/attribute-negated.ll
new file mode 100644
index 00000000000000..04f7257e446f9a
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/attribute-negated.ll
@@ -0,0 +1,54 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=mipsel -mattr=+fp64,+mips32r2 < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK
+
+define dso_local double @x1(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul.d $f0, $f12, $f14
+; CHECK-NEXT: ldc1 $f1, 16($sp)
+; CHECK-NEXT: jr $ra
+; CHECK-NEXT: sub.d $f0, $f0, $f1
+entry:
+ %neg = fneg double %a
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double negated %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
+define dso_local double @x2(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul.d $f0, $f12, $f14
+; CHECK-NEXT: ldc1 $f1, 16($sp)
+; CHECK-NEXT: jr $ra
+; CHECK-NEXT: sub.d $f0, $f0, $f1
+entry:
+ %neg = fneg double %b
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double negated %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
+define dso_local double @x3(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: neg.d $f0, $f12
+; CHECK-NEXT: mul.d $f0, $f0, $f14
+; CHECK-NEXT: ldc1 $f1, 16($sp)
+; CHECK-NEXT: jr $ra
+; CHECK-NEXT: add.d $f0, $f0, $f1
+entry:
+ %neg = fneg double %a
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
+define dso_local double @x4(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: neg.d $f0, $f14
+; CHECK-NEXT: mul.d $f0, $f12, $f0
+; CHECK-NEXT: ldc1 $f1, 16($sp)
+; CHECK-NEXT: jr $ra
+; CHECK-NEXT: add.d $f0, $f0, $f1
+entry:
+ %neg = fneg double %b
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
diff --git a/llvm/test/CodeGen/X86/attribute-negated.ll b/llvm/test/CodeGen/X86/attribute-negated.ll
new file mode 100644
index 00000000000000..b54b4b6f3c8bab
--- /dev/null
+++ b/llvm/test/CodeGen/X86/attribute-negated.ll
@@ -0,0 +1,72 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=x86_64-- -mattr=-fma < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK
+; RUN: llc -mtriple=x86_64-- -mattr=+fma < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK-FMA
+
+define dso_local double @x1(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mulsd %xmm1, %xmm0
+; CHECK-NEXT: subsd %xmm2, %xmm0
+; CHECK-NEXT: retq
+;
+; CHECK-FMA-LABEL: x1:
+; CHECK-FMA: # %bb.0: # %entry
+; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
+; CHECK-FMA-NEXT: retq
+entry:
+ %neg = fneg double %a
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double negated %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
+define dso_local double @x2(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mulsd %xmm1, %xmm0
+; CHECK-NEXT: subsd %xmm2, %xmm0
+; CHECK-NEXT: retq
+;
+; CHECK-FMA-LABEL: x2:
+; CHECK-FMA: # %bb.0: # %entry
+; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
+; CHECK-FMA-NEXT: retq
+entry:
+ %neg = fneg double %b
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double negated %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
+define dso_local double @x3(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: xorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: mulsd %xmm1, %xmm0
+; CHECK-NEXT: addsd %xmm2, %xmm0
+; CHECK-NEXT: retq
+;
+; CHECK-FMA-LABEL: x3:
+; CHECK-FMA: # %bb.0: # %entry
+; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
+; CHECK-FMA-NEXT: retq
+entry:
+ %neg = fneg double %a
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
+define dso_local double @x4(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
+; CHECK-LABEL: x4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: xorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; CHECK-NEXT: mulsd %xmm1, %xmm0
+; CHECK-NEXT: addsd %xmm2, %xmm0
+; CHECK-NEXT: retq
+;
+; CHECK-FMA-LABEL: x4:
+; CHECK-FMA: # %bb.0: # %entry
+; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
+; CHECK-FMA-NEXT: retq
+entry:
+ %neg = fneg double %b
+ %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ ret double %0
+}
>From e4d042f22c83e056a9c6618969b2caa0726d50a7 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 24 Dec 2024 08:17:45 +0000
Subject: [PATCH 3/6] Revert fmuladd support
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 20 +------------------
1 file changed, 1 insertion(+), 19 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index a9de7e25a4eb6a..f8d7c3ef7bbe71 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8360,28 +8360,10 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
// Break fmuladd into fmul and fadd.
if (TM.Options.AllowFPOpFusion == FPOpFusion::Strict ||
!TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), VT)) {
- auto PrevNode = FPI.getPrevNode();
- bool convertToFMULSUB = false;
- if (PrevNode && PrevNode->getOpcode() == Instruction::FNeg) {
- if (PrevNode->getName() == FPI.getOperand(0)->getName() &&
- FPI.getAttributes().getParamAttrs(0).hasAttribute(
- Attribute::Negated)) {
- Opers[1] = DAG.getNode(ISD::FNEG, sdl, VT, Opers[1]).getValue(0);
- convertToFMULSUB = true;
- } else if (PrevNode->getName() == FPI.getOperand(1)->getName() &&
- FPI.getAttributes().getParamAttrs(1).hasAttribute(
- Attribute::Negated)) {
- Opers[2] = DAG.getNode(ISD::FNEG, sdl, VT, Opers[2]).getValue(0);
- convertToFMULSUB = true;
- }
- }
Opers.pop_back();
SDValue Mul = DAG.getNode(ISD::STRICT_FMUL, sdl, VTs, Opers, Flags);
pushOutChain(Mul, EB);
- if (convertToFMULSUB)
- Opcode = ISD::STRICT_FSUB;
- else
- Opcode = ISD::STRICT_FADD;
+ Opcode = ISD::STRICT_FADD;
Opers.clear();
Opers.push_back(Mul.getValue(1));
Opers.push_back(Mul.getValue(0));
>From 803d99dcf269b336af72c9878bdea1de94e20c58 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 24 Dec 2024 08:17:58 +0000
Subject: [PATCH 4/6] Revert "Add testcase"
This reverts commit 67789aad898c90576a5c591f85ebc9ac33db8615.
---
llvm/test/CodeGen/Mips/attribute-negated.ll | 54 ----------------
llvm/test/CodeGen/X86/attribute-negated.ll | 72 ---------------------
2 files changed, 126 deletions(-)
delete mode 100644 llvm/test/CodeGen/Mips/attribute-negated.ll
delete mode 100644 llvm/test/CodeGen/X86/attribute-negated.ll
diff --git a/llvm/test/CodeGen/Mips/attribute-negated.ll b/llvm/test/CodeGen/Mips/attribute-negated.ll
deleted file mode 100644
index 04f7257e446f9a..00000000000000
--- a/llvm/test/CodeGen/Mips/attribute-negated.ll
+++ /dev/null
@@ -1,54 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=mipsel -mattr=+fp64,+mips32r2 < %s \
-; RUN: | FileCheck %s --check-prefixes=CHECK
-
-define dso_local double @x1(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x1:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul.d $f0, $f12, $f14
-; CHECK-NEXT: ldc1 $f1, 16($sp)
-; CHECK-NEXT: jr $ra
-; CHECK-NEXT: sub.d $f0, $f0, $f1
-entry:
- %neg = fneg double %a
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double negated %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
-define dso_local double @x2(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x2:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul.d $f0, $f12, $f14
-; CHECK-NEXT: ldc1 $f1, 16($sp)
-; CHECK-NEXT: jr $ra
-; CHECK-NEXT: sub.d $f0, $f0, $f1
-entry:
- %neg = fneg double %b
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double negated %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
-define dso_local double @x3(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x3:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: neg.d $f0, $f12
-; CHECK-NEXT: mul.d $f0, $f0, $f14
-; CHECK-NEXT: ldc1 $f1, 16($sp)
-; CHECK-NEXT: jr $ra
-; CHECK-NEXT: add.d $f0, $f0, $f1
-entry:
- %neg = fneg double %a
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
-define dso_local double @x4(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x4:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: neg.d $f0, $f14
-; CHECK-NEXT: mul.d $f0, $f12, $f0
-; CHECK-NEXT: ldc1 $f1, 16($sp)
-; CHECK-NEXT: jr $ra
-; CHECK-NEXT: add.d $f0, $f0, $f1
-entry:
- %neg = fneg double %b
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
diff --git a/llvm/test/CodeGen/X86/attribute-negated.ll b/llvm/test/CodeGen/X86/attribute-negated.ll
deleted file mode 100644
index b54b4b6f3c8bab..00000000000000
--- a/llvm/test/CodeGen/X86/attribute-negated.ll
+++ /dev/null
@@ -1,72 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=x86_64-- -mattr=-fma < %s \
-; RUN: | FileCheck %s --check-prefixes=CHECK
-; RUN: llc -mtriple=x86_64-- -mattr=+fma < %s \
-; RUN: | FileCheck %s --check-prefixes=CHECK-FMA
-
-define dso_local double @x1(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x1:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mulsd %xmm1, %xmm0
-; CHECK-NEXT: subsd %xmm2, %xmm0
-; CHECK-NEXT: retq
-;
-; CHECK-FMA-LABEL: x1:
-; CHECK-FMA: # %bb.0: # %entry
-; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
-; CHECK-FMA-NEXT: retq
-entry:
- %neg = fneg double %a
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double negated %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
-define dso_local double @x2(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x2:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mulsd %xmm1, %xmm0
-; CHECK-NEXT: subsd %xmm2, %xmm0
-; CHECK-NEXT: retq
-;
-; CHECK-FMA-LABEL: x2:
-; CHECK-FMA: # %bb.0: # %entry
-; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
-; CHECK-FMA-NEXT: retq
-entry:
- %neg = fneg double %b
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double negated %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
-define dso_local double @x3(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x3:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; CHECK-NEXT: mulsd %xmm1, %xmm0
-; CHECK-NEXT: addsd %xmm2, %xmm0
-; CHECK-NEXT: retq
-;
-; CHECK-FMA-LABEL: x3:
-; CHECK-FMA: # %bb.0: # %entry
-; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
-; CHECK-FMA-NEXT: retq
-entry:
- %neg = fneg double %a
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %neg, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
-define dso_local double @x4(double noundef %a, double noundef %b, double noundef %c) local_unnamed_addr #0 {
-; CHECK-LABEL: x4:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xorpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
-; CHECK-NEXT: mulsd %xmm1, %xmm0
-; CHECK-NEXT: addsd %xmm2, %xmm0
-; CHECK-NEXT: retq
-;
-; CHECK-FMA-LABEL: x4:
-; CHECK-FMA: # %bb.0: # %entry
-; CHECK-FMA-NEXT: vfnmadd213sd {{.*#+}} xmm0 = -(xmm1 * xmm0) + xmm2
-; CHECK-FMA-NEXT: retq
-entry:
- %neg = fneg double %b
- %0 = tail call double @llvm.experimental.constrained.fmuladd.f64(double %a, double %neg, double %c, metadata !"round.dynamic", metadata !"fpexcept.ignore")
- ret double %0
-}
>From 31782fb96fc283fdd2ea177078b9d0b2920dc38f Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 24 Dec 2024 08:21:28 +0000
Subject: [PATCH 5/6] improve LangRef
---
llvm/docs/LangRef.rst | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 9e5f39530b1679..bf37e6a788c4b6 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1576,11 +1576,9 @@ Currently, only the following parameter attributes are defined:
``negated``
The function parameter marked with this attribute is negated from
its opposite number by the frontend like Clang. The middle end or
- backend should convert it back if possible. For example, `c-a*b`
- is different with `c+(-a)*b`. Since we have only `fmuladd`,
- this attribute on `a` is to mark that we are working on `c-a*b`.
- So that we can convert `c+(-a)*b` to `fmsub` instruction
- or `fmul`/`fsub`.
+ backend should convert it back if possible. For example if -(a*b)
+ is converted to (-a)*b, the arg0 of `fmul` instruction should be
+ marked with `negated` attribute.
``alignstack(<n>)``
This indicates the alignment that should be considered by the backend when
>From 9a8925b18e609ac646b2c16da81264a261545513 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 24 Dec 2024 08:14:22 +0000
Subject: [PATCH 6/6] Clang/buildFMulAdd: Use negated attribute
Use negated attribute if negMul or negAdd. So that we can lower
fneg+fmuladd to fmul+fsub if needed.
1) It can save one machine instruction:
fneg/fmul/fadd vs fmul/fsub
2) In strict mode, `c-a*b` may be different with `c+(-a)*b`.
---
clang/lib/CodeGen/CGExprScalar.cpp | 4 ++++
clang/test/CodeGen/constrained-math-builtins.c | 6 +++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 4b71bd730ce12c..14d73de055d8ec 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4120,6 +4120,10 @@ static Value* buildFMulAdd(llvm::Instruction *MulOp, Value *Addend,
CGF.CGM.getIntrinsic(llvm::Intrinsic::experimental_constrained_fmuladd,
Addend->getType()),
{MulOp0, MulOp1, Addend});
+ if (negMul)
+ dyn_cast<llvm::CallBase>(FMulAdd)->addParamAttr(0, llvm::Attribute::Negated);
+ if (negAdd)
+ dyn_cast<llvm::CallBase>(FMulAdd)->addParamAttr(2, llvm::Attribute::Negated);
} else {
FMulAdd = Builder.CreateCall(
CGF.CGM.getIntrinsic(llvm::Intrinsic::fmuladd, Addend->getType()),
diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c
index 68b9e75283c547..f044f15e98918b 100644
--- a/clang/test/CodeGen/constrained-math-builtins.c
+++ b/clang/test/CodeGen/constrained-math-builtins.c
@@ -392,12 +392,12 @@ void bar(float f) {
// CHECK: call float @llvm.experimental.constrained.fmuladd.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// CHECK: fneg
- // CHECK: call double @llvm.experimental.constrained.fmuladd.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+ // CHECK: call double @llvm.experimental.constrained.fmuladd.f64(double %{{.*}}, double %{{.*}}, double negated %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// CHECK: fneg
// CHECK: call x86_fp80 @llvm.experimental.constrained.fmuladd.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// CHECK: fneg
// CHECK: fneg
- // CHECK: call float @llvm.experimental.constrained.fmuladd.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+ // CHECK: call float @llvm.experimental.constrained.fmuladd.f32(float negated %{{.*}}, float %{{.*}}, float negated %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// CHECK: fneg
- // CHECK: call float @llvm.experimental.constrained.fmuladd.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+ // CHECK: call float @llvm.experimental.constrained.fmuladd.f32(float negated %{{.*}}, float %{{.*}}, float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
};
More information about the llvm-commits
mailing list