From 6a02c36f0407e2bd7d63cc3fb10706c3ea6aefdd Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 24 Jul 2012 23:42:28 -0700 Subject: [PATCH] Added PassManagerBuilder. Updated test/passes.py for PassManagerBuilder. --- llvm/_core.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ llvm/core.py | 6 +--- llvm/extra.cpp | 38 +++++++++++++++++++++-- llvm/extra.h | 44 ++++++++++++++++++++++++-- llvm/passes.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ llvm/wrap.c | 12 +++++--- llvm/wrap.h | 8 +++++ test/passes.py | 73 +++++++++++++++++++++++++++++++++++++++++--- 8 files changed, 318 insertions(+), 19 deletions(-) diff --git a/llvm/_core.c b/llvm/_core.c index 55a64f3..1aaa62e 100644 --- a/llvm/_core.c +++ b/llvm/_core.c @@ -842,6 +842,50 @@ _wLLVMCreateMemoryBufferWithSTDIN(PyObject *self, PyObject *args) _wrap_obj2none(LLVMDisposeMemoryBuffer, LLVMMemoryBufferRef) +/*===----------------------------------------------------------------------===*/ +/* Pass Manager Builder */ +/*===----------------------------------------------------------------------===*/ + +_wrap_none2obj(LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderRef) +_wrap_obj2none(LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderRef) + +_wrap_objint2none(LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderRef) +_wrap_obj2obj(LLVMPassManagerBuilderGetOptLevel, LLVMPassManagerBuilderRef, int) + +_wrap_objint2none(LLVMPassManagerBuilderSetSizeLevel, LLVMPassManagerBuilderRef) +_wrap_obj2obj(LLVMPassManagerBuilderGetSizeLevel, LLVMPassManagerBuilderRef, int) + +_wrap_objint2none(LLVMPassManagerBuilderSetVectorize, LLVMPassManagerBuilderRef) +_wrap_obj2obj(LLVMPassManagerBuilderGetVectorize, LLVMPassManagerBuilderRef, int) + +_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnitAtATime, + LLVMPassManagerBuilderRef) +_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnitAtATime, + LLVMPassManagerBuilderRef, int) + +_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnrollLoops, + LLVMPassManagerBuilderRef) +_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnrollLoops, + LLVMPassManagerBuilderRef, int) + +_wrap_objint2none(LLVMPassManagerBuilderSetDisableSimplifyLibCalls, + LLVMPassManagerBuilderRef) +_wrap_obj2obj(LLVMPassManagerBuilderGetDisableSimplifyLibCalls, + LLVMPassManagerBuilderRef, int) + +_wrap_objint2none(LLVMPassManagerBuilderUseInlinerWithThreshold, + LLVMPassManagerBuilderRef) + + +_wrap_objobj2none(LLVMPassManagerBuilderPopulateFunctionPassManager, + LLVMPassManagerBuilderRef, + LLVMPassManagerRef) + +_wrap_objobj2none(LLVMPassManagerBuilderPopulateModulePassManager, + LLVMPassManagerBuilderRef, + LLVMPassManagerRef) + + /*===----------------------------------------------------------------------===*/ /* Pass Manager */ /*===----------------------------------------------------------------------===*/ @@ -1687,6 +1731,35 @@ static PyMethodDef core_methods[] = { _method( LLVMCreateMemoryBufferWithSTDIN ) _method( LLVMDisposeMemoryBuffer ) + /* Pass Manager Builder */ + + _method( LLVMPassManagerBuilderCreate ) + _method( LLVMPassManagerBuilderDispose ) + + _method( LLVMPassManagerBuilderSetOptLevel ) + _method( LLVMPassManagerBuilderGetOptLevel ) + + _method( LLVMPassManagerBuilderSetSizeLevel ) + _method( LLVMPassManagerBuilderGetSizeLevel ) + + _method( LLVMPassManagerBuilderSetVectorize ) + _method( LLVMPassManagerBuilderGetVectorize ) + + + _method( LLVMPassManagerBuilderSetDisableUnitAtATime ) + _method( LLVMPassManagerBuilderGetDisableUnitAtATime ) + + _method( LLVMPassManagerBuilderSetDisableUnrollLoops ) + _method( LLVMPassManagerBuilderGetDisableUnrollLoops ) + + _method( LLVMPassManagerBuilderSetDisableSimplifyLibCalls ) + _method( LLVMPassManagerBuilderGetDisableSimplifyLibCalls ) + + _method( LLVMPassManagerBuilderUseInlinerWithThreshold ) + + _method( LLVMPassManagerBuilderPopulateFunctionPassManager ) + _method( LLVMPassManagerBuilderPopulateModulePassManager ) + /* Pass Manager */ _method( LLVMCreatePassManager ) _method( LLVMCreateFunctionPassManagerForModule ) diff --git a/llvm/core.py b/llvm/core.py index 80753e3..1658846 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -620,11 +620,7 @@ class Type(object): @staticmethod def __struct(element_tys, packed, name): elems = unpack_types(element_tys) - - if packed: - packed=1 - else: - packed=0 + packed = int(bool(packed)) if name: # create Identified StructType objptr = _core.LLVMStructTypeIdentified(name) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 876921b..86067c0 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -76,8 +76,6 @@ // our includes #include "extra.h" -//using namespace llvm; - /* * For use in LLVMDumpPasses to dump passes. */ @@ -106,6 +104,42 @@ char *do_print(W obj) return strdup(buf.str().c_str()); } + +int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb) +{ + return llvm::unwrap(pmb)->OptLevel; +} + +int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb) +{ + return llvm::unwrap(pmb)->SizeLevel; +} + +void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag) +{ + llvm::unwrap(pmb)->Vectorize = flag; +} + +int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb){ + return llvm::unwrap(pmb)->Vectorize; +} + +int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb) +{ + return llvm::unwrap(pmb)->DisableUnitAtATime; +} + +int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb) +{ + return llvm::unwrap(pmb)->DisableUnrollLoops; +} + +int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb) +{ + return llvm::unwrap(pmb)->DisableSimplifyLibCalls; +} + + int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name) { using namespace llvm; diff --git a/llvm/extra.h b/llvm/extra.h index bd6a264..27fadfc 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -37,22 +37,62 @@ #ifndef LLVM_PY_EXTRA_H #define LLVM_PY_EXTRA_H +#include "llvm-c/Transforms/PassManagerBuilder.h" + #ifdef __cplusplus extern "C" { #endif +/* + * Wraps PassManagerBuilder::OptLevel + */ +int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb); + +/* + * Wraps PassManagerBuilder::SizeLevel + */ +int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb); + +/* + * Wraps PassManagerBuilder::Vectorize + */ +void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag); + +/* + * Wraps PassManagerBuilder::Vectorize + */ +int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb); + +/* + * Wraps PassManagerBuilder::DisableUnitAtATime + */ +int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb); + +/* + * Wraps PassManagerBuilder::DisableUnrollLoops + */ +int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb); + +/* + * Wraps PassManagerBuilder::DisableSimplifyLibCalls + */ +int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb); + +/* + * Wraps PassManager::add + */ int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name); /* * Wraps initialize* */ -void LLVMInitializePasses(); +void LLVMInitializePasses(void); /* * Wraps PassRegistry::enumerateWith() * Returns a '\n' separated string of all passes available to `opt`. */ -const char * LLVMDumpPasses(); +const char * LLVMDumpPasses(void); /* * Wraps StructType::isLiteral() diff --git a/llvm/passes.py b/llvm/passes.py index b39b367..0b64c11 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -40,6 +40,89 @@ import llvm.ee as ee # target data import llvm.core as core # module, function etc. import llvm._core as _core # C wrappers + +#===----------------------------------------------------------------------=== +# Pass manager builder +#===----------------------------------------------------------------------=== + +class PassManagerBuilder(object): + @staticmethod + def new(): + return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate()) + + def __init__(self, ptr): + self.ptr = ptr + + def __del__(self): + _core.LLVMPassManagerBuilderDispose(self.ptr) + + def populate(self, pm): + if isinstance(pm, FunctionPassManager): + return _core.LLVMPassManagerBuilderPopulateFunctionPassManager( + self.ptr, pm.ptr) + else: + return _core.LLVMPassManagerBuilderPopulateModulePassManager( + self.ptr, pm.ptr) + + + def _set_opt_level(self, optlevel): + _core.LLVMPassManagerBuilderSetOptLevel(self.ptr, optlevel) + + def _get_opt_level(self): + return _core.LLVMPassManagerBuilderGetOptLevel(self.ptr) + + opt_level = property(_get_opt_level, _set_opt_level) + + def _set_size_level(self, sizelevel): + _core.LLVMPassManagerBuilderSetSizeLevel(self.ptr, sizelevel) + + def _get_size_level(self): + return _core.LLVMPassManagerBuilderGetSizeLevel(self.ptr) + + size_level = property(_get_size_level, _set_size_level) + + def _set_vectorize(self, enable): + _core.LLVMPassManagerBuilderSetVectorize(self.ptr, int(bool(enable))) + + def _get_vectorize(self): + return bool(_core.LLVMPassManagerBuilderGetVectorize(self.ptr)) + + vectorize = property(_get_vectorize, _set_vectorize) + + def _set_disable_unit_at_a_time(self, disable): + return _core.LLVMPassManagerBuilderSetDisableUnitAtATime( + self.ptr, disable) + + def _get_disable_unit_at_a_time(self): + return _core.LLVMPassManagerBuilderGetDisableUnitAtATime( + self.ptr) + + disable_unit_at_a_time = property(_get_disable_unit_at_a_time, + _set_disable_unit_at_a_time) + + def _set_disable_unroll_loops(self, disable): + return _core.LLVMPassManagerBuilderGetDisableUnrollLoops( + self.ptr, disable) + + def _get_disable_unroll_loops(self): + return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(self.ptr) + + disable_unroll_loops = property(_get_disable_unroll_loops, + _set_disable_unroll_loops) + + def _set_disable_simplify_lib_calls(self, disable): + return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls( + self.ptr, disable) + + def _get_disable_simplify_lib_calls(self): + return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(self.ptr) + + disable_simplify_lib_calls = property(_get_disable_simplify_lib_calls, + _set_disable_simplify_lib_calls) + + def use_inliner_with_threshold(self, threshold): + _core.LLVMPassManagerBuilderUseInlinerWithThreshold(self.ptr, threshold) + #===----------------------------------------------------------------------=== # Pass manager #===----------------------------------------------------------------------=== diff --git a/llvm/wrap.c b/llvm/wrap.c index 9bd7e5b..3653061 100644 --- a/llvm/wrap.c +++ b/llvm/wrap.c @@ -11,7 +11,7 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - * * Neither the name of this software, nor the names of its + * * Neither the name of this software, nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * @@ -31,7 +31,7 @@ #include "wrap.h" /* Project-wide setting */ -#if (PY_MAJOR_VERSION >= 3) +#if (PY_MAJOR_VERSION >= 3) #define LLVM_PY_USE_PYCAPSULE #endif @@ -39,7 +39,7 @@ /* Helper functions/macros */ /*===----------------------------------------------------------------------===*/ -#ifdef LLVM_PY_USE_PYCAPSULE +#ifdef LLVM_PY_USE_PYCAPSULE #define _define_std_ctor(typ) \ PyObject * ctor_ ## typ ( typ p) \ @@ -76,6 +76,8 @@ _define_std_ctor(LLVMExecutionEngineRef) _define_std_ctor(LLVMTargetDataRef) _define_std_ctor(LLVMGenericValueRef) +_define_std_ctor(LLVMPassManagerBuilderRef) + PyObject *ctor_int(int i) { return PyLong_FromLong((long)i); @@ -108,7 +110,7 @@ void **make_array_from_list(PyObject *list, int n) { int i; void **arr; - + arr = (void **)malloc(sizeof(void *) * n); if (!arr) return NULL; @@ -121,7 +123,7 @@ void **make_array_from_list(PyObject *list, int n) arr[i] = PyCObject_AsVoidPtr(e); #endif } - + return arr; } diff --git a/llvm/wrap.h b/llvm/wrap.h index 9d1b04b..9fd5636 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -45,6 +45,10 @@ #include "llvm-c/Analysis.h" #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" +// workaround missing bool type +#define bool int +#include "llvm-c/Transforms/PassManagerBuilder.h" +#undef bool /* Project-wide setting */ #if PY_MAJOR_VERSION >= 3 @@ -58,6 +62,7 @@ typedef unsigned long long llvmwrap_ull; + /*===----------------------------------------------------------------------===*/ /* Type ctor/dtor */ /*===----------------------------------------------------------------------===*/ @@ -83,6 +88,9 @@ _declare_std_ctor(LLVMExecutionEngineRef) _declare_std_ctor(LLVMTargetDataRef) _declare_std_ctor(LLVMGenericValueRef) +// extra LLVM class not defined in LLVM-C +_declare_std_ctor(LLVMPassManagerBuilderRef) + /* standard types */ _declare_std_ctor(int) _declare_std_ctor(llvmwrap_ull) diff --git a/test/passes.py b/test/passes.py index fc0a478..6415b68 100755 --- a/test/passes.py +++ b/test/passes.py @@ -9,11 +9,11 @@ from StringIO import StringIO import logging, unittest # A helper class. -class strstream(object): - def __init__(self, s): - self.s = s - def read(self): - return self.s +#class strstream(object): +# def __init__(self, s): +# self.s = s +# def read(self): +# return self.s # Create a module. asm = """ @@ -100,9 +100,72 @@ class TestPasses(unittest.TestCase): # Make sure test1 is modified self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) + def test_passes_with_pmb(self): + m = Module.from_assembly(StringIO(asm)) + logging.debug("-"*72) + logging.debug(m) + + fn_test1 = m.get_function_named('test1') + fn_test2 = m.get_function_named('test2') + + original_test1 = str(fn_test1) + original_test2 = str(fn_test2) + + # Try out the PassManagerBuilder + + pmb = PassManagerBuilder.new() + + self.assertEqual(pmb.opt_level, 2) # ensure default is level 2 + pmb.opt_level = 3 + self.assertEqual(pmb.opt_level, 3) # make sure it works + + self.assertEqual(pmb.size_level, 0) # ensure default is level 0 + pmb.size_level = 2 + self.assertEqual(pmb.size_level, 2) # make sure it works + + self.assertFalse(pmb.vectorize) # ensure default is False + pmb.vectorize = True + self.assertTrue(pmb.vectorize) # make sure it works + + # make sure the default is False + self.assertFalse(pmb.disable_unit_at_a_time) + self.assertFalse(pmb.disable_unroll_loops) + self.assertFalse(pmb.disable_simplify_lib_calls) + + # Do function pass + fpm = FunctionPassManager.new(m) + + pmb.populate(fpm) + + fpm.run(fn_test1) + + # Print the result. Note the change in @test1. + logging.debug("-"*72) + logging.debug(m) + + # Make sure test1 has changed + self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) + + + # Do module pass + pm = PassManager.new() + + pmb.populate(pm) + + pm.run(m) + + # Print the result. Note the change in @test2. + logging.debug("-"*72) + logging.debug(m) + + # Make sure test2 has changed + self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) + + def test_dump_passes(self): self.assertTrue(len(PASSES)>0, msg="Cannot have no passes") + if __name__ == '__main__': unittest.main()