Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 11, 2023

Conversation

wangleiat
Copy link
Contributor

…tructions

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

@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2023

@llvm/pr-subscribers-backend-loongarch

Author: wanglei (wangleiat)

Changes

…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 --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]

@wangleiat wangleiat requested a review from SixWeining December 8, 2023 09:13
…tructions

This is similar to single and double-precision floating-point
instructions.
@wangleiat wangleiat merged commit af999c4 into llvm:main Dec 11, 2023
@wangleiat wangleiat deleted the vec branch December 29, 2023 08:02
leecheechen pushed a commit to leecheechen/llvm-project that referenced this pull request Jun 9, 2025
…tructions (llvm#74819)

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

(cherry picked from commit af999c4)

Change-Id: I4b946a4a4e6e0869aec43e6b085025a06a11e012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants