https://github.com/rohitaggarwal007 updated https://github.com/llvm/llvm-project/pull/213676
>From 43babe906d7e458f826e38e2122fdccd0f3e48fa Mon Sep 17 00:00:00 2001 From: Rohit Aggarwal <[email protected]> Date: Mon, 3 Aug 2026 19:00:50 +0530 Subject: [PATCH 1/3] [X86][AMDLIBM] - Add scalar AMD AOCL fast-call lowering (-fsclrlib=AMDLIBM) Under fast-math at -O3, scalar math library calls (e.g. tan, exp) are rewritten to their AMD AOCL fast-call equivalents (e.g. amd_fasttan, amd_fastexp) on X86 targets. LLVM: - New X86 MachineFunctionPass X86GenScalarAmdFastCalls, run in addMachineSSAOptimization at CodeGenOptLevel::Aggressive. - TargetLibraryInfo gains a scalar-math-library selection (ScalarLibrary enum, addScalarFunctionsFromMathLib / getScalarFunctionFromMathLib / getScalarMathLib / setScalarMathLib), populated from the new ScalarAOCLFuncs.def mapping and driven by the -scalar-library=AMDLIBM cl::opt (usable with llc and the LTO plugin). - The rewrite is gated on -scalar-library=AMDLIBM plus a function-level fast-math signal (per-operation fast-math flags are no longer available at this late machine pass in upstream codegen). Clang: - New -fsclrlib= driver/CC1 flag with a CodeGenOptions ScalarLib enum, applied in BackendUtil and forwarded to LTO as -plugin-opt=-scalar-library=. Tests: - llvm/test/CodeGen/X86/aocl-fast-scalar-calls.ll (llc path, incl. a negative no-fast-math case). - clang/test/CodeGen/X86/aocl-fast-scalar-calls.c (driver path). - aocl-fast-scalar-calls-mappings.ll: float variants (tanf, powf), a *_finite alias (__exp_finite), inverse-trig (acos, atan), and negative cases for math calls with no AOCL mapping (pow(double), cbrt). - aocl-fast-scalar-calls-i686.ll: 32-bit X86 coverage (tan, expf). - aocl-fast-scalar-calls.c: add a single-precision case (tanf) and an unmapped negative case (cbrt) to the clang driver test. --- clang/include/clang/Basic/CodeGenOptions.def | 3 + clang/include/clang/Basic/CodeGenOptions.h | 6 + clang/include/clang/Options/Options.td | 7 + clang/lib/CodeGen/BackendUtil.cpp | 15 + clang/lib/Driver/ToolChains/Clang.cpp | 11 + clang/lib/Driver/ToolChains/CommonArgs.cpp | 8 + .../test/CodeGen/X86/aocl-fast-scalar-calls.c | 40 +++ .../include/llvm/Analysis/ScalarAOCLFuncs.def | 80 ++++++ .../include/llvm/Analysis/TargetLibraryInfo.h | 33 +++ llvm/lib/Analysis/TargetLibraryInfo.cpp | 52 ++++ llvm/lib/Target/X86/CMakeLists.txt | 1 + llvm/lib/Target/X86/X86.h | 6 + .../Target/X86/X86GenScalarAmdFastCalls.cpp | 176 ++++++++++++ llvm/lib/Target/X86/X86TargetMachine.cpp | 5 + .../X86/aocl-fast-scalar-calls-i686.ll | 31 +++ .../X86/aocl-fast-scalar-calls-mappings.ll | 124 +++++++++ .../CodeGen/X86/aocl-fast-scalar-calls.ll | 63 +++++ llvm/test/CodeGen/X86/veclib-llvm.sincos.s | 258 ++++++++++++++++++ 18 files changed, 919 insertions(+) create mode 100644 clang/test/CodeGen/X86/aocl-fast-scalar-calls.c create mode 100644 llvm/include/llvm/Analysis/ScalarAOCLFuncs.def create mode 100644 llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp create mode 100644 llvm/test/CodeGen/X86/aocl-fast-scalar-calls-i686.ll create mode 100644 llvm/test/CodeGen/X86/aocl-fast-scalar-calls-mappings.ll create mode 100644 llvm/test/CodeGen/X86/aocl-fast-scalar-calls.ll create mode 100644 llvm/test/CodeGen/X86/veclib-llvm.sincos.s diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 7e54e75752f39..16e353ae76f20 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -420,6 +420,9 @@ VALUE_CODEGENOPT(InlineMaxStackSize, 32, UINT_MAX, Benign) // Vector functions library to use. ENUM_CODEGENOPT(VecLib, VectorLibrary, 4, VectorLibrary::NoLibrary, Benign) +// Scalar math functions library to use. +ENUM_CODEGENOPT(ScalarLib, ScalarLibrary, 1, Default_Scalar_Library, Benign) + /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel, Benign) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index c12434135a198..06cca30d9c5aa 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -110,6 +110,12 @@ class CodeGenOptions : public CodeGenOptionsBase { OnlyAlwaysInlining // Only run the always inlining pass. }; + /// Scalar math functions library to use with -fsclrlib=. + enum ScalarLibrary { + Default_Scalar_Library, // Use default library. + SCALAR_AMDLIBM // AMD scalar math library. + }; + enum ObjCDispatchMethodKind { Legacy = 0, NonLegacy = 1, diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 2467ebd0abe19..8eadef417fa35 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -3965,6 +3965,13 @@ def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "SVML", "SLEEF", "Darwin_libsystem_m", "ArmPL", "AMDLIBM", "NoLibrary"]>, MarshallingInfoEnum<CodeGenOpts<"VecLib">, "NoLibrary">; +def fsclrlib : Joined<["-"], "fsclrlib=">, Group<f_Group>, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Use the given scalar math functions library.">, + Values<"AMDLIBM,none">, + NormalizedValuesScope<"CodeGenOptions">, + NormalizedValues<["SCALAR_AMDLIBM", "Default_Scalar_Library"]>, + MarshallingInfoEnum<CodeGenOpts<"ScalarLib">, "Default_Scalar_Library">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>, Alias<flax_vector_conversions_EQ>, AliasArgs<["none"]>; def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 068b1b4c262c8..aa0797adddfc3 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -142,6 +142,19 @@ static std::string getProfileGenName(const CodeGenOptions &CodeGenOpts) { return FileName; } +/// Populate the scalar math library mappings on \p TLII according to the +/// -fsclrlib= selection. +static void addScalarMathLibrary(TargetLibraryInfoImpl &TLII, + const CodeGenOptions &CodeGenOpts) { + switch (CodeGenOpts.getScalarLib()) { + case CodeGenOptions::SCALAR_AMDLIBM: + TLII.addScalarFunctionsFromMathLib(TargetLibraryInfoImpl::SCALAR_AMDLIBM); + break; + case CodeGenOptions::Default_Scalar_Library: + break; + } +} + namespace { class EmitAssemblyHelper { @@ -1002,6 +1015,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( // preset TLI. std::unique_ptr<TargetLibraryInfoImpl> TLII( llvm::driver::createTLII(TargetTriple, CodeGenOpts.getVecLib())); + addScalarMathLibrary(*TLII, CodeGenOpts); FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); // Register all the basic analyses with the managers. @@ -1271,6 +1285,7 @@ void EmitAssemblyHelper::RunCodegenPipelineLegacy( // Add LibraryInfo. std::unique_ptr<TargetLibraryInfoImpl> TLII( llvm::driver::createTLII(TargetTriple, CodeGenOpts.getVecLib())); + addScalarMathLibrary(*TLII, CodeGenOpts); CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII)); const llvm::TargetOptions &Options = TM->Options; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 9e90994c178dd..934b504478a8c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5982,6 +5982,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->render(Args, CmdArgs); } + if (Arg *A = Args.getLastArg(options::OPT_fsclrlib)) { + StringRef Name = A->getValue(); + if (Name == "AMDLIBM") { + if (Triple.getArch() != llvm::Triple::x86 && + Triple.getArch() != llvm::Triple::x86_64) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Name << Triple.getArchName(); + } + A->render(Args, CmdArgs); + } + if (Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants, false)) CmdArgs.push_back("-fmerge-all-constants"); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 883296e43111b..2ca621ad1123a 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1145,6 +1145,14 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, Twine(PluginOptPrefix) + "-vector-library=" + OptVal.value())); } + // Pass scalar math library arguments to LTO. + if (Arg *ArgScalarLib = Args.getLastArg(options::OPT_fsclrlib)) { + StringRef Name = ArgScalarLib->getValue(); + if (Name == "AMDLIBM") + CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + + "-scalar-library=" + Name)); + } + // Try to pass driver level flags relevant to LTO code generation down to // the plugin. diff --git a/clang/test/CodeGen/X86/aocl-fast-scalar-calls.c b/clang/test/CodeGen/X86/aocl-fast-scalar-calls.c new file mode 100644 index 0000000000000..50a512ebc2a5e --- /dev/null +++ b/clang/test/CodeGen/X86/aocl-fast-scalar-calls.c @@ -0,0 +1,40 @@ +// Verify that the -fsclrlib=AMDLIBM driver flag, together with fast-math at -O3, +// rewrites scalar math library calls into their AMD AOCL fast-call equivalents +// for X86, and leaves them untouched without the flag. + +// REQUIRES: x86-registered-target + +// RUN: %clang --target=x86_64-unknown-linux-gnu -O3 -ffast-math \ +// RUN: -fsclrlib=AMDLIBM -S %s -o - | FileCheck %s --check-prefix=AMD +// RUN: %clang --target=x86_64-unknown-linux-gnu -O3 -ffast-math \ +// RUN: -S %s -o - | FileCheck %s --check-prefix=STD + +double tan(double); +double exp(double); +float tanf(float); +double cbrt(double); + +double call_tan(double x) { return tan(x) + x; } +// AMD-LABEL: call_tan: +// AMD: callq{{.*}}amd_fasttan +// STD-LABEL: call_tan: +// STD: callq{{.*}}tan + +double call_exp(double x) { return exp(x) + x; } +// AMD-LABEL: call_exp: +// AMD: callq{{.*}}amd_fastexp +// STD-LABEL: call_exp: +// STD: callq{{.*}}exp + +// Single-precision variant is rewritten too. +float call_tanf(float x) { return tanf(x) + x; } +// AMD-LABEL: call_tanf: +// AMD: callq{{.*}}amd_fasttanf +// STD-LABEL: call_tanf: +// STD: callq{{.*}}tanf + +// cbrt has no AOCL mapping and must stay even with the option enabled. +double call_cbrt(double x) { return cbrt(x) + x; } +// AMD-LABEL: call_cbrt: +// AMD-NOT: amd_fast +// AMD: callq{{.*}}cbrt diff --git a/llvm/include/llvm/Analysis/ScalarAOCLFuncs.def b/llvm/include/llvm/Analysis/ScalarAOCLFuncs.def new file mode 100644 index 0000000000000..906b1612afa5c --- /dev/null +++ b/llvm/include/llvm/Analysis/ScalarAOCLFuncs.def @@ -0,0 +1,80 @@ +//===-- ScalarAOCLFuncs.def - AMD scalar math library mappings --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This .def file creates a mapping from standard scalar math functions to +// their corresponding fast entry points in the AMD AOCL scalar math library. +// The lowering is only legal under fast-math semantics. +// +//===----------------------------------------------------------------------===// + +#if defined(TLI_DEFINE_SCALAR_AOCL_FUNCS) +#define TLI_DEFINE_SCALAR_AOCL_FUNC(SCAL, AOCLENTRY) {SCAL, AOCLENTRY}, + +TLI_DEFINE_SCALAR_AOCL_FUNC("acosf", "amd_fastacosf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__acosf_finite", "amd_fastacosf") +TLI_DEFINE_SCALAR_AOCL_FUNC("acos", "amd_fastacos") +TLI_DEFINE_SCALAR_AOCL_FUNC("__acos_finite", "amd_fastacos") + +TLI_DEFINE_SCALAR_AOCL_FUNC("asinf", "amd_fastasinf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__asinf_finite", "amd_fastasinf") +TLI_DEFINE_SCALAR_AOCL_FUNC("asin", "amd_fastasin") +TLI_DEFINE_SCALAR_AOCL_FUNC("__asin_finite", "amd_fastasin") + +TLI_DEFINE_SCALAR_AOCL_FUNC("atanf", "amd_fastatanf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__atanf_finite", "amd_fastatanf") +TLI_DEFINE_SCALAR_AOCL_FUNC("atan", "amd_fastatan") +TLI_DEFINE_SCALAR_AOCL_FUNC("__atan_finite", "amd_fastatan") + +TLI_DEFINE_SCALAR_AOCL_FUNC("cosf", "amd_fastcosf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__cosf_finite", "amd_fastcosf") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.cos.f32", "amd_fastcosf") +TLI_DEFINE_SCALAR_AOCL_FUNC("cos", "amd_fastcos") +TLI_DEFINE_SCALAR_AOCL_FUNC("__cos_finite", "amd_fastcos") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.cos.f64", "amd_fastcos") + +TLI_DEFINE_SCALAR_AOCL_FUNC("erff", "amd_fasterff") +TLI_DEFINE_SCALAR_AOCL_FUNC("__erff_finite", "amd_fasterff") +TLI_DEFINE_SCALAR_AOCL_FUNC("erf", "amd_fasterf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__erf_finite", "amd_fasterf") + +TLI_DEFINE_SCALAR_AOCL_FUNC("expf", "amd_fastexpf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__expf_finite", "amd_fastexpf") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.exp.f32", "amd_fastexpf") +TLI_DEFINE_SCALAR_AOCL_FUNC("exp", "amd_fastexp") +TLI_DEFINE_SCALAR_AOCL_FUNC("__exp_finite", "amd_fastexp") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.exp.f64", "amd_fastexp") + +TLI_DEFINE_SCALAR_AOCL_FUNC("logf", "amd_fastlogf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__logf_finite", "amd_fastlogf") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.log.f32", "amd_fastlogf") +TLI_DEFINE_SCALAR_AOCL_FUNC("log", "amd_fastlog") +TLI_DEFINE_SCALAR_AOCL_FUNC("__log_finite", "amd_fastlog") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.log.f64", "amd_fastlog") + +TLI_DEFINE_SCALAR_AOCL_FUNC("powf", "amd_fastpowf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__powf_finite", "amd_fastpowf") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.pow.f32", "amd_fastpowf") +TLI_DEFINE_SCALAR_AOCL_FUNC("pow", "amd_fastpow") +TLI_DEFINE_SCALAR_AOCL_FUNC("__pow_finite", "amd_fastpow") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.pow.f64", "amd_fastpow") + +TLI_DEFINE_SCALAR_AOCL_FUNC("sinf", "amd_fastsinf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__sinf_finite", "amd_fastsinf") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.sin.f32", "amd_fastsinf") +TLI_DEFINE_SCALAR_AOCL_FUNC("sin", "amd_fastsin") +TLI_DEFINE_SCALAR_AOCL_FUNC("__sin_finite", "amd_fastsin") +TLI_DEFINE_SCALAR_AOCL_FUNC("llvm.sin.f64", "amd_fastsin") + +TLI_DEFINE_SCALAR_AOCL_FUNC("tanf", "amd_fasttanf") +TLI_DEFINE_SCALAR_AOCL_FUNC("__tanf_finite", "amd_fasttanf") +TLI_DEFINE_SCALAR_AOCL_FUNC("tan", "amd_fasttan") +TLI_DEFINE_SCALAR_AOCL_FUNC("__tan_finite", "amd_fasttan") +#endif + +#undef TLI_DEFINE_SCALAR_AOCL_FUNCS +#undef TLI_DEFINE_SCALAR_AOCL_FUNC diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h index cd61b925ee5d7..4df61a4ec0791 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -109,12 +109,25 @@ class TargetLibraryInfoImpl { /// on VectorFnName rather than ScalarFnName. std::vector<VecDesc> ScalarDescs; + /// Mapping from a standard scalar math function name to its AMD scalar math + /// library fast-call equivalent (e.g. "tan" -> "amd_fasttan"). Populated when + /// an AMD scalar math library is selected. + DenseMap<StringRef, StringRef> LibScalarFunctions; + /// Return true if the function type FTy is valid for the library function /// F, regardless of whether the function is available. LLVM_ABI bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, const Module &M) const; public: + /// Scalar math library selection used for lowering standard scalar math + /// calls to faster, library-specific entry points. + enum ScalarLibrary { + Default_Scalar_Library, // Use default library. + SCALAR_AMDLIBM // AMD scalar math library. + }; + ScalarLibrary ScalarMathLib = Default_Scalar_Library; + TargetLibraryInfoImpl() = delete; LLVM_ABI explicit TargetLibraryInfoImpl( const Triple &T, VectorLibrary VecLib = VectorLibrary::NoLibrary); @@ -182,6 +195,20 @@ class TargetLibraryInfoImpl { addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib, const llvm::Triple &TargetTriple); + /// Populate the scalar math function mappings for the given scalar library + /// and record it as the selected scalar math library. + LLVM_ABI void addScalarFunctionsFromMathLib(enum ScalarLibrary ScalarLib); + + /// Return the library-specific scalar function name for \p F, or an empty + /// StringRef if no mapping exists. + LLVM_ABI StringRef getScalarFunctionFromMathLib(StringRef F) const; + + /// Return the currently selected scalar math library. + LLVM_ABI ScalarLibrary getScalarMathLib() const; + + /// Set the selected scalar math library. + LLVM_ABI void setScalarMathLib(enum ScalarLibrary ScalarLib); + /// Return true if the function F has a vector equivalent with vectorization /// factor VF. bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const { @@ -387,6 +414,12 @@ class TargetLibraryInfo { bool Masked) const { return Impl->getVectorMappingInfo(F, VF, Masked); } + StringRef getScalarFunctionFromMathLib(StringRef F) const { + return Impl->getScalarFunctionFromMathLib(F); + } + TargetLibraryInfoImpl::ScalarLibrary getScalarMathLib() const { + return Impl->getScalarMathLib(); + } /// Tests if the function is both available and a candidate for optimized code /// generation. diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 763c04b9b06f7..45a20b8398b4e 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -18,9 +18,18 @@ #include "llvm/IR/Module.h" #include "llvm/IR/SystemLibraries.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/CommandLine.h" #include "llvm/TargetParser/Triple.h" using namespace llvm; +static cl::opt<TargetLibraryInfoImpl::ScalarLibrary> ClScalarLibrary( + "scalar-library", cl::Hidden, cl::desc("Scalar functions library"), + cl::init(TargetLibraryInfoImpl::Default_Scalar_Library), + cl::values(clEnumValN(TargetLibraryInfoImpl::Default_Scalar_Library, "none", + "Use default library"), + clEnumValN(TargetLibraryInfoImpl::SCALAR_AMDLIBM, "AMDLIBM", + "AMD scalar math library"))); + #define GET_TARGET_LIBRARY_INFO_STRING_TABLE #include "llvm/Analysis/TargetLibraryInfo.inc" @@ -902,6 +911,7 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(const Triple &T, memset(AvailableArray, -1, sizeof(AvailableArray)); initialize(*this, T, StandardNamesStrTable, VecLib); + addScalarFunctionsFromMathLib(ClScalarLibrary); } TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI) @@ -913,6 +923,8 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI) memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); VectorDescs = TLI.VectorDescs; ScalarDescs = TLI.ScalarDescs; + LibScalarFunctions = TLI.LibScalarFunctions; + ScalarMathLib = TLI.ScalarMathLib; } TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI) @@ -926,6 +938,8 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI) AvailableArray); VectorDescs = TLI.VectorDescs; ScalarDescs = TLI.ScalarDescs; + LibScalarFunctions = TLI.LibScalarFunctions; + ScalarMathLib = TLI.ScalarMathLib; } TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoImpl &TLI) { @@ -936,6 +950,8 @@ TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoI ShouldSignExtI32Return = TLI.ShouldSignExtI32Return; SizeOfInt = TLI.SizeOfInt; memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); + LibScalarFunctions = TLI.LibScalarFunctions; + ScalarMathLib = TLI.ScalarMathLib; return *this; } @@ -948,6 +964,8 @@ TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(TargetLibraryInfoImpl && SizeOfInt = TLI.SizeOfInt; std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); + LibScalarFunctions = TLI.LibScalarFunctions; + ScalarMathLib = TLI.ScalarMathLib; return *this; } @@ -1397,6 +1415,40 @@ void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib( } } +void TargetLibraryInfoImpl::addScalarFunctionsFromMathLib( + enum ScalarLibrary ScalarLib) { + setScalarMathLib(ScalarLib); + switch (ScalarLib) { + case ScalarLibrary::SCALAR_AMDLIBM: { + const DenseMap<StringRef, StringRef> ScalarAOCLFuncs = { +#define TLI_DEFINE_SCALAR_AOCL_FUNCS +#include "llvm/Analysis/ScalarAOCLFuncs.def" + }; + LibScalarFunctions.insert(ScalarAOCLFuncs.begin(), ScalarAOCLFuncs.end()); + break; + } + case ScalarLibrary::Default_Scalar_Library: + break; + } +} + +void TargetLibraryInfoImpl::setScalarMathLib(enum ScalarLibrary ScalarLib) { + ScalarMathLib = ScalarLib; +} + +StringRef TargetLibraryInfoImpl::getScalarFunctionFromMathLib( + StringRef ScalarFnName) const { + auto Iter = LibScalarFunctions.find(ScalarFnName); + if (Iter == LibScalarFunctions.end()) + return StringRef(); + return Iter->second; +} + +TargetLibraryInfoImpl::ScalarLibrary +TargetLibraryInfoImpl::getScalarMathLib() const { + return ScalarMathLib; +} + bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName) const { funcName = sanitizeFunctionName(funcName); if (funcName.empty()) diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt index 62987bdbd1c2b..0c07e7c0c4b7f 100644 --- a/llvm/lib/Target/X86/CMakeLists.txt +++ b/llvm/lib/Target/X86/CMakeLists.txt @@ -56,6 +56,7 @@ set(sources X86FlagsCopyLowering.cpp X86FloatingPoint.cpp X86FrameLowering.cpp + X86GenScalarAmdFastCalls.cpp X86ISelDAGToDAG.cpp X86ISelLowering.cpp X86ISelLoweringCall.cpp diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h index eef4de389a7de..e790a602e0f08 100644 --- a/llvm/lib/Target/X86/X86.h +++ b/llvm/lib/Target/X86/X86.h @@ -483,6 +483,12 @@ class X86ArgumentStackSlotPass FunctionPass *createX86ArgumentStackSlotLegacyPass(); +/// This pass rewrites scalar math library calls (e.g. tan) to their AMD AOCL +/// fast-call equivalents (e.g. amd_fasttan) under fast-math semantics. +FunctionPass *createX86GenScalarAmdFastCallsPass(); +void initializeX86GenScalarAmdFastCallsPass(PassRegistry &); +extern char &X86GenScalarAmdFastCallsID; + void initializeCompressEVEXLegacyPass(PassRegistry &); void initializeX86FixupBWInstLegacyPass(PassRegistry &); void initializeFixupLEAsLegacyPass(PassRegistry &); diff --git a/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp b/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp new file mode 100644 index 0000000000000..85544a2436c73 --- /dev/null +++ b/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp @@ -0,0 +1,176 @@ +//===-- X86GenScalarAmdFastCalls.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This transformation converts standard scalar math function calls into their +// corresponding AMD AOCL scalar library entries for X86 targets, e.g.: +// tan ---> amd_fasttan +// Such lowering is only legal under fast-math semantics and when the AMD +// scalar math library has been selected (-scalar-library=AMDLIBM / +// -fsclrlib=AMDLIBM). +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "X86Subtarget.h" +#include "X86TargetMachine.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "x86-gen-scalar-aocl" + +using namespace llvm; + +namespace { + +class X86GenScalarAmdFastCalls : public MachineFunctionPass { +public: + static char ID; + + X86GenScalarAmdFastCalls() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &F) override; + + StringRef getPassName() const override { + return "X86 Generate Scalar AOCL Entries"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired<TargetLibraryInfoWrapperPass>(); + AU.addRequired<MachineOptimizationRemarkEmitterPass>(); + MachineFunctionPass::getAnalysisUsage(AU); + } + +private: + TargetLibraryInfo *TLI = nullptr; + MachineOptimizationRemarkEmitter *ORE = nullptr; + bool isCandidateSafeToLower(MachineInstr *MI) const; + bool createScalarAOCLCall(MachineInstr *MI) const; +}; + +} // namespace + +// Rewriting a scalar math call to its AOCL fast-call variant is only legal +// under fast-math semantics. By the time this late machine pass runs, the +// per-operation fast-math flags carried by the original call have already been +// lowered away, so we rely on the function-level fast-math attribute that the +// frontend sets under -ffast-math. Together with the explicit +// -scalar-library=AMDLIBM opt-in (checked in runOnMachineFunction) this gates +// the transformation. +bool X86GenScalarAmdFastCalls::isCandidateSafeToLower(MachineInstr *MI) const { + const Function &F = MI->getMF()->getFunction(); + return F.getFnAttribute("no-signed-zeros-fp-math").getValueAsBool(); +} + +/// Lowers scalar math functions to scalar AOCL functions. +/// e.g.: tan --> amd_fasttan +/// The callsite symbol is updated during lowering. +bool X86GenScalarAmdFastCalls::createScalarAOCLCall(MachineInstr *MI) const { + StringRef CallSiteName = ""; + StringRef LibScalarFnName = ""; + if (MI->getOperand(0).isSymbol()) { + CallSiteName = MI->getOperand(0).getSymbolName(); + } else if (MI->getOperand(0).isGlobal()) { + CallSiteName = MI->getOperand(0).getGlobal()->getName(); + } else { + return false; + } + + LLVM_DEBUG(dbgs() << "Candidate Func = " << CallSiteName << "\n";); + if (CallSiteName.empty()) { + return false; + } + LibScalarFnName = TLI->getScalarFunctionFromMathLib(CallSiteName); + if (LibScalarFnName.empty()) { + LLVM_DEBUG(dbgs() << "Fast call not supported\n";); + return false; + } + LLVM_DEBUG(dbgs() << "Candidate Func has fast Call variant available = " + << LibScalarFnName << "\n";); + MI->getOperand(0).ChangeToES(LibScalarFnName.data(), + MI->getOperand(0).getTargetFlags()); + + LLVM_DEBUG(dbgs() << "Successfully replaced with fastcall= " << LibScalarFnName + << "\n";); + + ORE->emit([&]() { + return MachineOptimizationRemark(DEBUG_TYPE, "Passed", MI->getDebugLoc(), + MI->getParent()) + << "Successfully replaced with fastcall= " << LibScalarFnName + << "\n"; + }); + return true; +} + +bool X86GenScalarAmdFastCalls::runOnMachineFunction(MachineFunction &MF) { + bool Changed = false; + + if (skipFunction(MF.getFunction())) + return Changed; + if (MF.getFunction().isDeclaration()) + return Changed; + SmallVector<MachineInstr *, 4> Callsites; + for (auto &BB : MF) { + for (auto &I : BB) { + if (I.isCall()) { + Callsites.push_back(&I); + } + } + } + + if (Callsites.empty()) { + return Changed; + } + + TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(MF.getFunction()); + ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); + if (!TLI) + return Changed; + + if (TLI->getScalarMathLib() != + TargetLibraryInfoImpl::ScalarLibrary::SCALAR_AMDLIBM) { + LLVM_DEBUG(dbgs() << "-scalar-library=AMDLIBM not used so bailing out.\n";); + return Changed; + } + + for (auto *CI : Callsites) { + if (isCandidateSafeToLower(CI)) { + LLVM_DEBUG(dbgs() << "Call Inst has fastMath flags\n";); + Changed |= createScalarAOCLCall(CI); + } else + LLVM_DEBUG(dbgs() << "Call Inst does not have fastMath flags\n";); + } + return Changed; +} + +char X86GenScalarAmdFastCalls::ID = 0; + +char &llvm::X86GenScalarAmdFastCallsID = X86GenScalarAmdFastCalls::ID; + +INITIALIZE_PASS_BEGIN(X86GenScalarAmdFastCalls, DEBUG_TYPE, + "Generate Scalar AMD Fast calls", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass) +INITIALIZE_PASS_END(X86GenScalarAmdFastCalls, DEBUG_TYPE, + "Generate Scalar AMD Fast calls", false, false) + +FunctionPass *llvm::createX86GenScalarAmdFastCallsPass() { + return new X86GenScalarAmdFastCalls(); +} diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index 932669b5cbac6..7bf01aac98a1b 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -110,6 +110,7 @@ extern "C" LLVM_C_ABI void LLVMInitializeX86Target() { initializeX86PreLegalizerCombinerLegacyPass(PR); initializeX86PostLegalizerCombinerLegacyPass(PR); initializeX86WinEHUnwindV3Pass(PR); + initializeX86GenScalarAmdFastCallsPass(PR); } static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { @@ -535,6 +536,10 @@ void X86PassConfig::addPreRegAlloc() { void X86PassConfig::addMachineSSAOptimization() { addPass(createX86DomainReassignmentLegacyPass()); + // Generate x86 target-specific function calls for scalar math functions + // that are available in the AMD AOCL library. + if (getOptLevel() == CodeGenOptLevel::Aggressive) + addPass(createX86GenScalarAmdFastCallsPass()); TargetPassConfig::addMachineSSAOptimization(); } diff --git a/llvm/test/CodeGen/X86/aocl-fast-scalar-calls-i686.ll b/llvm/test/CodeGen/X86/aocl-fast-scalar-calls-i686.ll new file mode 100644 index 0000000000000..8cc4b1d9b94e2 --- /dev/null +++ b/llvm/test/CodeGen/X86/aocl-fast-scalar-calls-i686.ll @@ -0,0 +1,31 @@ +; The AOCL fast-call lowering applies to 32-bit X86 (i686) as well as x86_64. + +; RUN: llc -mtriple=i686-unknown-linux-gnu -O3 -scalar-library=AMDLIBM < %s \ +; RUN: | FileCheck %s --check-prefix=AMD +; RUN: llc -mtriple=i686-unknown-linux-gnu -O3 < %s \ +; RUN: | FileCheck %s --check-prefix=STD + +declare double @tan(double) +declare float @expf(float) + +define double @call_tan(double %x) #0 { + %r = call double @tan(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_tan: +; AMD: calll{{.*}}amd_fasttan +; STD-LABEL: call_tan: +; STD: calll{{.*}}tan + +define float @call_expf(float %x) #0 { + %r = call float @expf(float %x) + %a = fadd float %r, %x + ret float %a +} +; AMD-LABEL: call_expf: +; AMD: calll{{.*}}amd_fastexpf +; STD-LABEL: call_expf: +; STD: calll{{.*}}expf + +attributes #0 = { "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" } diff --git a/llvm/test/CodeGen/X86/aocl-fast-scalar-calls-mappings.ll b/llvm/test/CodeGen/X86/aocl-fast-scalar-calls-mappings.ll new file mode 100644 index 0000000000000..b98704409a0f3 --- /dev/null +++ b/llvm/test/CodeGen/X86/aocl-fast-scalar-calls-mappings.ll @@ -0,0 +1,124 @@ +; Exercises the scalar->AOCL fast-call name mapping under fast-math at -O3 with +; -scalar-library=AMDLIBM on X86: float variants, *_finite aliases and +; inverse-trig functions are rewritten, while math calls with no AOCL mapping +; (e.g. cbrt) are left untouched. + +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O3 -scalar-library=AMDLIBM < %s \ +; RUN: | FileCheck %s --check-prefix=AMD +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O3 < %s \ +; RUN: | FileCheck %s --check-prefix=STD + +declare float @tanf(float) +declare float @powf(float, float) +declare double @acos(double) +declare float @acosf(float) +declare double @atan(double) +declare double @cos(double) +declare float @sinf(float) +declare double @erf(double) +declare double @__exp_finite(double) +declare double @pow(double, double) +declare double @cbrt(double) + +; Single-precision variant: tanf -> amd_fasttanf +define float @call_tanf(float %x) #0 { + %r = call float @tanf(float %x) + %a = fadd float %r, %x + ret float %a +} +; AMD-LABEL: call_tanf: +; AMD: callq{{.*}}amd_fasttanf +; STD-LABEL: call_tanf: +; STD: callq{{.*}}tanf + +; Single-precision, two-argument variant: powf -> amd_fastpowf +define float @call_powf(float %x, float %y) #0 { + %r = call float @powf(float %x, float %y) + %a = fadd float %r, %x + ret float %a +} +; AMD-LABEL: call_powf: +; AMD: callq{{.*}}amd_fastpowf + +; Inverse-trigonometric functions. +define double @call_acos(double %x) #0 { + %r = call double @acos(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_acos: +; AMD: callq{{.*}}amd_fastacos + +define double @call_atan(double %x) #0 { + %r = call double @atan(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_atan: +; AMD: callq{{.*}}amd_fastatan + +; Single-precision inverse-trig: acosf -> amd_fastacosf +define float @call_acosf(float %x) #0 { + %r = call float @acosf(float %x) + %a = fadd float %r, %x + ret float %a +} +; AMD-LABEL: call_acosf: +; AMD: callq{{.*}}amd_fastacosf + +; cos(double) -> amd_fastcos +define double @call_cos(double %x) #0 { + %r = call double @cos(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_cos: +; AMD: callq{{.*}}amd_fastcos + +; sinf -> amd_fastsinf +define float @call_sinf(float %x) #0 { + %r = call float @sinf(float %x) + %a = fadd float %r, %x + ret float %a +} +; AMD-LABEL: call_sinf: +; AMD: callq{{.*}}amd_fastsinf + +; erf(double) -> amd_fasterf +define double @call_erf(double %x) #0 { + %r = call double @erf(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_erf: +; AMD: callq{{.*}}amd_fasterf + +; pow(double) -> amd_fastpow +define double @call_pow(double %x, double %y) #0 { + %r = call double @pow(double %x, double %y) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_pow: +; AMD: callq{{.*}}amd_fastpow + +; A *_finite alias maps to the same fast entry as the base function. +define double @call_exp_finite(double %x) #0 { + %r = call double @__exp_finite(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_exp_finite: +; AMD: callq{{.*}}amd_fastexp + +; cbrt has no AOCL mapping and must not be rewritten. +define double @call_cbrt_unmapped(double %x) #0 { + %r = call double @cbrt(double %x) + %a = fadd double %r, %x + ret double %a +} +; AMD-LABEL: call_cbrt_unmapped: +; AMD-NOT: amd_fast +; AMD: callq{{.*}}cbrt + +attributes #0 = { "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" } diff --git a/llvm/test/CodeGen/X86/aocl-fast-scalar-calls.ll b/llvm/test/CodeGen/X86/aocl-fast-scalar-calls.ll new file mode 100644 index 0000000000000..96824158fe853 --- /dev/null +++ b/llvm/test/CodeGen/X86/aocl-fast-scalar-calls.ll @@ -0,0 +1,63 @@ +; Verify that, under fast-math at -O3 with -scalar-library=AMDLIBM, scalar math +; library calls are rewritten to their AMD AOCL fast-call equivalents on X86, +; and that they are left untouched without the option. + +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O3 -scalar-library=AMDLIBM < %s \ +; RUN: | FileCheck %s --check-prefix=AMD +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O3 < %s \ +; RUN: | FileCheck %s --check-prefix=STD + +declare double @tan(double) +declare double @exp(double) +declare double @log(double) + +define double @call_tan(double %x) #0 { +entry: + %r = call double @tan(double %x) + %a = fadd double %r, %x + ret double %a +} + +; AMD-LABEL: call_tan: +; AMD: callq{{.*}}amd_fasttan +; STD-LABEL: call_tan: +; STD: callq{{.*}}tan + +define double @call_exp(double %x) #0 { +entry: + %r = call double @exp(double %x) + %a = fadd double %r, %x + ret double %a +} + +; AMD-LABEL: call_exp: +; AMD: callq{{.*}}amd_fastexp +; STD-LABEL: call_exp: +; STD: callq{{.*}}exp + +define double @call_log(double %x) #0 { +entry: + %r = call double @log(double %x) + %a = fadd double %r, %x + ret double %a +} + +; AMD-LABEL: call_log: +; AMD: callq{{.*}}amd_fastlog +; STD-LABEL: call_log: +; STD: callq{{.*}}log + +; Without the fast-math attributes the call must not be rewritten even when the +; AMD scalar library is selected. +define double @call_tan_no_fastmath(double %x) { +entry: + %r = call double @tan(double %x) + %a = fadd double %r, %x + ret double %a +} + +; AMD-LABEL: call_tan_no_fastmath: +; AMD-NOT: amd_fasttan +; AMD: callq{{.*}}tan + +attributes #0 = { "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" } diff --git a/llvm/test/CodeGen/X86/veclib-llvm.sincos.s b/llvm/test/CodeGen/X86/veclib-llvm.sincos.s new file mode 100644 index 0000000000000..df1edb99dcd53 --- /dev/null +++ b/llvm/test/CodeGen/X86/veclib-llvm.sincos.s @@ -0,0 +1,258 @@ + .att_syntax + .file "veclib-llvm.sincos.ll" + .text + .globl test_sincos_v4f32 # -- Begin function test_sincos_v4f32 + .p2align 4 + .type test_sincos_v4f32,@function +test_sincos_v4f32: # @test_sincos_v4f32 + .cfi_startproc +# %bb.0: + pushq %rbx + .cfi_def_cfa_offset 16 + subq $16, %rsp + .cfi_def_cfa_offset 32 + .cfi_offset %rbx, -16 + movq %rsi, %rbx + movq %rsp, %rsi + callq amd_vrs4_sincosf@PLT + movaps (%rsp), %xmm0 + movaps %xmm0, (%rbx) + addq $16, %rsp + .cfi_def_cfa_offset 16 + popq %rbx + .cfi_def_cfa_offset 8 + retq +.Lfunc_end0: + .size test_sincos_v4f32, .Lfunc_end0-test_sincos_v4f32 + .cfi_endproc + # -- End function + .globl test_sincos_v8f32 # -- Begin function test_sincos_v8f32 + .p2align 4 + .type test_sincos_v8f32,@function +test_sincos_v8f32: # @test_sincos_v8f32 + .cfi_startproc +# %bb.0: + pushq %r14 + .cfi_def_cfa_offset 16 + pushq %rbx + .cfi_def_cfa_offset 24 + subq $56, %rsp + .cfi_def_cfa_offset 80 + .cfi_offset %rbx, -24 + .cfi_offset %r14, -16 + movq %rsi, %rbx + movq %rdi, %r14 + movaps %xmm0, (%rsp) # 16-byte Spill + addq $16, %rdi + leaq 16(%rsp), %rsi + movaps %xmm1, %xmm0 + callq amd_vrs4_sincosf@PLT + leaq 32(%rsp), %rsi + movaps (%rsp), %xmm0 # 16-byte Reload + movq %r14, %rdi + callq amd_vrs4_sincosf@PLT + movaps 16(%rsp), %xmm0 + movaps 32(%rsp), %xmm1 + movaps %xmm1, (%rbx) + movaps %xmm0, 16(%rbx) + addq $56, %rsp + .cfi_def_cfa_offset 24 + popq %rbx + .cfi_def_cfa_offset 16 + popq %r14 + .cfi_def_cfa_offset 8 + retq +.Lfunc_end1: + .size test_sincos_v8f32, .Lfunc_end1-test_sincos_v8f32 + .cfi_endproc + # -- End function + .globl test_sincos_v16f32 # -- Begin function test_sincos_v16f32 + .p2align 4 + .type test_sincos_v16f32,@function +test_sincos_v16f32: # @test_sincos_v16f32 + .cfi_startproc +# %bb.0: + pushq %r14 + .cfi_def_cfa_offset 16 + pushq %rbx + .cfi_def_cfa_offset 24 + subq $120, %rsp + .cfi_def_cfa_offset 144 + .cfi_offset %rbx, -24 + .cfi_offset %r14, -16 + movq %rsi, %rbx + movq %rdi, %r14 + movaps %xmm3, (%rsp) # 16-byte Spill + movaps %xmm2, 16(%rsp) # 16-byte Spill + movaps %xmm0, 32(%rsp) # 16-byte Spill + addq $16, %rdi + leaq 80(%rsp), %rsi + movaps %xmm1, %xmm0 + callq amd_vrs4_sincosf@PLT + leaq 48(%r14), %rdi + leaq 48(%rsp), %rsi + movaps (%rsp), %xmm0 # 16-byte Reload + callq amd_vrs4_sincosf@PLT + leaq 32(%r14), %rdi + leaq 64(%rsp), %rsi + movaps 16(%rsp), %xmm0 # 16-byte Reload + callq amd_vrs4_sincosf@PLT + leaq 96(%rsp), %rsi + movaps 32(%rsp), %xmm0 # 16-byte Reload + movq %r14, %rdi + callq amd_vrs4_sincosf@PLT + movaps 80(%rsp), %xmm0 + movaps 48(%rsp), %xmm1 + movaps 64(%rsp), %xmm2 + movaps 96(%rsp), %xmm3 + movaps %xmm3, (%rbx) + movaps %xmm2, 32(%rbx) + movaps %xmm1, 48(%rbx) + movaps %xmm0, 16(%rbx) + addq $120, %rsp + .cfi_def_cfa_offset 24 + popq %rbx + .cfi_def_cfa_offset 16 + popq %r14 + .cfi_def_cfa_offset 8 + retq +.Lfunc_end2: + .size test_sincos_v16f32, .Lfunc_end2-test_sincos_v16f32 + .cfi_endproc + # -- End function + .globl test_sincos_v2f64 # -- Begin function test_sincos_v2f64 + .p2align 4 + .type test_sincos_v2f64,@function +test_sincos_v2f64: # @test_sincos_v2f64 + .cfi_startproc +# %bb.0: + pushq %rbx + .cfi_def_cfa_offset 16 + subq $16, %rsp + .cfi_def_cfa_offset 32 + .cfi_offset %rbx, -16 + movq %rsi, %rbx + movq %rsp, %rsi + callq amd_vrd2_sincos@PLT + movaps (%rsp), %xmm0 + movaps %xmm0, (%rbx) + addq $16, %rsp + .cfi_def_cfa_offset 16 + popq %rbx + .cfi_def_cfa_offset 8 + retq +.Lfunc_end3: + .size test_sincos_v2f64, .Lfunc_end3-test_sincos_v2f64 + .cfi_endproc + # -- End function + .globl test_sincos_v4f64 # -- Begin function test_sincos_v4f64 + .p2align 4 + .type test_sincos_v4f64,@function +test_sincos_v4f64: # @test_sincos_v4f64 + .cfi_startproc +# %bb.0: + pushq %r14 + .cfi_def_cfa_offset 16 + pushq %rbx + .cfi_def_cfa_offset 24 + subq $56, %rsp + .cfi_def_cfa_offset 80 + .cfi_offset %rbx, -24 + .cfi_offset %r14, -16 + movq %rsi, %rbx + movq %rdi, %r14 + movaps %xmm0, (%rsp) # 16-byte Spill + addq $16, %rdi + leaq 16(%rsp), %rsi + movaps %xmm1, %xmm0 + callq amd_vrd2_sincos@PLT + leaq 32(%rsp), %rsi + movaps (%rsp), %xmm0 # 16-byte Reload + movq %r14, %rdi + callq amd_vrd2_sincos@PLT + movaps 16(%rsp), %xmm0 + movaps 32(%rsp), %xmm1 + movaps %xmm1, (%rbx) + movaps %xmm0, 16(%rbx) + addq $56, %rsp + .cfi_def_cfa_offset 24 + popq %rbx + .cfi_def_cfa_offset 16 + popq %r14 + .cfi_def_cfa_offset 8 + retq +.Lfunc_end4: + .size test_sincos_v4f64, .Lfunc_end4-test_sincos_v4f64 + .cfi_endproc + # -- End function + .globl test_sincos_v8f64 # -- Begin function test_sincos_v8f64 + .p2align 4 + .type test_sincos_v8f64,@function +test_sincos_v8f64: # @test_sincos_v8f64 + .cfi_startproc +# %bb.0: + pushq %r14 + .cfi_def_cfa_offset 16 + pushq %rbx + .cfi_def_cfa_offset 24 + subq $120, %rsp + .cfi_def_cfa_offset 144 + .cfi_offset %rbx, -24 + .cfi_offset %r14, -16 + movq %rsi, %rbx + movq %rdi, %r14 + movaps %xmm3, (%rsp) # 16-byte Spill + movaps %xmm2, 16(%rsp) # 16-byte Spill + movaps %xmm0, 32(%rsp) # 16-byte Spill + addq $16, %rdi + leaq 80(%rsp), %rsi + movaps %xmm1, %xmm0 + callq amd_vrd2_sincos@PLT + leaq 48(%r14), %rdi + leaq 48(%rsp), %rsi + movaps (%rsp), %xmm0 # 16-byte Reload + callq amd_vrd2_sincos@PLT + leaq 32(%r14), %rdi + leaq 64(%rsp), %rsi + movaps 16(%rsp), %xmm0 # 16-byte Reload + callq amd_vrd2_sincos@PLT + leaq 96(%rsp), %rsi + movaps 32(%rsp), %xmm0 # 16-byte Reload + movq %r14, %rdi + callq amd_vrd2_sincos@PLT + movaps 80(%rsp), %xmm0 + movaps 48(%rsp), %xmm1 + movaps 64(%rsp), %xmm2 + movaps 96(%rsp), %xmm3 + movaps %xmm3, (%rbx) + movaps %xmm2, 32(%rbx) + movaps %xmm1, 48(%rbx) + movaps %xmm0, 16(%rbx) + addq $120, %rsp + .cfi_def_cfa_offset 24 + popq %rbx + .cfi_def_cfa_offset 16 + popq %r14 + .cfi_def_cfa_offset 8 + retq +.Lfunc_end5: + .size test_sincos_v8f64, .Lfunc_end5-test_sincos_v8f64 + .cfi_endproc + # -- End function + .globl test_sincos_v4f32_void # -- Begin function test_sincos_v4f32_void + .p2align 4 + .type test_sincos_v4f32_void,@function +test_sincos_v4f32_void: # @test_sincos_v4f32_void + .cfi_startproc +# %bb.0: + pushq %rax + .cfi_def_cfa_offset 16 + callq sincosf@PLT + popq %rax + .cfi_def_cfa_offset 8 + retq +.Lfunc_end6: + .size test_sincos_v4f32_void, .Lfunc_end6-test_sincos_v4f32_void + .cfi_endproc + # -- End function + .section ".note.GNU-stack","",@progbits >From 7586808a60e4782bb69e27e291f41e936fb27417 Mon Sep 17 00:00:00 2001 From: Rohit Aggarwal <[email protected]> Date: Mon, 3 Aug 2026 19:29:32 +0530 Subject: [PATCH 2/3] Fix the formatting issue. --- llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp b/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp index 85544a2436c73..0a4b1b7b32cd2 100644 --- a/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp +++ b/llvm/lib/Target/X86/X86GenScalarAmdFastCalls.cpp @@ -107,8 +107,8 @@ bool X86GenScalarAmdFastCalls::createScalarAOCLCall(MachineInstr *MI) const { MI->getOperand(0).ChangeToES(LibScalarFnName.data(), MI->getOperand(0).getTargetFlags()); - LLVM_DEBUG(dbgs() << "Successfully replaced with fastcall= " << LibScalarFnName - << "\n";); + LLVM_DEBUG(dbgs() << "Successfully replaced with fastcall= " + << LibScalarFnName << "\n";); ORE->emit([&]() { return MachineOptimizationRemark(DEBUG_TYPE, "Passed", MI->getDebugLoc(), >From 60a57f68344f6001583eb1d9201f5fe660877983 Mon Sep 17 00:00:00 2001 From: Rohit Aggarwal <[email protected]> Date: Tue, 4 Aug 2026 14:05:23 +0530 Subject: [PATCH 3/3] Fix the test cases failure --- llvm/test/CodeGen/X86/opt-pipeline.ll | 5 +- llvm/test/CodeGen/X86/veclib-llvm.sincos.s | 258 --------------------- 2 files changed, 4 insertions(+), 259 deletions(-) delete mode 100644 llvm/test/CodeGen/X86/veclib-llvm.sincos.s diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll index 896515909cf10..acc5c72d48c6e 100644 --- a/llvm/test/CodeGen/X86/opt-pipeline.ll +++ b/llvm/test/CodeGen/X86/opt-pipeline.ll @@ -5,7 +5,7 @@ ; RUN: llc -mtriple=x86_64-- -O2 -debug-pass=Structure < %s -o /dev/null 2>&1 \ ; RUN: | grep -v 'Verify generated machine code' | FileCheck %s ; RUN: llc -mtriple=x86_64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 \ -; RUN: | grep -v 'Verify generated machine code' | FileCheck %s +; RUN: | grep -v 'Verify generated machine code' | FileCheck %s --check-prefixes=CHECK,O3 ; RUN: llc -mtriple=x86_64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 \ ; RUN: | FileCheck %s --check-prefix=FPM @@ -97,6 +97,9 @@ ; CHECK-NEXT: Finalize ISel and expand pseudo-instructions ; CHECK-NEXT: X86 Domain Reassignment Pass ; CHECK-NEXT: Lazy Machine Block Frequency Analysis +; O3-NEXT: Machine Optimization Remark Emitter +; O3-NEXT: X86 Generate Scalar AOCL Entries +; O3-NEXT: Lazy Machine Block Frequency Analysis ; CHECK-NEXT: Early Tail Duplication ; CHECK-NEXT: Optimize machine instruction PHIs ; CHECK-NEXT: Slot index numbering diff --git a/llvm/test/CodeGen/X86/veclib-llvm.sincos.s b/llvm/test/CodeGen/X86/veclib-llvm.sincos.s deleted file mode 100644 index df1edb99dcd53..0000000000000 --- a/llvm/test/CodeGen/X86/veclib-llvm.sincos.s +++ /dev/null @@ -1,258 +0,0 @@ - .att_syntax - .file "veclib-llvm.sincos.ll" - .text - .globl test_sincos_v4f32 # -- Begin function test_sincos_v4f32 - .p2align 4 - .type test_sincos_v4f32,@function -test_sincos_v4f32: # @test_sincos_v4f32 - .cfi_startproc -# %bb.0: - pushq %rbx - .cfi_def_cfa_offset 16 - subq $16, %rsp - .cfi_def_cfa_offset 32 - .cfi_offset %rbx, -16 - movq %rsi, %rbx - movq %rsp, %rsi - callq amd_vrs4_sincosf@PLT - movaps (%rsp), %xmm0 - movaps %xmm0, (%rbx) - addq $16, %rsp - .cfi_def_cfa_offset 16 - popq %rbx - .cfi_def_cfa_offset 8 - retq -.Lfunc_end0: - .size test_sincos_v4f32, .Lfunc_end0-test_sincos_v4f32 - .cfi_endproc - # -- End function - .globl test_sincos_v8f32 # -- Begin function test_sincos_v8f32 - .p2align 4 - .type test_sincos_v8f32,@function -test_sincos_v8f32: # @test_sincos_v8f32 - .cfi_startproc -# %bb.0: - pushq %r14 - .cfi_def_cfa_offset 16 - pushq %rbx - .cfi_def_cfa_offset 24 - subq $56, %rsp - .cfi_def_cfa_offset 80 - .cfi_offset %rbx, -24 - .cfi_offset %r14, -16 - movq %rsi, %rbx - movq %rdi, %r14 - movaps %xmm0, (%rsp) # 16-byte Spill - addq $16, %rdi - leaq 16(%rsp), %rsi - movaps %xmm1, %xmm0 - callq amd_vrs4_sincosf@PLT - leaq 32(%rsp), %rsi - movaps (%rsp), %xmm0 # 16-byte Reload - movq %r14, %rdi - callq amd_vrs4_sincosf@PLT - movaps 16(%rsp), %xmm0 - movaps 32(%rsp), %xmm1 - movaps %xmm1, (%rbx) - movaps %xmm0, 16(%rbx) - addq $56, %rsp - .cfi_def_cfa_offset 24 - popq %rbx - .cfi_def_cfa_offset 16 - popq %r14 - .cfi_def_cfa_offset 8 - retq -.Lfunc_end1: - .size test_sincos_v8f32, .Lfunc_end1-test_sincos_v8f32 - .cfi_endproc - # -- End function - .globl test_sincos_v16f32 # -- Begin function test_sincos_v16f32 - .p2align 4 - .type test_sincos_v16f32,@function -test_sincos_v16f32: # @test_sincos_v16f32 - .cfi_startproc -# %bb.0: - pushq %r14 - .cfi_def_cfa_offset 16 - pushq %rbx - .cfi_def_cfa_offset 24 - subq $120, %rsp - .cfi_def_cfa_offset 144 - .cfi_offset %rbx, -24 - .cfi_offset %r14, -16 - movq %rsi, %rbx - movq %rdi, %r14 - movaps %xmm3, (%rsp) # 16-byte Spill - movaps %xmm2, 16(%rsp) # 16-byte Spill - movaps %xmm0, 32(%rsp) # 16-byte Spill - addq $16, %rdi - leaq 80(%rsp), %rsi - movaps %xmm1, %xmm0 - callq amd_vrs4_sincosf@PLT - leaq 48(%r14), %rdi - leaq 48(%rsp), %rsi - movaps (%rsp), %xmm0 # 16-byte Reload - callq amd_vrs4_sincosf@PLT - leaq 32(%r14), %rdi - leaq 64(%rsp), %rsi - movaps 16(%rsp), %xmm0 # 16-byte Reload - callq amd_vrs4_sincosf@PLT - leaq 96(%rsp), %rsi - movaps 32(%rsp), %xmm0 # 16-byte Reload - movq %r14, %rdi - callq amd_vrs4_sincosf@PLT - movaps 80(%rsp), %xmm0 - movaps 48(%rsp), %xmm1 - movaps 64(%rsp), %xmm2 - movaps 96(%rsp), %xmm3 - movaps %xmm3, (%rbx) - movaps %xmm2, 32(%rbx) - movaps %xmm1, 48(%rbx) - movaps %xmm0, 16(%rbx) - addq $120, %rsp - .cfi_def_cfa_offset 24 - popq %rbx - .cfi_def_cfa_offset 16 - popq %r14 - .cfi_def_cfa_offset 8 - retq -.Lfunc_end2: - .size test_sincos_v16f32, .Lfunc_end2-test_sincos_v16f32 - .cfi_endproc - # -- End function - .globl test_sincos_v2f64 # -- Begin function test_sincos_v2f64 - .p2align 4 - .type test_sincos_v2f64,@function -test_sincos_v2f64: # @test_sincos_v2f64 - .cfi_startproc -# %bb.0: - pushq %rbx - .cfi_def_cfa_offset 16 - subq $16, %rsp - .cfi_def_cfa_offset 32 - .cfi_offset %rbx, -16 - movq %rsi, %rbx - movq %rsp, %rsi - callq amd_vrd2_sincos@PLT - movaps (%rsp), %xmm0 - movaps %xmm0, (%rbx) - addq $16, %rsp - .cfi_def_cfa_offset 16 - popq %rbx - .cfi_def_cfa_offset 8 - retq -.Lfunc_end3: - .size test_sincos_v2f64, .Lfunc_end3-test_sincos_v2f64 - .cfi_endproc - # -- End function - .globl test_sincos_v4f64 # -- Begin function test_sincos_v4f64 - .p2align 4 - .type test_sincos_v4f64,@function -test_sincos_v4f64: # @test_sincos_v4f64 - .cfi_startproc -# %bb.0: - pushq %r14 - .cfi_def_cfa_offset 16 - pushq %rbx - .cfi_def_cfa_offset 24 - subq $56, %rsp - .cfi_def_cfa_offset 80 - .cfi_offset %rbx, -24 - .cfi_offset %r14, -16 - movq %rsi, %rbx - movq %rdi, %r14 - movaps %xmm0, (%rsp) # 16-byte Spill - addq $16, %rdi - leaq 16(%rsp), %rsi - movaps %xmm1, %xmm0 - callq amd_vrd2_sincos@PLT - leaq 32(%rsp), %rsi - movaps (%rsp), %xmm0 # 16-byte Reload - movq %r14, %rdi - callq amd_vrd2_sincos@PLT - movaps 16(%rsp), %xmm0 - movaps 32(%rsp), %xmm1 - movaps %xmm1, (%rbx) - movaps %xmm0, 16(%rbx) - addq $56, %rsp - .cfi_def_cfa_offset 24 - popq %rbx - .cfi_def_cfa_offset 16 - popq %r14 - .cfi_def_cfa_offset 8 - retq -.Lfunc_end4: - .size test_sincos_v4f64, .Lfunc_end4-test_sincos_v4f64 - .cfi_endproc - # -- End function - .globl test_sincos_v8f64 # -- Begin function test_sincos_v8f64 - .p2align 4 - .type test_sincos_v8f64,@function -test_sincos_v8f64: # @test_sincos_v8f64 - .cfi_startproc -# %bb.0: - pushq %r14 - .cfi_def_cfa_offset 16 - pushq %rbx - .cfi_def_cfa_offset 24 - subq $120, %rsp - .cfi_def_cfa_offset 144 - .cfi_offset %rbx, -24 - .cfi_offset %r14, -16 - movq %rsi, %rbx - movq %rdi, %r14 - movaps %xmm3, (%rsp) # 16-byte Spill - movaps %xmm2, 16(%rsp) # 16-byte Spill - movaps %xmm0, 32(%rsp) # 16-byte Spill - addq $16, %rdi - leaq 80(%rsp), %rsi - movaps %xmm1, %xmm0 - callq amd_vrd2_sincos@PLT - leaq 48(%r14), %rdi - leaq 48(%rsp), %rsi - movaps (%rsp), %xmm0 # 16-byte Reload - callq amd_vrd2_sincos@PLT - leaq 32(%r14), %rdi - leaq 64(%rsp), %rsi - movaps 16(%rsp), %xmm0 # 16-byte Reload - callq amd_vrd2_sincos@PLT - leaq 96(%rsp), %rsi - movaps 32(%rsp), %xmm0 # 16-byte Reload - movq %r14, %rdi - callq amd_vrd2_sincos@PLT - movaps 80(%rsp), %xmm0 - movaps 48(%rsp), %xmm1 - movaps 64(%rsp), %xmm2 - movaps 96(%rsp), %xmm3 - movaps %xmm3, (%rbx) - movaps %xmm2, 32(%rbx) - movaps %xmm1, 48(%rbx) - movaps %xmm0, 16(%rbx) - addq $120, %rsp - .cfi_def_cfa_offset 24 - popq %rbx - .cfi_def_cfa_offset 16 - popq %r14 - .cfi_def_cfa_offset 8 - retq -.Lfunc_end5: - .size test_sincos_v8f64, .Lfunc_end5-test_sincos_v8f64 - .cfi_endproc - # -- End function - .globl test_sincos_v4f32_void # -- Begin function test_sincos_v4f32_void - .p2align 4 - .type test_sincos_v4f32_void,@function -test_sincos_v4f32_void: # @test_sincos_v4f32_void - .cfi_startproc -# %bb.0: - pushq %rax - .cfi_def_cfa_offset 16 - callq sincosf@PLT - popq %rax - .cfi_def_cfa_offset 8 - retq -.Lfunc_end6: - .size test_sincos_v4f32_void, .Lfunc_end6-test_sincos_v4f32_void - .cfi_endproc - # -- End function - .section ".note.GNU-stack","",@progbits _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
