diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -4168,6 +4168,15 @@ } defm FSUB : TwoOperandFPData<0b0011, "fsub", any_fsub>; +// Match reassociated forms of FNMUL. +def : Pat<(fmul (fneg FPR16:$a), (f16 FPR16:$b)), + (FNMULHrr FPR16:$a, FPR16:$b)>, + Requires<[HasFullFP16]>; +def : Pat<(fmul (fneg FPR32:$a), (f32 FPR32:$b)), + (FNMULSrr FPR32:$a, FPR32:$b)>; +def : Pat<(fmul (fneg FPR64:$a), (f64 FPR64:$b)), + (FNMULDrr FPR64:$a, FPR64:$b)>; + def : Pat<(v1f64 (fmaximum (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))), (FMAXDrr FPR64:$Rn, FPR64:$Rm)>; def : Pat<(v1f64 (fminimum (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))), diff --git a/llvm/test/CodeGen/AArch64/fnmul.ll b/llvm/test/CodeGen/AArch64/fnmul.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/fnmul.ll @@ -0,0 +1,76 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+v8.2a,+fullfp16 -fp-contract=fast -verify-machineinstrs -global-isel=0 | FileCheck %s +;RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+v8.2a,+fullfp16 -verify-machineinstrs -global-isel=0 | FileCheck %s + + +define half @fnmul16(half noundef %x, half noundef %y) { +; CHECK-LABEL: fnmul16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fnmul h0, h0, h1 +; CHECK-NEXT: ret +; +entry: + %fneg = fneg fast half %x + %mul = fmul fast half %fneg, %y + ret half %mul +} + +define float @fnmul32(float noundef %x, float noundef %y) { +; CHECK-LABEL: fnmul32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fnmul s0, s0, s1 +; CHECK-NEXT: ret +; +entry: + %fneg = fneg float %x + %mul = fmul float %fneg, %y + ret float %mul +} + +define double @fnmul64(double noundef %x, double noundef %y) { +; CHECK-LABEL: fnmul64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fnmul d0, d0, d1 +; CHECK-NEXT: ret +; +entry: + %fneg = fneg fast double %x + %mul = fmul fast double %fneg, %y + ret double %mul +} + +define half @fnmul16_2(half noundef %x, half noundef %y) { +; CHECK-LABEL: fnmul16_2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fnmul h0, h1, h0 +; CHECK-NEXT: ret +; +entry: + %fneg = fneg fast half %y + %mul = fmul fast half %x, %fneg + ret half %mul +} + +define float @fnmul32_2(float noundef %x, float noundef %y) { +; CHECK-LABEL: fnmul32_2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fnmul s0, s1, s0 +; CHECK-NEXT: ret +; +entry: + %fneg = fneg fast float %y + %mul = fmul fast float %x, %fneg + ret float %mul +} + +define double @fnmul64_2(double noundef %x, double noundef %y) { +; CHECK-LABEL: fnmul64_2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fnmul d0, d1, d0 +; CHECK-NEXT: ret +; +entry: + %fneg = fneg double %y + %mul = fmul double %x, %fneg + ret double %mul +}