Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1998,6 +1998,10 @@ def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group; def msingle_float : Flag<["-"], "msingle-float">, Group; def mdouble_float : Flag<["-"], "mdouble-float">, Group; +def mmadd4 : Flag<["-"], "mmadd4">, Group, + HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">; +def mno_madd4 : Flag<["-"], "mno-madd4">, Group, + HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">; def mmsa : Flag<["-"], "mmsa">, Group, HelpText<"Enable MSA ASE (MIPS only)">; def mno_msa : Flag<["-"], "mno-msa">, Group, Index: lib/Driver/ToolChains/Arch/Mips.cpp =================================================================== --- lib/Driver/ToolChains/Arch/Mips.cpp +++ lib/Driver/ToolChains/Arch/Mips.cpp @@ -298,6 +298,13 @@ AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, options::OPT_modd_spreg, "nooddspreg"); + + if(Arg *A = Args.getLastArg(options::OPT_mmadd4, options::OPT_mno_madd4)) { + if(A->getOption().matches(options::OPT_mmadd4)) + Features.push_back("+madd4"); + else + Features.push_back("-madd4"); + } } mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) { Index: test/CodeGen/mips-madd4.c =================================================================== --- test/CodeGen/mips-madd4.c +++ test/CodeGen/mips-madd4.c @@ -0,0 +1,86 @@ +// RUN: %clang --target=mips64-unknown-linux -S -mmadd4 %s -o -| FileCheck %s -check-prefix=MADD4 +// RUN: %clang --target=mips64-unknown-linux -S -mno-madd4 %s -o -| FileCheck %s -check-prefix=NOMADD4 +// RUN: %clang --target=mips64-unknown-linux -S -mmadd4 -fno-honor-nans %s -o -| FileCheck %s -check-prefix=MADD4-NONAN +// RUN: %clang --target=mips64-unknown-linux -S -mno-madd4 -fno-honor-nans %s -o -| FileCheck %s -check-prefix=NOMADD4-NONAN + +float madd_s (float f, float g, float h) +{ + return (f * g) + h; +} +// MADD4: madd.s +// NOMADD4: mul.s +// NOMADD4: add.s + +float msub_s (float f, float g, float h) +{ + return (f * g) - h; +} +// MADD4: msub.s +// NOMADD4: mul.s +// NOMADD4: sub.s + +double madd_d (double f, double g, double h) +{ + return (f * g) + h; +} +// MADD4: madd.d +// NOMADD4: mul.d +// NOMADD4: add.d + +double msub_d (double f, double g, double h) +{ + return (f * g) - h; +} +// MADD4: msub.d +// NOMADD4: mul.d +// NOMADD4: sub.d + + +float nmadd_s (float f, float g, float h) +{ + // FIXME: Zero has been explicitly placed to force generation of a positive + // zero in IR until pattern used to match this instruction is changed to + // comply with negative zero as well. + return 0-((f * g) + h); +} +// MADD4-NONAN: nmadd.s +// NOMADD4-NONAN: mul.s +// NOMADD4-NONAN: add.s +// NOMADD4-NONAN: sub.s + +float nmsub_s (float f, float g, float h) +{ + // FIXME: Zero has been explicitly placed to force generation of a positive + // zero in IR until pattern used to match this instruction is changed to + // comply with negative zero as well. + return 0-((f * g) - h); +} +// MADD4-NONAN: nmsub.s +// NOMADD4-NONAN: mul.s +// NOMADD4-NONAN: sub.s +// NOMADD4-NONAN: sub.s + +double nmadd_d (double f, double g, double h) +{ + // FIXME: Zero has been explicitly placed to force generation of a positive + // zero in IR until pattern used to match this instruction is changed to + // comply with negative zero as well. + return 0-((f * g) + h); +} +// MADD4-NONAN: nmadd.d +// NOMADD4-NONAN: mul.d +// NOMADD4-NONAN: add.d +// NOMADD4-NONAN: sub.d + +double nmsub_d (double f, double g, double h) +{ + // FIXME: Zero has been explicitly placed to force generation of a positive + // zero in IR until pattern used to match this instruction is changed to + // comply with negative zero as well. + return 0-((f * g) - h); +} +// MADD4-NONAN: nmsub.d +// NOMADD4-NONAN: mul.d +// NOMADD4-NONAN: sub.d +// NOMADD4-NONAN: sub.d +