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

Dave Airlie airlied at gmail.com
Mon Jul 9 21:03:05 UTC 2018


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!

>>  };
>>
>>  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