Skip to content

Commit 9370462

Browse files
committed
Add inlining support to LLVM JIT provider.
This provides infrastructure to allow JITed code to inline code implemented in C. This e.g. can be postgres internal functions or extension code. This already speeds up long running queries, by allowing the LLVM optimizer to optimize across function boundaries. The optimization potential currently doesn't reach its full potential because LLVM cannot optimize the FunctionCallInfoData argument fully away, because it's allocated on the heap rather than the stack. Fixing that is beyond what's realistic for v11. To be able to do that, use CLANG to convert C code to LLVM bitcode, and have LLVM build a summary for it. That bitcode can then be used to to inline functions at runtime. For that the bitcode needs to be installed. Postgres bitcode goes into $pkglibdir/bitcode/postgres, extensions go into equivalent directories. PGXS has been modified so that happens automatically if postgres has been compiled with LLVM support. Currently this isn't the fastest inline implementation, modules are reloaded from disk during inlining. That's to work around an apparent LLVM bug, triggering an apparently spurious error in LLVM assertion enabled builds. Once that is resolved we can remove the superfluous read from disk. Docs will follow in a later commit containing docs for the whole JIT feature. Author: Andres Freund Discussion: https://postgr.es/m/20170901064131.tazjxwus3k2w3ybh@alap3.anarazel.de
1 parent 8a934d6 commit 9370462

File tree

13 files changed

+988
-8
lines changed

13 files changed

+988
-8
lines changed

src/Makefile.global.in

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ endif # PGXS
171171
includedir_server = $(pkgincludedir)/server
172172
includedir_internal = $(pkgincludedir)/internal
173173
pgxsdir = $(pkglibdir)/pgxs
174+
bitcodedir = $(pkglibdir)/bitcode
174175

175176

176177
##########################################################################
@@ -972,3 +973,36 @@ endif
972973

973974
%.bc : %.cpp
974975
$(COMPILE.cxx.bc) -o $@ $<
976+
977+
# Install LLVM bitcode module (for JITing).
978+
#
979+
# The arguments are:
980+
# $(1) name of the module (e.g. an extension's name or postgres for core code)
981+
# $(2) source objects, with .o suffix
982+
#
983+
define install_llvm_module
984+
# Create target directory
985+
$(MKDIR_P) "$(DESTDIR)${bitcodedir}/$(1)"
986+
# Create sub-directories, if files are in subdirectories
987+
$(MKDIR_P) $(sort $(dir $(addprefix $(DESTDIR)${bitcodedir}/$(1)/, $(2))))
988+
# Then install files
989+
#
990+
# The many INSTALL_DATA invocations aren't particularly fast, it'd be
991+
# good if we could coalesce them, but I didn't find a good way.
992+
$(foreach obj, ${2}, $(INSTALL_DATA) $(patsubst %.o,%.bc, $(obj)) $(DESTDIR)/${bitcodedir}/$(1)/$(dir $(obj));
993+
)
994+
# and generate index
995+
(cd "$(DESTDIR)${bitcodedir}" && $(LLVM_BINPATH)/llvm-lto -thinlto -thinlto-action=thinlink -o $(1).index.bc $(addprefix $(1)/,$(patsubst %.o,%.bc, $(2))))
996+
endef
997+
998+
# Uninstall LLVM bitcode module.
999+
#
1000+
# The arguments are:
1001+
# $(1) name of the module (e.g. an extension's name or postgres for core code)
1002+
#
1003+
# This intentionally doesn't use the explicit installed file list,
1004+
# seems too likely to change regularly.
1005+
define uninstall_llvm_module
1006+
rm -rf "$(DESTDIR)${bitcodedir}/$(1)/"
1007+
rm -f "$(DESTDIR)${bitcodedir}/$(1).index.bc"
1008+
endef

src/backend/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ endif
252252
$(INSTALL_DATA) $(srcdir)/utils/misc/postgresql.conf.sample '$(DESTDIR)$(datadir)/postgresql.conf.sample'
253253
$(INSTALL_DATA) $(srcdir)/access/transam/recovery.conf.sample '$(DESTDIR)$(datadir)/recovery.conf.sample'
254254

