#include "lp_bld_debug.h"
#include "lp_bld_init.h"
+#include <llvm-c/Transforms/Scalar.h>
+
#ifdef DEBUG
unsigned gallivm_debug = 0;
static const struct debug_named_value lp_bld_debug_flags[] = {
- { "tgsi", GALLIVM_DEBUG_TGSI },
- { "ir", GALLIVM_DEBUG_IR },
- { "asm", GALLIVM_DEBUG_ASM },
- { "nopt", GALLIVM_DEBUG_NO_OPT },
- {NULL, 0}
+ { "tgsi", GALLIVM_DEBUG_TGSI, NULL },
+ { "ir", GALLIVM_DEBUG_IR, NULL },
+ { "asm", GALLIVM_DEBUG_ASM, NULL },
+ { "nopt", GALLIVM_DEBUG_NO_OPT, NULL },
+ DEBUG_NAMED_VALUE_END
};
#endif
LLVMExecutionEngineRef lp_build_engine = NULL;
LLVMModuleProviderRef lp_build_provider = NULL;
LLVMTargetDataRef lp_build_target = NULL;
+LLVMPassManagerRef lp_build_pass = NULL;
+
+
+/*
+ * Optimization values are:
+ * - 0: None (-O0)
+ * - 1: Less (-O1)
+ * - 2: Default (-O2, -Os)
+ * - 3: Aggressive (-O3)
+ *
+ * See also CodeGenOpt::Level in llvm/Target/TargetMachine.h
+ */
+enum LLVM_CodeGenOpt_Level {
+#if HAVE_LLVM >= 0x207
+ None, // -O0
+ Less, // -O1
+ Default, // -O2, -Os
+ Aggressive // -O3
+#else
+ Default,
+ None,
+ Aggressive
+#endif
+};
+
+
+extern void
+lp_register_oprofile_jit_event_listener(LLVMExecutionEngineRef EE);
+
+extern void
+lp_set_target_options(void);
void
gallivm_debug = debug_get_flags_option("GALLIVM_DEBUG", lp_bld_debug_flags, 0 );
#endif
+ lp_set_target_options();
+
LLVMInitializeNativeTarget();
LLVMLinkInJIT();
lp_build_provider = LLVMCreateModuleProviderForExistingModule(lp_build_module);
if (!lp_build_engine) {
+ enum LLVM_CodeGenOpt_Level optlevel;
char *error = NULL;
- if (LLVMCreateJITCompiler(&lp_build_engine, lp_build_provider, 1, &error)) {
+ if (gallivm_debug & GALLIVM_DEBUG_NO_OPT) {
+ optlevel = None;
+ }
+ else {
+ optlevel = Default;
+ }
+
+ if (LLVMCreateJITCompiler(&lp_build_engine, lp_build_provider,
+ (unsigned)optlevel, &error)) {
_debug_printf("%s\n", error);
LLVMDisposeMessage(error);
assert(0);
}
+
+#if defined(DEBUG) || defined(PROFILE)
+ lp_register_oprofile_jit_event_listener(lp_build_engine);
+#endif
}
if (!lp_build_target)
lp_build_target = LLVMGetExecutionEngineTargetData(lp_build_engine);
+ if (!lp_build_pass) {
+ lp_build_pass = LLVMCreateFunctionPassManager(lp_build_provider);
+ LLVMAddTargetData(lp_build_target, lp_build_pass);
+
+ if ((gallivm_debug & GALLIVM_DEBUG_NO_OPT) == 0) {
+ /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
+ * but there are more on SVN. */
+ /* TODO: Add more passes */
+ LLVMAddCFGSimplificationPass(lp_build_pass);
+ LLVMAddPromoteMemoryToRegisterPass(lp_build_pass);
+ LLVMAddConstantPropagationPass(lp_build_pass);
+ if(util_cpu_caps.has_sse4_1) {
+ /* FIXME: There is a bug in this pass, whereby the combination of fptosi
+ * and sitofp (necessary for trunc/floor/ceil/round implementation)
+ * somehow becomes invalid code.
+ */
+ LLVMAddInstructionCombiningPass(lp_build_pass);
+ }
+ LLVMAddGVNPass(lp_build_pass);
+ } else {
+ /* We need at least this pass to prevent the backends to fail in
+ * unexpected ways.
+ */
+ LLVMAddPromoteMemoryToRegisterPass(lp_build_pass);
+ }
+ }
+
util_cpu_detect();
#if 0