Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -4170,6 +4170,17 @@ } defm FSUB : TwoOperandFPData<0b0011, "fsub", any_fsub>; +// Match reassociated forms only if not sign dependent rounding. +def : Pat<(fmul (fneg FPR16:$a), (f16 FPR16:$b)), + (FNMULHrr FPR16:$a, FPR16:$b)>, + Requires<[HasFullFP16,NoHonorSignDependentRounding]>; +def : Pat<(fmul (fneg FPR32:$a), (f32 FPR32:$b)), + (FNMULSrr FPR32:$a, FPR32:$b)>, + Requires<[NoHonorSignDependentRounding]>; +def : Pat<(fmul (fneg FPR64:$a), (f64 FPR64:$b)), + (FNMULDrr FPR64:$a, FPR64:$b)>, + Requires<[NoHonorSignDependentRounding]>; + 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))), Index: llvm/test/CodeGen/AArch64/fnmul.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/fnmul.ll @@ -0,0 +1,56 @@ +; 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 -fp-contract=fast -verify-machineinstrs -global-isel=0 -enable-sign-dependent-rounding-fp-math=1 | FileCheck %s --check-prefix=NEGMUL +;RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+v8.2a,+fullfp16 -verify-machineinstrs -global-isel=0 -enable-sign-dependent-rounding-fp-math=1 | FileCheck %s --check-prefix=NEGMUL + + +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 +; +; NEGMUL-LABEL: fnmul16: +; NEGMUL: // %bb.0: // %entry +; NEGMUL-NEXT: fneg h0, h0 +; NEGMUL-NEXT: fmul h0, h0, h1 +; NEGMUL-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 +; +; NEGMUL-LABEL: fnmul32: +; NEGMUL: // %bb.0: // %entry +; NEGMUL-NEXT: fneg s0, s0 +; NEGMUL-NEXT: fmul s0, s0, s1 +; NEGMUL-NEXT: ret +entry: + %fneg = fneg fast float %x + %mul = fmul fast 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 +; +; NEGMUL-LABEL: fnmul64: +; NEGMUL: // %bb.0: // %entry +; NEGMUL-NEXT: fneg d0, d0 +; NEGMUL-NEXT: fmul d0, d0, d1 +; NEGMUL-NEXT: ret +entry: + %fneg = fneg fast double %x + %mul = fmul fast double %fneg, %y + ret double %mul +}