255+
ifeq ($(with_llvm), yes)
256+
install-bin: install-postgres-bitcode
257+
258+
install-postgres-bitcode: $(OBJS) all
259+
$(call install_llvm_module,postgres,$(call expand_subsys, $(filter-out $(top_builddir)/src/timezone/objfiles.txt, $(SUBDIROBJS))))
260+
endif
261+
255262
install-bin: postgres $(POSTGRES_IMP) installdirs
256263
$(INSTALL_PROGRAM) postgres$(X) '$(DESTDIR)$(bindir)/postgres$(X)'
257264
ifneq ($(PORTNAME), win32)
@@ -309,6 +316,9 @@ endif
309316
'$(DESTDIR)$(datadir)/pg_ident.conf.sample' \
310317
'$(DESTDIR)$(datadir)/postgresql.conf.sample' \
311318
'$(DESTDIR)$(datadir)/recovery.conf.sample'
319+
ifeq ($(with_llvm), yes)
320+
$(call uninstall_llvm_module,postgres)
321+
endif
312322

313323

314324
##########################################################################

src/backend/common.mk

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ objfiles.txt: Makefile $(SUBDIROBJS) $(OBJS)
3030
# Don't rebuild the list if only the OBJS have changed.
3131
$(if $(filter-out $(OBJS),$?),( $(if $(SUBDIROBJS),cat $(SUBDIROBJS); )echo $(addprefix $(subdir)/,$(OBJS)) ) >$@,touch $@)
3232

33+
ifeq ($(with_llvm), yes)
34+
objfiles.txt: $(patsubst %.o,%.bc, $(OBJS))
35+
endif
36+
3337
# make function to expand objfiles.txt contents
3438
expand_subsys = $(foreach file,$(1),$(if $(filter %/objfiles.txt,$(file)),$(patsubst ../../src/backend/%,%,$(addprefix $(top_builddir)/,$(shell cat $(file)))),$(file)))
3539

@@ -43,7 +47,7 @@ $(SUBDIRS:%=%-recursive):
4347
$(call recurse,clean)
4448
clean: clean-local
4549
clean-local:
46-
rm -f $(subsysfilename) $(OBJS)
50+
rm -f $(subsysfilename) $(OBJS) $(patsubst %.o,%.bc, $(OBJS))
4751

4852
$(call recurse,coverage)
4953
$(call recurse,install)

src/backend/jit/jit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ bool jit_expressions = true;
4040
bool jit_profiling_support = false;
4141
bool jit_tuple_deforming = true;
4242
double jit_above_cost = 100000;
43+
double jit_inline_above_cost = 500000;
4344
double jit_optimize_above_cost = 500000;
4445

4546
static JitProviderCallbacks provider;

src/backend/jit/llvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ override COMPILER = $(CXX) $(CFLAGS)
3737
OBJS=$(WIN32RES)
3838

3939
# Infrastructure
40-
OBJS += llvmjit.o llvmjit_error.o llvmjit_wrap.o
40+
OBJS += llvmjit.o llvmjit_error.o llvmjit_inline.o llvmjit_wrap.o
4141
# Code generation
4242
OBJS += llvmjit_expr.o llvmjit_deform.o
4343

src/backend/jit/llvm/llvmjit.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,10 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
468468
/* always use always-inliner pass */
469469
if (!(context->base.flags & PGJIT_OPT3))
470470
LLVMAddAlwaysInlinerPass(llvm_mpm);
471+
/* if doing inlining, but no expensive optimization, add inlining pass */
472+
if (context->base.flags & PGJIT_INLINE
473+
&& !(context->base.flags & PGJIT_OPT3))
474+
LLVMAddFunctionInliningPass(llvm_mpm);
471475
LLVMRunPassManager(llvm_mpm, context->module);
472476
LLVMDisposePassManager(llvm_mpm);
473477

@@ -491,6 +495,16 @@ llvm_compile_module(LLVMJitContext *context)
491495
else
492496
compile_orc = llvm_opt0_orc;
493497

498+
/* perform inlining */
499+
if (context->base.flags & PGJIT_INLINE)
500+
{
501+
INSTR_TIME_SET_CURRENT(starttime);
502+
llvm_inline(context->module);
503+
INSTR_TIME_SET_CURRENT(endtime);
504+
INSTR_TIME_ACCUM_DIFF(context->base.inlining_counter,
505+
endtime, starttime);
506+
}
507+
494508
if (jit_dump_bitcode)
495509
{
496510
char *filename;
@@ -578,7 +592,8 @@ llvm_compile_module(LLVMJitContext *context)
578592
MemoryContextSwitchTo(oldcontext);
579593

580594
ereport(DEBUG1,
581-
(errmsg("time to opt: %.3fs, emit: %.3fs",
595+
(errmsg("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
596+
INSTR_TIME_GET_DOUBLE(context->base.inlining_counter),
582597
INSTR_TIME_GET_DOUBLE(context->base.optimization_counter),
583598
INSTR_TIME_GET_DOUBLE(context->base.emission_counter)),
584599
errhidestmt(true),

0 commit comments

Comments
 (0)