[Mesa-dev] [PATCH] radv: using tls to store llvm related info and speed up compiles (v8)

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Mon Jul 9 21:07:59 UTC 2018


On Mon, Jul 9, 2018 at 11:03 PM, Dave Airlie <airlied at gmail.com> wrote:
> On 9 July 2018 at 05:58, Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl> wrote:
>> On Thu, Jul 5, 2018 at 2:03 AM, Dave Airlie <airlied at gmail.com> wrote:
>>> From: Dave Airlie <airlied at redhat.com>
>>>
>>> This uses the common compiler passes abstraction to help radv
>>> avoid fixed cost compiler overheads. This uses a linked list per
>>> thread stored in thread local storage, with an entry in the list
>>> for each target machine.
>>>
>>> This should remove all the fixed overheads setup costs of creating
>>> the pass manager each time.
>>>
>>> This takes a demo app time to compile the radv meta shaders on nocache
>>> and exit from 1.7s to 1s. It also has been reported to take the startup
>>> time of uncached shaders on RoTR from 12m24s to 11m35s (Alex)
>>>
>>> v2: fix llvm6 build, inline emit function, handle multiple targets
>>> in one thread
>>> v3: rebase and port onto new structure
>>> v4: rename some vars (Bas)
>>> v5: drag all code into radv for now, we can refactor it out later
>>> for radeonsi if we make it shareable
>>> v6: use a bit more C++ in the wrapper
>>> v7: logic bugs fixed so it actually runs again.
>>> v8: rebase on top of radeonsi changes.
>>> ---
>>>  src/amd/vulkan/Makefile.sources     |   2 +
>>>  src/amd/vulkan/meson.build          |   2 +
>>>  src/amd/vulkan/radv_debug.h         |   1 +
>>>  src/amd/vulkan/radv_device.c        |   1 +
>>>  src/amd/vulkan/radv_llvm_helper.cpp | 148 ++++++++++++++++++++++++++++
>>>  src/amd/vulkan/radv_nir_to_llvm.c   |  27 +----
>>>  src/amd/vulkan/radv_shader.c        |  10 +-
>>>  src/amd/vulkan/radv_shader_helper.h |  44 +++++++++
>>>  8 files changed, 207 insertions(+), 28 deletions(-)
>>>  create mode 100644 src/amd/vulkan/radv_llvm_helper.cpp
>>>  create mode 100644 src/amd/vulkan/radv_shader_helper.h
>>>
>>> diff --git a/src/amd/vulkan/Makefile.sources b/src/amd/vulkan/Makefile.sources
>>> index 70d56e88cb3..152fdd7cb71 100644
>>> --- a/src/amd/vulkan/Makefile.sources
>>> +++ b/src/amd/vulkan/Makefile.sources
>>> @@ -54,6 +54,7 @@ VULKAN_FILES := \
>>>         radv_meta_resolve_cs.c \
>>>         radv_meta_resolve_fs.c \
>>>         radv_nir_to_llvm.c \
>>> +       radv_llvm_helper.cpp \
>>>         radv_pass.c \
>>>         radv_pipeline.c \
>>>         radv_pipeline_cache.c \
>>> @@ -62,6 +63,7 @@ VULKAN_FILES := \
>>>         radv_shader.c \
>>>         radv_shader_info.c \
>>>         radv_shader.h \
>>> +       radv_shader_helper.h \
>>>         radv_query.c \
>>>         radv_util.c \
>>>         radv_util.h \
>>> diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build
>>> index 22857926fa1..9f2842182e7 100644
>>> --- a/src/amd/vulkan/meson.build
>>> +++ b/src/amd/vulkan/meson.build
>>> @@ -67,6 +67,7 @@ libradv_files = files(
>>>    'radv_descriptor_set.h',
>>>    'radv_formats.c',
>>>    'radv_image.c',
>>> +  'radv_llvm_helper.cpp',
>>>    'radv_meta.c',
>>>    'radv_meta.h',
>>>    'radv_meta_blit.c',
>>> @@ -88,6 +89,7 @@ libradv_files = files(
>>>    'radv_radeon_winsys.h',
>>>    'radv_shader.c',
>>>    'radv_shader.h',
>>> +  'radv_shader_helper.h',
>>>    'radv_shader_info.c',
>>>    'radv_query.c',
>>>    'radv_util.c',
>>> diff --git a/src/amd/vulkan/radv_debug.h b/src/amd/vulkan/radv_debug.h
>>> index f1b0dc26a63..9fe4c3b7404 100644
>>> --- a/src/amd/vulkan/radv_debug.h
>>> +++ b/src/amd/vulkan/radv_debug.h
>>> @@ -49,6 +49,7 @@ enum {
>>>         RADV_DEBUG_ERRORS            = 0x80000,
>>>         RADV_DEBUG_STARTUP           = 0x100000,
>>>         RADV_DEBUG_CHECKIR           = 0x200000,
>>> +       RADV_DEBUG_NOTHREADLLVM      = 0x400000,
>
> In response to your second query, I'm not sure I understand.
> NOTHREADLLVM is here!

woops, I somehow missed it.

>
>>>  };
>>>
>>>  enum {
>>> diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
>>> index ad3465f594e..73c48cef1f0 100644
>>> --- a/src/amd/vulkan/radv_device.c
>>> +++ b/src/amd/vulkan/radv_device.c
>>> @@ -436,6 +436,7 @@ static const struct debug_control radv_debug_options[] = {
>>>         {"errors", RADV_DEBUG_ERRORS},
>>>         {"startup", RADV_DEBUG_STARTUP},
>>>         {"checkir", RADV_DEBUG_CHECKIR},
>>> +       {"nothreadllvm", RADV_DEBUG_NOTHREADLLVM},
>>>         {NULL, 0}
>>>  };
>>>
>>> diff --git a/src/amd/vulkan/radv_llvm_helper.cpp b/src/amd/vulkan/radv_llvm_helper.cpp
>>> new file mode 100644
>>> index 00000000000..dad881f6b1a
>>> --- /dev/null
>>> +++ b/src/amd/vulkan/radv_llvm_helper.cpp
>>> @@ -0,0 +1,148 @@
>>> +/*
>>> + * Copyright © 2018 Red Hat.
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a
>>> + * copy of this software and associated documentation files (the "Software"),
>>> + * to deal in the Software without restriction, including without limitation
>>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>>> + * and/or sell copies of the Software, and to permit persons to whom the
>>> + * Software is furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice (including the next
>>> + * paragraph) shall be included in all copies or substantial portions of the
>>> + * Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
>>> + * IN THE SOFTWARE.
>>> + */
>>> +#include "ac_llvm_util.h"
>>> +#include "ac_llvm_build.h"
>>> +#include "radv_shader_helper.h"
>>> +#include <llvm-c/Core.h>
>>> +#include <llvm-c/Support.h>
>>> +#include <llvm/Target/TargetMachine.h>
>>> +#include <llvm/Analysis/TargetLibraryInfo.h>
>>> +#include <llvm/IR/LegacyPassManager.h>
>>> +#if HAVE_LLVM >= 0x0700
>>> +#include <llvm-c/Transforms/Utils.h>
>>> +#endif
>>> +#if HAVE_LLVM < 0x0700
>>> +#include "llvm/Support/raw_ostream.h"
>>> +#endif
>>> +
>>> +class radv_llvm_per_thread_info {
>>> +public:
>>> +       radv_llvm_per_thread_info(enum radeon_family arg_family,
>>> +                               enum ac_target_machine_options arg_tm_options)
>>> +               : family(arg_family), tm_options(arg_tm_options) {}
>>> +
>>> +       ~radv_llvm_per_thread_info()
>>> +       {
>>> +               ac_destroy_llvm_passes(passes);
>>> +               ac_destroy_llvm_compiler(&llvm_info);
>>> +       }
>>> +
>>> +       bool init(void)
>>> +       {
>>> +               if (!ac_init_llvm_compiler(&llvm_info,
>>> +                                         true,
>>> +                                         family,
>>> +                                         tm_options))
>>> +                       return false;
>>> +
>>> +               passes = ac_create_llvm_passes(llvm_info.tm);
>>> +               if (!passes)
>>> +                       return false;
>>> +
>>> +               return true;
>>> +       }
>>> +
>>> +       bool compile_to_memory_buffer(LLVMModuleRef module,
>>> +                                     struct ac_shader_binary *binary)
>>> +       {
>>> +               return ac_compile_module_to_binary(passes, module, binary);
>>> +       }
>>> +
>>> +       bool is_same(enum radeon_family arg_family,
>>> +                    enum ac_target_machine_options arg_tm_options) {
>>> +               if (arg_family == family &&
>>> +                   arg_tm_options == tm_options)
>>> +                       return true;
>>> +               return false;
>>> +       }
>>> +       struct ac_llvm_compiler llvm_info;
>>> +private:
>>> +       enum radeon_family family;
>>> +       enum ac_target_machine_options tm_options;
>>> +       struct ac_compiler_passes *passes;
>>> +};
>>> +
>>> +/* we have to store a linked list per thread due to the possiblity of multiple gpus being required */
>>> +static thread_local std::list<radv_llvm_per_thread_info> radv_llvm_per_thread_list;
>>> +
>>> +bool radv_compile_to_binary(struct ac_llvm_compiler *info,
>>> +                           LLVMModuleRef module,
>>> +                           struct ac_shader_binary *binary)
>>> +{
>>> +       radv_llvm_per_thread_info *thread_info = nullptr;
>>> +
>>> +       for (auto &I : radv_llvm_per_thread_list) {
>>> +               if (I.llvm_info.tm == info->tm) {
>>> +                       thread_info = &I;
>>> +                       break;
>>> +               }
>>> +       }
>>> +
>>> +       if (!thread_info) {
>>> +               struct ac_compiler_passes *passes = ac_create_llvm_passes(info->tm);
>>> +               bool ret = ac_compile_module_to_binary(passes, module, binary);
>>> +               ac_destroy_llvm_passes(passes);
>>> +               return ret;
>>> +       }
>>> +
>>> +       return thread_info->compile_to_memory_buffer(module, binary);
>>> +}
>>> +
>>> +bool radv_init_llvm_compiler(struct ac_llvm_compiler *info,
>>> +                            bool okay_to_leak_target_library_info,
>>> +                            bool thread_compiler,
>>> +                            enum radeon_family family,
>>> +                            enum ac_target_machine_options tm_options)
>>> +{
>>> +       if (thread_compiler) {
>>> +               for (auto &I : radv_llvm_per_thread_list) {
>>> +                       if (I.is_same(family, tm_options)) {
>>> +                               *info = I.llvm_info;
>>> +                               return true;
>>> +                       }
>>> +               }
>>> +
>>> +               radv_llvm_per_thread_list.emplace_back(family, tm_options);
>>> +               radv_llvm_per_thread_info &tinfo = radv_llvm_per_thread_list.back();
>>> +
>>> +               if (!tinfo.init())
>>> +                       return false;
>>
>> Clean up the newly inserted list entry?
>
> Once I figure out how to do it nicely :-)
>
> Dave.


More information about the mesa-dev mailing list