[llvm] [LoongArch] Add codegen support for [X]VF{MSUB/NMADD/NMSUB}.{S/D} ins… (PR #74819)

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 8 01:13:30 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-loongarch

Author: wanglei (wangleiat)

<details>
<summary>Changes</summary>

…tructions

This is similar to single and double-precision floating-point instructions.

---

Patch is 122.86 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74819.diff


6 Files Affected:

- (modified) llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td (+26) 
- (modified) llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td (+26) 
- (added) llvm/test/CodeGen/LoongArch/lasx/fma-v4f64.ll (+804) 
- (added) llvm/test/CodeGen/LoongArch/lasx/fma-v8f32.ll (+804) 
- (added) llvm/test/CodeGen/LoongArch/lsx/fma-v2f64.ll (+804) 
- (added) llvm/test/CodeGen/LoongArch/lsx/fma-v4f32.ll (+804) 


``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index 8559baa0e525f..ec6983d0f4871 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -1455,6 +1455,32 @@ def : Pat<(fma v8f32:$xj, v8f32:$xk, v8f32:$xa),
 def : Pat<(fma v4f64:$xj, v4f64:$xk, v4f64:$xa),
           (XVFMADD_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>;
 
+// XVFMSUB_{S/D}
+def : Pat<(fma v8f32:$xj, v8f32:$xk, (fneg v8f32:$xa)),
+          (XVFMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>;
+def : Pat<(fma v4f64:$xj, v4f64:$xk, (fneg v4f64:$xa)),
+          (XVFMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>;
+
+// XVFNMADD_{S/D}
+def : Pat<(fneg (fma v8f32:$xj, v8f32:$xk, v8f32:$xa)),
+          (XVFNMADD_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>;
+def : Pat<(fneg (fma v4f64:$xj, v4f64:$xk, v4f64:$xa)),
+          (XVFNMADD_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>;
+def : Pat<(fma_nsz (fneg v8f32:$xj), v8f32:$xk, (fneg v8f32:$xa)),
+          (XVFNMADD_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>;
+def : Pat<(fma_nsz (fneg v4f64:$xj), v4f64:$xk, (fneg v4f64:$xa)),
+          (XVFNMADD_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>;
+
+// XVFNMSUB_{S/D}
+def : Pat<(fneg (fma v8f32:$xj, v8f32:$xk, (fneg v8f32:$xa))),
+          (XVFNMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>;
+def : Pat<(fneg (fma v4f64:$xj, v4f64:$xk, (fneg v4f64:$xa))),
+          (XVFNMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>;
+def : Pat<(fma_nsz (fneg v8f32:$xj), v8f32:$xk, v8f32:$xa),
+          (XVFNMSUB_S v8f32:$xj, v8f32:$xk, v8f32:$xa)>;
+def : Pat<(fma_nsz (fneg v4f64:$xj), v4f64:$xk, v4f64:$xa),
+          (XVFNMSUB_D v4f64:$xj, v4f64:$xk, v4f64:$xa)>;
+
 // XVFSQRT_{S/D}
 defm : PatXrF<fsqrt, "XVFSQRT">;
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 5947f241bb597..e468176885d75 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -1555,6 +1555,32 @@ def : Pat<(fma v4f32:$vj, v4f32:$vk, v4f32:$va),
 def : Pat<(fma v2f64:$vj, v2f64:$vk, v2f64:$va),
           (VFMADD_D v2f64:$vj, v2f64:$vk, v2f64:$va)>;
 
+// VFMSUB_{S/D}
+def : Pat<(fma v4f32:$vj, v4f32:$vk, (fneg v4f32:$va)),
+          (VFMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>;
+def : Pat<(fma v2f64:$vj, v2f64:$vk, (fneg v2f64:$va)),
+          (VFMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>;
+
+// VFNMADD_{S/D}
+def : Pat<(fneg (fma v4f32:$vj, v4f32:$vk, v4f32:$va)),
+          (VFNMADD_S v4f32:$vj, v4f32:$vk, v4f32:$va)>;
+def : Pat<(fneg (fma v2f64:$vj, v2f64:$vk, v2f64:$va)),
+          (VFNMADD_D v2f64:$vj, v2f64:$vk, v2f64:$va)>;
+def : Pat<(fma_nsz (fneg v4f32:$vj), v4f32:$vk, (fneg v4f32:$va)),
+          (VFNMADD_S v4f32:$vj, v4f32:$vk, v4f32:$va)>;
+def : Pat<(fma_nsz (fneg v2f64:$vj), v2f64:$vk, (fneg v2f64:$va)),
+          (VFNMADD_D v2f64:$vj, v2f64:$vk, v2f64:$va)>;
+
+// VFNMSUB_{S/D}
+def : Pat<(fneg (fma v4f32:$vj, v4f32:$vk, (fneg v4f32:$va))),
+          (VFNMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>;
+def : Pat<(fneg (fma v2f64:$vj, v2f64:$vk, (fneg v2f64:$va))),
+          (VFNMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>;
+def : Pat<(fma_nsz (fneg v4f32:$vj), v4f32:$vk, v4f32:$va),
+          (VFNMSUB_S v4f32:$vj, v4f32:$vk, v4f32:$va)>;
+def : Pat<(fma_nsz (fneg v2f64:$vj), v2f64:$vk, v2f64:$va),
+          (VFNMSUB_D v2f64:$vj, v2f64:$vk, v2f64:$va)>;
+
 // VFSQRT_{S/D}
 defm : PatVrF<fsqrt, "VFSQRT">;
 
diff --git a/llvm/test/CodeGen/LoongArch/lasx/fma-v4f64.ll b/llvm/test/CodeGen/LoongArch/lasx/fma-v4f64.ll
new file mode 100644
index 0000000000000..39dfee6bc2206
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/fma-v4f64.ll
@@ -0,0 +1,804 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx --fp-contract=fast < %s \
+; RUN:   | FileCheck %s --check-prefix=CONTRACT-FAST
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx --fp-contract=on < %s \
+; RUN:   | FileCheck %s --check-prefix=CONTRACT-ON
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx --fp-contract=off < %s \
+; RUN:   | FileCheck %s --check-prefix=CONTRACT-OFF
+
+define void @fmadd_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: fmadd_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: fmadd_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfadd.d $xr0, $xr0, $xr1
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: fmadd_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfadd.d $xr0, $xr0, $xr1
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %mul = fmul<4 x double> %v0, %v1
+  %add = fadd<4 x double> %mul, %v2
+  store <4 x double> %add, ptr %res
+  ret void
+}
+
+define void @fmsub_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: fmsub_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: fmsub_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: fmsub_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %mul = fmul<4 x double> %v0, %v1
+  %sub = fsub<4 x double> %mul, %v2
+  store <4 x double> %sub, ptr %res
+  ret void
+}
+
+define void @fnmadd_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: fnmadd_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfnmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: fnmadd_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfadd.d $xr0, $xr0, $xr1
+; CONTRACT-ON-NEXT:    xvbitrevi.d $xr0, $xr0, 63
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: fnmadd_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfadd.d $xr0, $xr0, $xr1
+; CONTRACT-OFF-NEXT:    xvbitrevi.d $xr0, $xr0, 63
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %mul = fmul<4 x double> %v0, %v1
+  %add = fadd<4 x double> %mul, %v2
+  %negadd = fneg<4 x double> %add
+  store <4 x double> %negadd, ptr %res
+  ret void
+}
+
+define void @fnmadd_v4f64_nsz(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: fnmadd_v4f64_nsz:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfnmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: fnmadd_v4f64_nsz:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvbitrevi.d $xr1, $xr1, 63
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: fnmadd_v4f64_nsz:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvbitrevi.d $xr1, $xr1, 63
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %negv0 = fneg nsz<4 x double> %v0
+  %negv2 = fneg nsz<4 x double> %v2
+  %mul = fmul nsz<4 x double> %negv0, %v1
+  %add = fadd nsz<4 x double> %mul, %negv2
+  store <4 x double> %add, ptr %res
+  ret void
+}
+
+;; Check that fnmadd.s is not emitted.
+define void @not_fnmadd_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: not_fnmadd_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvbitrevi.d $xr2, $xr2, 63
+; CONTRACT-FAST-NEXT:    xvfmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: not_fnmadd_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvbitrevi.d $xr1, $xr1, 63
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: not_fnmadd_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvbitrevi.d $xr1, $xr1, 63
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %negv0 = fneg<4 x double> %v0
+  %negv2 = fneg<4 x double> %v2
+  %mul = fmul<4 x double> %negv0, %v1
+  %add = fadd<4 x double> %mul, %negv2
+  store <4 x double> %add, ptr %res
+  ret void
+}
+
+define void @fnmsub_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: fnmsub_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfnmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: fnmsub_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-ON-NEXT:    xvbitrevi.d $xr0, $xr0, 63
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: fnmsub_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfsub.d $xr0, $xr0, $xr1
+; CONTRACT-OFF-NEXT:    xvbitrevi.d $xr0, $xr0, 63
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %negv2 = fneg<4 x double> %v2
+  %mul = fmul<4 x double> %v0, %v1
+  %add = fadd<4 x double> %mul, %negv2
+  %neg = fneg<4 x double> %add
+  store <4 x double> %neg, ptr %res
+  ret void
+}
+
+define void @fnmsub_v4f64_nsz(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: fnmsub_v4f64_nsz:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfnmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: fnmsub_v4f64_nsz:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfsub.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: fnmsub_v4f64_nsz:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfsub.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %negv0 = fneg nsz<4 x double> %v0
+  %mul = fmul nsz<4 x double> %negv0, %v1
+  %add = fadd nsz<4 x double> %mul, %v2
+  store <4 x double> %add, ptr %res
+  ret void
+}
+
+;; Check that fnmsub.s is not emitted.
+define void @not_fnmsub_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: not_fnmsub_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvbitrevi.d $xr2, $xr2, 63
+; CONTRACT-FAST-NEXT:    xvfmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: not_fnmsub_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-ON-NEXT:    xvfsub.d $xr0, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: not_fnmsub_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmul.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a3, 0
+; CONTRACT-OFF-NEXT:    xvfsub.d $xr0, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %negv0 = fneg<4 x double> %v0
+  %mul = fmul<4 x double> %negv0, %v1
+  %add = fadd<4 x double> %mul, %v2
+  store <4 x double> %add, ptr %res
+  ret void
+}
+
+define void @contract_fmadd_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: contract_fmadd_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: contract_fmadd_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: contract_fmadd_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %mul = fmul contract <4 x double> %v0, %v1
+  %add = fadd contract <4 x double> %mul, %v2
+  store <4 x double> %add, ptr %res
+  ret void
+}
+
+define void @contract_fmsub_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: contract_fmsub_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: contract_fmsub_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-ON-NEXT:    xvfmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: contract_fmsub_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfmsub.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-OFF-NEXT:    ret
+entry:
+  %v0 = load <4 x double>, ptr %a0
+  %v1 = load <4 x double>, ptr %a1
+  %v2 = load <4 x double>, ptr %a2
+  %mul = fmul contract <4 x double> %v0, %v1
+  %sub = fsub contract <4 x double> %mul, %v2
+  store <4 x double> %sub, ptr %res
+  ret void
+}
+
+define void @contract_fnmadd_v4f64(ptr %res, ptr %a0, ptr %a1, ptr %a2) nounwind {
+; CONTRACT-FAST-LABEL: contract_fnmadd_v4f64:
+; CONTRACT-FAST:       # %bb.0: # %entry
+; CONTRACT-FAST-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-FAST-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-FAST-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-FAST-NEXT:    xvfnmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-FAST-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-FAST-NEXT:    ret
+;
+; CONTRACT-ON-LABEL: contract_fnmadd_v4f64:
+; CONTRACT-ON:       # %bb.0: # %entry
+; CONTRACT-ON-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-ON-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-ON-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-ON-NEXT:    xvfnmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-ON-NEXT:    xvst $xr0, $a0, 0
+; CONTRACT-ON-NEXT:    ret
+;
+; CONTRACT-OFF-LABEL: contract_fnmadd_v4f64:
+; CONTRACT-OFF:       # %bb.0: # %entry
+; CONTRACT-OFF-NEXT:    xvld $xr0, $a3, 0
+; CONTRACT-OFF-NEXT:    xvld $xr1, $a2, 0
+; CONTRACT-OFF-NEXT:    xvld $xr2, $a1, 0
+; CONTRACT-OFF-NEXT:    xvfnmadd.d $xr0, $xr2, $xr1, $xr0
+; CONTRACT-OFF-NEXT:    xvst $xr0, $a0, 0
+;...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/74819


More information about the llvm-commits mailing list