diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3a4e5190e5122f6305e24e057cd61e3a597ce69c..b99dd44e65276ac2bdf44d1dc45842cd98f86806 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,6 @@
 ---
 variables:
+  GIT_STRATEGY: clone
   GIT_SUBMODULE_STRATEGY: recursive
   HYPERTHREADING: "false"
   OMP_NUM_THREADS: 1
diff --git a/.gitmodules b/.gitmodules
index 1733ea4f5c7666f27dfc88945612f491bc6cc4df..0eef893d9c288c88fce4e0fbf210ba4978faa945 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,8 +10,8 @@
 [submodule "python/cgen"]
 	path = python/cgen
 	url = https://github.com/inducer/cgen.git
-[submodule "dune/perftool/vectorclass"]
-	path = dune/perftool/vectorclass
+[submodule "dune/codegen/vectorclass"]
+	path = dune/codegen/vectorclass
 	url = https://github.com/darealshinji/vectorclass.git
 [submodule "python/pytools"]
 	path = python/pytools
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7cf8469e5b7b3ad58a370e1c114229740813b812..e333cab7b37c5466067f1cd5f05c9385e5fa120c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 2.8.12)
-project(dune-perftool CXX)
+project(dune-codegen CXX)
 
 if(NOT (dune-common_DIR OR dune-common_ROOT OR
       "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*"))
@@ -21,15 +21,15 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDUNE_ISTL_SUPPORT_OLD_CATEGORY_INTERFA
 # start a dune project with information from dune.module
 dune_project()
 
-dune_add_library(duneperftool dune/perftool/common/tsc.cc)
+dune_add_library(dunecodegen dune/codegen/common/tsc.cc)
 
-dune_target_enable_all_packages(duneperftool)
+dune_target_enable_all_packages(dunecodegen)
 
-dune_register_package_flags(LIBRARIES duneperftool)
+dune_register_package_flags(LIBRARIES dunecodegen)
 
 dune_enable_all_packages()
 
-add_subdirectory(dune/perftool)
+add_subdirectory(dune/codegen)
 add_subdirectory(cmake/modules)
 
 # Add the python subdirectory to systematically install
diff --git a/COPYING b/COPYING
index a6667742a94d5fd8a5a764b9e316e3109da2334c..6e3c2d2290300cea8a726588e8285794be72f39e 100644
--- a/COPYING
+++ b/COPYING
@@ -1,30 +1,30 @@
-Copyright by Dominic Kempf, René Heß 2015-2017.
+Copyright by Dominic Kempf, René Heß, Marcel Koch 2015-2018.
 
-The following files are copyrighted by Agner Fog, 2012-2015:
+The following files are copyrighted by Agner Fog, 2012-2018:
 
-dune/perftool/complexvec.h
-dune/perftool/decimal.h
-dune/perftool/dispatch_example.cpp
-dune/perftool/instrset_detect.cpp
-dune/perftool/instrset.h
-dune/perftool/quaternion.h
-dune/perftool/ranvec1.cpp
-dune/perftool/ranvec1.h
-dune/perftool/vector3d.h
-dune/perftool/vectorclass.h
-dune/perftool/vectorf128.h
-dune/perftool/vectorf256e.h
-dune/perftool/vectorf256.h
-dune/perftool/vectorf512e.h
-dune/perftool/vectorf512.h
-dune/perftool/vectori128.h
-dune/perftool/vectori256e.h
-dune/perftool/vectori256.h
-dune/perftool/vectori512e.h
-dune/perftool/vectori512.h
-dune/perftool/vectormath_common.h
-dune/perftool/vectormath_exp.h
-dune/perftool/vectormath_hyp.h
-dune/perftool/vectormath_lib.h
-dune/perftool/vectormath_trig.h
+dune/codegen/complexvec.h
+dune/codegen/decimal.h
+dune/codegen/dispatch_example.cpp
+dune/codegen/instrset_detect.cpp
+dune/codegen/instrset.h
+dune/codegen/quaternion.h
+dune/codegen/ranvec1.cpp
+dune/codegen/ranvec1.h
+dune/codegen/vector3d.h
+dune/codegen/vectorclass.h
+dune/codegen/vectorf128.h
+dune/codegen/vectorf256e.h
+dune/codegen/vectorf256.h
+dune/codegen/vectorf512e.h
+dune/codegen/vectorf512.h
+dune/codegen/vectori128.h
+dune/codegen/vectori256e.h
+dune/codegen/vectori256.h
+dune/codegen/vectori512e.h
+dune/codegen/vectori512.h
+dune/codegen/vectormath_common.h
+dune/codegen/vectormath_exp.h
+dune/codegen/vectormath_hyp.h
+dune/codegen/vectormath_lib.h
+dune/codegen/vectormath_trig.h
 doc/vclmanual.pdf
diff --git a/README.md b/README.md
index f23438ea118c648acf1ec2a20f2135b8dc96013f..f1aeb98fa4fcf3d6354873f35b053aa6c39a7627 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,18 @@
-# dune-perftool
+# dune-codegen
 
-dune-perftool is an active research project with the goal of
+dune-codegen is an active research project with the goal of
 generating high-performance integration kernels for dune-pdelab.
 
 **Note**: Due to the research character of the code things will change
 a lot and there is no guarantee for interface stability ;).
 
 
-[![pipeline status](https://gitlab.dune-project.org/dominic/dune-perftool/badges/master/pipeline.svg)](https://gitlab.dune-project.org/dominic/dune-perftool/commits/master)
+[![pipeline status](https://gitlab.dune-project.org/dominic/dune-codegen/badges/master/pipeline.svg)](https://gitlab.dune-project.org/dominic/dune-codegen/commits/master)
 
 
 ## Dependencies
 
-dune-perftool depends on the following software packages:
+dune-codegen depends on the following software packages:
 
 * You need a working [dune-pdelab][1].
 
@@ -27,21 +27,21 @@ dune-perftool depends on the following software packages:
 We use several submodules so you should clone with the `--recursive` option:
 
 ```
-git clone --recursive ssh://git@parcomp-git.iwr.uni-heidelberg.de:20022/dominic/dune-perftool.git
+git clone --recursive ssh://git@gitlab.dune-project.org:22022/dominic/dune-codegen.git
 ```
 
 or
 
 ```
-git clone --recursive https://parcomp-git.iwr.uni-heidelberg.de/dominic/dune-perftool.git
+git clone --recursive https://gitlab.dune-project.org/dominic/dune-codegen.git
 ```
 
 If you have a feature branch `feature/my-branch` where you change the
-submodules of dune-perftool and you want to test your branch it makes
+submodules of dune-codegen and you want to test your branch it makes
 sense to checkout this branch directly in a fresh clone:
 
 ```
-git clone --recursive -b feature/my-branch ssh://git@parcomp-git.iwr.uni-heidelberg.de:20022/dominic/dune-perftool.git
+git clone --recursive -b feature/my-branch ssh://git@gitlab.dune-project.org:22022/dominic/dune-codegen.git
 ```
 
 Some tests compare the vtkoutput to a reference vtk output. If you
@@ -51,27 +51,22 @@ case:
 
 ```
 ssh-add
-git clone --recursive ssh://git@parcomp-git.iwr.uni-heidelberg.de:20022/dominic/dune-perftool.git
+git clone --recursive ssh://git@gitlab.dune-project.org:22022/dominic/dune-codegen.git
 ```
 
-After cloning dune-perftool you need apply some patches:
+After cloning dune-codegen you need apply some patches:
 
-* Go to the base folder of dune-perftool and run
+* Go to the base folder of dune-codegen and run
   patches/apply_patches.sh. This applies patches to the submodules.
 
   ```
-  cd dune-perftool/
+  cd dune-codegen/
   ./patches/apply_patches.sh
   ```
 
-* Besides that you need to apply the patch
-  dune-perftool/patches/dune-geometry/quadrule_operator_counting_compatible.patch
-  in dune-geometry.
+## Building dune-codegen
 
-
-## Building dune-perftool
-
-Building dune-perftool is done through the Dune build-system using
+Building dune-codegen is done through the Dune build-system using
 cmake. See the [Dune homepage][4] for further details. You need to set the options
 
 ```
@@ -101,7 +96,7 @@ MAKE_FLAGS="-j2"
 You can build and run the tests via:
 
 ```
-cd path/to/dune-perftool/build/directory
+cd path/to/dune-codegen/build/directory
 make build_tests
 ctest
 ```
diff --git a/bin/.gitignore b/bin/.gitignore
index 8c6f2092904a09f3004ed2e381b9169efc40b11f..e910c773f2c3c9a78db6c37a7e511a2e22ceae22 100644
--- a/bin/.gitignore
+++ b/bin/.gitignore
@@ -1 +1 @@
-perftoolcoveniencescripts.egg-info/*
+dunecodegencoveniencescripts.egg-info/*
diff --git a/bin/analyzegrid/analyze_grid.cc b/bin/analyzegrid/analyze_grid.cc
index bc7c0a93304f21ae8016e970ba4831e7b8716ca0..bd19952640f2162ac3fa8cbaab0a51c638862286 100644
--- a/bin/analyzegrid/analyze_grid.cc
+++ b/bin/analyzegrid/analyze_grid.cc
@@ -12,7 +12,7 @@
 
 #include <dune/consistent-edge-orientation/createconsistentgrid.hh>
 
-#include <dune/perftool/sumfact/analyzegrid.hh>
+#include <dune/codegen/sumfact/analyzegrid.hh>
 
 int main(int argc, char** argv){
   try
diff --git a/bin/setup.py b/bin/setup.py
index feaeace8ad1a0cc9279d582a2f3f5d1eedca2bb0..c86bac6bb4e2bbf8cc6a82a3cac1d6e1f819b79b 100644
--- a/bin/setup.py
+++ b/bin/setup.py
@@ -8,7 +8,7 @@
 from setuptools import setup
 
 
-setup(name='perftoolcoveniencescripts',
+setup(name='dunecodegencoveniencescripts',
       version='0.1',
       description='Some convenience scripts',
       author='Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>',
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
index 85e38089ee5a7389a34f1697ae7a6939e8cf8a45..0746ef28f8e31988ceed71e33e49f4da64937df2 100644
--- a/cmake/modules/CMakeLists.txt
+++ b/cmake/modules/CMakeLists.txt
@@ -1,5 +1,5 @@
 install(FILES deplist.py
-              DunePerftoolMacros.cmake
+              dune-codegen_sourcepath.py
+              DuneCodegenMacros.cmake
               GeneratedSystemtest.cmake
-              perftool_sourcepath.py
         DESTINATION ${DUNE_INSTALL_MODULEDIR})
diff --git a/cmake/modules/DunePerftoolMacros.cmake b/cmake/modules/DuneCodegenMacros.cmake
similarity index 91%
rename from cmake/modules/DunePerftoolMacros.cmake
rename to cmake/modules/DuneCodegenMacros.cmake
index 34e542c4ae170a98f64eb4eb106c1e7012f8ead7..6823107087dbef0040b80d2637d9d604545dd3e7 100644
--- a/cmake/modules/DunePerftoolMacros.cmake
+++ b/cmake/modules/DuneCodegenMacros.cmake
@@ -55,18 +55,18 @@ add_custom_target(generation)
 
 # Gather a list of form compiler sources to add as dependencies
 # to have correct retriggers of generated executables
-if(CMAKE_PROJECT_NAME STREQUAL dune-perftool)
+if(CMAKE_PROJECT_NAME STREQUAL dune-codegen)
   set(UFL2PDELAB_GLOB_PATTERN "${CMAKE_SOURCE_DIR}/python/*.py")
-  set(perftool_path ${CMAKE_SOURCE_DIR}/cmake/modules)
+  set(dune-codegen_path ${CMAKE_SOURCE_DIR}/cmake/modules)
 else()
-  dune_module_path(MODULE dune-perftool
-                   RESULT perftool_path
+  dune_module_path(MODULE dune-codegen
+                   RESULT dune-codegen_path
                    CMAKE_MODULES)
-  dune_execute_process(COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env python ${perftool_path}/perftool_sourcepath.py
-                       OUTPUT_VARIABLE perftool_source
+  dune_execute_process(COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env python ${dune-codegen_path}/dune-codegen_sourcepath.py
+                       OUTPUT_VARIABLE dune-codegen_source
                        OUTPUT_STRIP_TRAILING_WHITESPACE
                        )
-  set(UFL2PDELAB_GLOB_PATTERN "${perftool_source}/*.py")
+  set(UFL2PDELAB_GLOB_PATTERN "${dune-codegen_source}/*.py")
 endif()
 file(GLOB_RECURSE UFL2PDELAB_SOURCES ${UFL2PDELAB_GLOB_PATTERN})
 
@@ -105,7 +105,7 @@ function(add_generated_executable)
                                --driver-file ${GEN_SOURCE}
                                --project-basedir ${CMAKE_BINARY_DIR}
                                ${GEN_FORM_COMPILER_ARGS}
-                       DEPENDS ${GEN_UFLFILE} ${UFL2PDELAB_SOURCES} ${GEN_DEPENDS} ${DUNE_PERFTOOL_ADDITIONAL_PYTHON_SOURCES}
+                       DEPENDS ${GEN_UFLFILE} ${UFL2PDELAB_SOURCES} ${GEN_DEPENDS} ${DUNE_CODEGEN_ADDITIONAL_PYTHON_SOURCES}
                        COMMENT "Generating driver for the target ${GEN_TARGET}"
                        )
   endif()
@@ -131,7 +131,7 @@ function(add_generated_executable)
   endif()
 
   # Parse a mapping of operators to build and their respective filenames
-  dune_execute_process(COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env python ${perftool_path}/deplist.py ${GEN_INIFILE} ${GEN_TARGET}
+  dune_execute_process(COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env python ${dune-codegen_path}/deplist.py ${GEN_INIFILE} ${GEN_TARGET}
                        OUTPUT_VARIABLE depdata
                        )
   parse_python_data(PREFIX depdata INPUT ${depdata})
@@ -148,7 +148,7 @@ function(add_generated_executable)
                                --target-name ${GEN_TARGET}
                                --operator-to-build ${op}
                                ${ANALYZE_GRID_OPTION}
-                       DEPENDS ${GEN_UFLFILE} ${UFL2PDELAB_SOURCES} ${GEN_DEPENDS} ${DUNE_PERFTOOL_ADDITIONAL_PYTHON_SOURCES} ${ANALYZE_GRID_FILE}
+                       DEPENDS ${GEN_UFLFILE} ${UFL2PDELAB_SOURCES} ${GEN_DEPENDS} ${DUNE_CODEGEN_ADDITIONAL_PYTHON_SOURCES} ${ANALYZE_GRID_FILE}
                        COMMENT "Generating operator file ${depdata___${op}} for the target ${GEN_TARGET}"
                        )
     set(header_deps ${header_deps} ${depdata___${op}})
diff --git a/cmake/modules/perftool_sourcepath.py b/cmake/modules/dune-codegen_sourcepath.py
similarity index 52%
rename from cmake/modules/perftool_sourcepath.py
rename to cmake/modules/dune-codegen_sourcepath.py
index 26cde733d7b09b3dd344213ea0ed2f3030bb88de..9eaf66e71b36c5e3de7c1b4e2bc77c4736fcaf9e 100644
--- a/cmake/modules/perftool_sourcepath.py
+++ b/cmake/modules/dune-codegen_sourcepath.py
@@ -1,16 +1,16 @@
-# Find the actual sources of dune-perftool from downstream modules
+# Find the actual sources of dune-codegen from downstream modules
 # to define dependency on them (otherwise working on the form compiler
-# becomes PITA). The cmake variable dune-perftool_DIR only points to the
+# becomes PITA). The cmake variable dune-codegen_DIR only points to the
 # *build directory*, the source directory of upstream modules is not
 # available through CMake (for good reason).
 #
-# Do not use this on your own, DunePerftoolMacros.cmake uses this!
+# Do not use this on your own, DuneCodegenMacros.cmake uses this!
 
 import os
 import sys
-import dune.perftool
+import dune.codegen
 
-path = dune.perftool.__path__[0]
+path = dune.codegen.__path__[0]
 path = os.path.split(os.path.split(path)[0])[0]
 sys.stdout.write(path)
 sys.exit(0)
diff --git a/config.h.cmake b/config.h.cmake
index 9a36b5c11c19b4b76ef63a3bb0ebdc9c80b2d866..fc6cc8d76f11369da55a0feb6c31c474cd607c1d 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -1,4 +1,4 @@
-/* begin dune-perftool
+/* begin dune-codegen
    put the definitions for config.h specific to
    your project here. Everything above will be
    overwritten
@@ -28,18 +28,18 @@
 
 /* end private */
 
-/* Define to the version of dune-perftool */
-#define DUNE_PERFTOOL_VERSION "@DUNE_PERFTOOL_VERSION@"
+/* Define to the version of dune-codegen */
+#define DUNE_CODEGEN_VERSION "@DUNE_CODEGEN_VERSION@"
 
-/* Define to the major version of dune-perftool */
-#define DUNE_PERFTOOL_VERSION_MAJOR @DUNE_PERFTOOL_VERSION_MAJOR@
+/* Define to the major version of dune-codegen */
+#define DUNE_CODEGEN_VERSION_MAJOR @DUNE_CODEGEN_VERSION_MAJOR@
 
-/* Define to the minor version of dune-perftool */
-#define DUNE_PERFTOOL_VERSION_MINOR @DUNE_PERFTOOL_VERSION_MINOR@
+/* Define to the minor version of dune-codegen */
+#define DUNE_CODEGEN_VERSION_MINOR @DUNE_CODEGEN_VERSION_MINOR@
 
-/* Define to the revision of dune-perftool */
-#define DUNE_PERFTOOL_VERSION_REVISION @DUNE_PERFTOOL_VERSION_REVISION@
+/* Define to the revision of dune-codegen */
+#define DUNE_CODEGEN_VERSION_REVISION @DUNE_CODEGEN_VERSION_REVISION@
 
-/* end dune-perftool
+/* end dune-codegen
    Everything below here will be overwritten
 */
diff --git a/dune-perftool.pc.in b/dune-codegen.pc.in
similarity index 77%
rename from dune-perftool.pc.in
rename to dune-codegen.pc.in
index 646119855cbb90663a79e25a9ad398afefd7e845..126f21c16e58c1c42482722f239bbb5b2b17ffc1 100644
--- a/dune-perftool.pc.in
+++ b/dune-codegen.pc.in
@@ -8,8 +8,8 @@ DEPENDENCIES=@REQUIRES@
 
 Name: @PACKAGE_NAME@
 Version: @VERSION@
-Description: dune-perftool module
+Description: dune-codegen module
 URL: http://dune-project.org/
-Requires: dune-pdelab dune-python
+Requires: dune-pdelab dune-testtools
 Libs: -L${libdir}
 Cflags: -I${includedir}
diff --git a/dune.module b/dune.module
index 1ae974397a480f5e80e4beb88007ae68468c0073..4f1a80d528fbe14ece9a034c63e3378c2e44b124 100644
--- a/dune.module
+++ b/dune.module
@@ -3,7 +3,7 @@
 ################################
 
 #Name of the module
-Module: dune-perftool
+Module: dune-codegen
 Version: 0.0
 Maintainer: dominic.kempf@iwr.uni-heidelberg.de
 #depending on
diff --git a/dune/perftool/CMakeLists.txt b/dune/codegen/CMakeLists.txt
similarity index 63%
rename from dune/perftool/CMakeLists.txt
rename to dune/codegen/CMakeLists.txt
index 92f812d0fe1d364e4fdd175b6cebe02b14f2f978..d9e21026a38673aed2b7975251fec95e40a06c39 100644
--- a/dune/perftool/CMakeLists.txt
+++ b/dune/codegen/CMakeLists.txt
@@ -1,4 +1,6 @@
+add_subdirectory(blockstructured)
 add_subdirectory(common)
+add_subdirectory(sumfact)
 add_subdirectory(test)
 
 install(FILES vectorclass/dispatch_example.cpp
@@ -20,12 +22,12 @@ install(FILES vectorclass/dispatch_example.cpp
               vectorclass/vectormath_hyp.h
               vectorclass/vectormath_lib.h
               vectorclass/vectormath_trig.h
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/perftool/vectorclass)
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/codegen/vectorclass)
 
-install(FILES vectorclass/complexvec.h
-              vectorclass/decimal.h
-              vectorclass/quaternion.h
-              vectorclass/ranvec1.cpp
-              vectorclass/ranvec1.h
-              vectorclass/vector3d.h
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/perftool/vectorclass/special)
+install(FILES vectorclass/special/complexvec.h
+              vectorclass/special/decimal.h
+              vectorclass/special/quaternion.h
+              vectorclass/special/ranvec1.cpp
+              vectorclass/special/ranvec1.h
+              vectorclass/special/vector3d.h
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/codegen/vectorclass/special)
diff --git a/dune/codegen/blockstructured/CMakeLists.txt b/dune/codegen/blockstructured/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..19d37d340c2579403abcb7daa5d311e1c7b565d7
--- /dev/null
+++ b/dune/codegen/blockstructured/CMakeLists.txt
@@ -0,0 +1,3 @@
+install(FILES blockstructuredqkfem.hh
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/codegen/blockstructured
+        )
diff --git a/dune/perftool/blockstructured/blockstructuredqkfem.hh b/dune/codegen/blockstructured/blockstructuredqkfem.hh
similarity index 89%
rename from dune/perftool/blockstructured/blockstructuredqkfem.hh
rename to dune/codegen/blockstructured/blockstructuredqkfem.hh
index 90ad10e684fe2735527e527701dc4962b510e3d7..64512ce42339d483a3c3bc56e51c60c7d64a2efa 100644
--- a/dune/perftool/blockstructured/blockstructuredqkfem.hh
+++ b/dune/codegen/blockstructured/blockstructuredqkfem.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_BLOCKSTRUCTUREDQKFEM_HH
-#define DUNE_PERFTOOL_BLOCKSTRUCTUREDQKFEM_HH
+#ifndef DUNE_CODEGEN_BLOCKSTRUCTUREDQKFEM_HH
+#define DUNE_CODEGEN_BLOCKSTRUCTUREDQKFEM_HH
 
 
 #include <cstddef>
@@ -58,4 +58,4 @@ namespace Dune {
 }
 
 
-#endif //DUNE_PERFTOOL_BLOCKSTRUCTUREDQKFEM_HH
+#endif //DUNE_CODEGEN_BLOCKSTRUCTUREDQKFEM_HH
diff --git a/dune/perftool/common/CMakeLists.txt b/dune/codegen/common/CMakeLists.txt
similarity index 71%
rename from dune/perftool/common/CMakeLists.txt
rename to dune/codegen/common/CMakeLists.txt
index 6cd100631e8241eb91cbd4a3f11b27197941b8c9..0b1b1e3ac460d568758c8ddbd8251a37d51433f8 100644
--- a/dune/perftool/common/CMakeLists.txt
+++ b/dune/codegen/common/CMakeLists.txt
@@ -4,5 +4,5 @@ install(FILES muladd_workarounds.hh
               timer_chrono.hh
               tsc.hh
               vectorclass.hh
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/perftool/common
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/codegen/common
         )
diff --git a/dune/perftool/common/muladd_workarounds.hh b/dune/codegen/common/muladd_workarounds.hh
similarity index 77%
rename from dune/perftool/common/muladd_workarounds.hh
rename to dune/codegen/common/muladd_workarounds.hh
index ba728fad57bbbe78ed997c6b8f42f5cbf265988b..95832e5fd4c0e3088087d64666fd071b867cc73a 100644
--- a/dune/perftool/common/muladd_workarounds.hh
+++ b/dune/codegen/common/muladd_workarounds.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_MULADD_WORKAROUNDS_HH
-#define DUNE_PERFTOOL_MULADD_WORKAROUNDS_HH
+#ifndef DUNE_CODEGEN_MULADD_WORKAROUNDS_HH
+#define DUNE_CODEGEN_MULADD_WORKAROUNDS_HH
 
 /* We are currently having some issues with FMA nodes not being
  * eliminated correctly upon code generation. We "solve" the problem
diff --git a/dune/codegen/common/timer.hh b/dune/codegen/common/timer.hh
new file mode 100644
index 0000000000000000000000000000000000000000..a216a8c9a5e640a0e262158cdbdf26e3b647f9ad
--- /dev/null
+++ b/dune/codegen/common/timer.hh
@@ -0,0 +1,14 @@
+#ifndef DUNE_CODEGEN_COMMON_TIMER_HH
+#define DUNE_CODEGEN_COMMON_TIMER_HH
+
+#define _GONE_THROUGH_TIMER_HH
+
+#if ENABLE_CHRONO_TIMER
+#include<dune/codegen/common/timer_chrono.hh>
+#else
+#include<dune/codegen/common/timer_tsc.hh>
+#endif
+
+#undef _GONE_THROUGH_TIMER_HH
+
+#endif
diff --git a/dune/perftool/common/timer_chrono.hh b/dune/codegen/common/timer_chrono.hh
similarity index 96%
rename from dune/perftool/common/timer_chrono.hh
rename to dune/codegen/common/timer_chrono.hh
index 8e96a70a2e4126471f2636300bfb9a46841d5f9f..9983695df01e3e1231d59db67e807460559bba7e 100644
--- a/dune/perftool/common/timer_chrono.hh
+++ b/dune/codegen/common/timer_chrono.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_COMMON_TIMER_CHRONO_HH
-#define DUNE_PERFTOOL_COMMON_TIMER_CHRONO_HH
+#ifndef DUNE_CODEGEN_COMMON_TIMER_CHRONO_HH
+#define DUNE_CODEGEN_COMMON_TIMER_CHRONO_HH
 
 #ifndef _GONE_THROUGH_TIMER_HH
 #error "Do not include timer_chrono.hh directly, instead use timer.hh"
@@ -111,4 +111,4 @@
 
 #endif
 
-#endif // DUNE_PERFTOOL_COMMON_TIMER_CHRONO_HH
+#endif // DUNE_CODEGEN_COMMON_TIMER_CHRONO_HH
diff --git a/dune/perftool/common/timer_tsc.hh b/dune/codegen/common/timer_tsc.hh
similarity index 95%
rename from dune/perftool/common/timer_tsc.hh
rename to dune/codegen/common/timer_tsc.hh
index 10ec75d98ffbb5a68425dbab21367fb20bdbf395..e4d9dfa9136389ce43d6d161ac5ae901cdaeae5b 100644
--- a/dune/perftool/common/timer_tsc.hh
+++ b/dune/codegen/common/timer_tsc.hh
@@ -1,11 +1,11 @@
-#ifndef DUNE_PERFTOOL_COMMON_TIMER_TSC_HH
-#define DUNE_PERFTOOL_COMMON_TIMER_TSC_HH
+#ifndef DUNE_CODEGEN_COMMON_TIMER_TSC_HH
+#define DUNE_CODEGEN_COMMON_TIMER_TSC_HH
 
 #ifndef _GONE_THROUGH_TIMER_HH
 #error "Do not include timer_tsc.hh directly, instead use timer.hh"
 #endif
 
-#include <dune/perftool/common/tsc.hh>
+#include <dune/codegen/common/tsc.hh>
 #include <dune/opcounter/opcounter.hh>
 
 #define HP_TIMER_DURATION(name) __hp_timer_##name##_duration
@@ -113,4 +113,4 @@
 
 #endif
 
-#endif // DUNE_PERFTOOL_COMMON_TIMER_TSC_HH
+#endif // DUNE_CODEGEN_COMMON_TIMER_TSC_HH
diff --git a/dune/perftool/common/tsc.cc b/dune/codegen/common/tsc.cc
similarity index 99%
rename from dune/perftool/common/tsc.cc
rename to dune/codegen/common/tsc.cc
index 42616419e4c1e716c4ffc8c96b57c7ccc307d51b..b1e8c10a37ccbf8b40062518cf1641819a58e0c3 100644
--- a/dune/perftool/common/tsc.cc
+++ b/dune/codegen/common/tsc.cc
@@ -15,7 +15,7 @@
 #include <sys/sysctl.h>
 #endif
 
-#include <dune/perftool/common/tsc.hh>
+#include <dune/codegen/common/tsc.hh>
 
 namespace Dune {
   namespace PDELab {
diff --git a/dune/perftool/common/tsc.hh b/dune/codegen/common/tsc.hh
similarity index 96%
rename from dune/perftool/common/tsc.hh
rename to dune/codegen/common/tsc.hh
index c002722269aa580f28006d14f8049dddb5680987..830a87d9ae67fabba00271bae0d3809834c987b0 100644
--- a/dune/perftool/common/tsc.hh
+++ b/dune/codegen/common/tsc.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_COMMON_TSC_TIMER_HH
-#define DUNE_PERFTOOL_COMMON_TSC_TIMER_HH
+#ifndef DUNE_CODEGEN_COMMON_TSC_TIMER_HH
+#define DUNE_CODEGEN_COMMON_TSC_TIMER_HH
 
 #include <dune/pdelab/common/exceptions.hh>
 #include <dune/common/parametertree.hh>
diff --git a/dune/perftool/common/vectorclass.hh b/dune/codegen/common/vectorclass.hh
similarity index 72%
rename from dune/perftool/common/vectorclass.hh
rename to dune/codegen/common/vectorclass.hh
index 9fe0cf17b47abda0691c14591be3fcc15ee6e4d7..aa3bba7b98f9cf57dcc223f61755e3aa26c5bdca 100644
--- a/dune/perftool/common/vectorclass.hh
+++ b/dune/codegen/common/vectorclass.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_COMMON_VECTORCLASS_HH
-#define DUNE_PERFTOOL_COMMON_VECTORCLASS_HH
+#ifndef DUNE_CODEGEN_COMMON_VECTORCLASS_HH
+#define DUNE_CODEGEN_COMMON_VECTORCLASS_HH
 
 
 template<typename T>
@@ -21,10 +21,10 @@ struct base_floatingpoint<OpCounter::impl::OpCounterVector<F, size>>
 #error "dune-opcounter is needed for opcounted vector types"
 #endif
 #else
-#include<dune/perftool/vectorclass/vectorclass.h>
-#include<dune/perftool/vectorclass/vectormath_exp.h>
-#include<dune/perftool/vectorclass/vectormath_hyp.h>
-#include<dune/perftool/vectorclass/vectormath_trig.h>
+#include<dune/codegen/vectorclass/vectorclass.h>
+#include<dune/codegen/vectorclass/vectormath_exp.h>
+#include<dune/codegen/vectorclass/vectormath_hyp.h>
+#include<dune/codegen/vectorclass/vectormath_trig.h>
 
 template<>
 struct base_floatingpoint<Vec2d>
@@ -69,4 +69,4 @@ struct base_floatingpoint<Vec16f>
 
 #endif
 
-#endif // DUNE_PDELAB_COMMON_VECTORCLASS_HH
+#endif // DUNE_CODEGEN_COMMON_VECTORCLASS_HH
diff --git a/dune/perftool/localbasiscache.hh b/dune/codegen/localbasiscache.hh
similarity index 96%
rename from dune/perftool/localbasiscache.hh
rename to dune/codegen/localbasiscache.hh
index 6a9312e7ff8c0ee119ee4c051ee40a75b3d4fb8a..d2d2a8552d890a1a9687db94dd8ac7195e818f67 100644
--- a/dune/perftool/localbasiscache.hh
+++ b/dune/codegen/localbasiscache.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_CACHEWRAPPER_HH
-#define DUNE_PERFTOOL_CACHEWRAPPER_HH
+#ifndef DUNE_CODEGEN_CACHEWRAPPER_HH
+#define DUNE_CODEGEN_CACHEWRAPPER_HH
 
 #include<vector>
 
diff --git a/dune/perftool/matrixfree.hh b/dune/codegen/matrixfree.hh
similarity index 89%
rename from dune/perftool/matrixfree.hh
rename to dune/codegen/matrixfree.hh
index 9de88135da7e7064f3a0c06c9fb7846de665d813..52ea23704f3b75c3e69ec24e73a3887e1dfb5f81 100644
--- a/dune/perftool/matrixfree.hh
+++ b/dune/codegen/matrixfree.hh
@@ -1,12 +1,12 @@
-#ifndef DUNE_PERFTOOL_MATRIXFREE_HH
-#define DUNE_PERFTOOL_MATRIXFREE_HH
+#ifndef DUNE_CODEGEN_MATRIXFREE_HH
+#define DUNE_CODEGEN_MATRIXFREE_HH
 
 #include <iostream>
 
 #include <dune/pdelab/backend/istl.hh>
 
-#include <dune/perftool/matrixfreeistlbackends.hh>
-#include <dune/perftool/matrixfreenewton.hh>
+#include <dune/codegen/matrixfreeistlbackends.hh>
+#include <dune/codegen/matrixfreenewton.hh>
 
 namespace Dune{
   namespace PDELab{
diff --git a/dune/perftool/matrixfreeistlbackends.hh b/dune/codegen/matrixfreeistlbackends.hh
similarity index 98%
rename from dune/perftool/matrixfreeistlbackends.hh
rename to dune/codegen/matrixfreeistlbackends.hh
index c150bf988ed3066b473bdf032ed487820e3d3549..ae6cbaf4942f3a847f0b8768490f217dcc1a2ca8 100644
--- a/dune/perftool/matrixfreeistlbackends.hh
+++ b/dune/codegen/matrixfreeistlbackends.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_MATRIXFREEISTLBACKENDS_HH
-#define DUNE_PERFTOOL_MATRIXFREEISTLBACKENDS_HH
+#ifndef DUNE_CODEGEN_MATRIXFREEISTLBACKENDS_HH
+#define DUNE_CODEGEN_MATRIXFREEISTLBACKENDS_HH
 namespace Dune {
   namespace PDELab {
 
diff --git a/dune/perftool/matrixfreenewton.hh b/dune/codegen/matrixfreenewton.hh
similarity index 99%
rename from dune/perftool/matrixfreenewton.hh
rename to dune/codegen/matrixfreenewton.hh
index 728bafc0b83d12584bdaf2d7fb64a8ec431d3d86..84e83c2ffa1737a81063432e6e00d170c7d519c7 100644
--- a/dune/perftool/matrixfreenewton.hh
+++ b/dune/codegen/matrixfreenewton.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 2; indent-tabs-mode: nil -*-
 // vi: set et ts=2 sw=2 sts=2:
-#ifndef DUNE_PDELAB_NEWTON_MATRIXFREENEWTON_HH
-#define DUNE_PDELAB_NEWTON_MATRIXFREENEWTON_HH
+#ifndef DUNE_CODEGEN_MATRIXFREENEWTON_HH
+#define DUNE_CODEGEN_MATRIXFREENEWTON_HH
 
 #include <iostream>
 #include <iomanip>
@@ -14,7 +14,7 @@
 #include <dune/common/timer.hh>
 #include <dune/common/parametertree.hh>
 
-#include <dune/perftool/newtonbase.hh>
+#include <dune/codegen/newtonbase.hh>
 
 namespace Dune {
   namespace PDELab {
diff --git a/dune/perftool/newtonbase.hh b/dune/codegen/newtonbase.hh
similarity index 95%
rename from dune/perftool/newtonbase.hh
rename to dune/codegen/newtonbase.hh
index 9f264d416c0cba11c0291dc099f9acebca79e8ee..a40e0567cdd3780346476a1f7759103e1eff9909 100644
--- a/dune/perftool/newtonbase.hh
+++ b/dune/codegen/newtonbase.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 2; indent-tabs-mode: nil -*-
 // vi: set et ts=2 sw=2 sts=2:
-#ifndef DUNE_PDELAB_NEWTON_NEWTONBASE_HH
-#define DUNE_PDELAB_NEWTON_NEWTONBASE_HH
+#ifndef DUNE_CODEGEN_NEWTONBASE_HH
+#define DUNE_CODEGEN_NEWTONBASE_HH
 
 #include <dune/common/exceptions.hh>
 #include <dune/pdelab/backend/solver.hh>
diff --git a/dune/codegen/sumfact/CMakeLists.txt b/dune/codegen/sumfact/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5bfcd522d34623e0800a5a885364301bf90903d5
--- /dev/null
+++ b/dune/codegen/sumfact/CMakeLists.txt
@@ -0,0 +1,7 @@
+install(FILES analyzegrid.hh
+              horizontaladd.hh
+              invertgeometry.hh
+              onedquadrature.hh
+              transposereg.hh
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/codegen/sumfact
+        )
diff --git a/dune/perftool/sumfact/analyzegrid.hh b/dune/codegen/sumfact/analyzegrid.hh
similarity index 97%
rename from dune/perftool/sumfact/analyzegrid.hh
rename to dune/codegen/sumfact/analyzegrid.hh
index c646616110b1b3bfb2a29e497eeacb3d58a60dbd..cc5180b0ed7f1de18e46e1206dce4d417f37e64e 100644
--- a/dune/perftool/sumfact/analyzegrid.hh
+++ b/dune/codegen/sumfact/analyzegrid.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_SUMFACT_ANALYZEGRID_HH
-#define DUNE_PERFTOOL_SUMFACT_ANALYZEGRID_HH
+#ifndef DUNE_CODEGEN_SUMFACT_ANALYZEGRID_HH
+#define DUNE_CODEGEN_SUMFACT_ANALYZEGRID_HH
 
 
 #include <dune/pdelab/common/intersectiontype.hh>
diff --git a/dune/perftool/sumfact/horizontaladd.hh b/dune/codegen/sumfact/horizontaladd.hh
similarity index 66%
rename from dune/perftool/sumfact/horizontaladd.hh
rename to dune/codegen/sumfact/horizontaladd.hh
index db7634f0e5507214318dabb719240ff3674808ed..fc62dc47dab77330a125bb5f91805c89808480b0 100644
--- a/dune/perftool/sumfact/horizontaladd.hh
+++ b/dune/codegen/sumfact/horizontaladd.hh
@@ -1,7 +1,7 @@
-#ifndef DUNE_PERFTOOL_SUMFACT_HORIZONTALADD_HH
-#define DUNE_PERFTOOL_SUMFACT_HORIZONTALADD_HH
+#ifndef DUNE_CODEGEN_SUMFACT_HORIZONTALADD_HH
+#define DUNE_CODEGEN_SUMFACT_HORIZONTALADD_HH
 
-#include<dune/perftool/common/vectorclass.hh>
+#include<dune/codegen/common/vectorclass.hh>
 
 
 template<class V>
diff --git a/dune/perftool/sumfact/invertgeometry.hh b/dune/codegen/sumfact/invertgeometry.hh
similarity index 94%
rename from dune/perftool/sumfact/invertgeometry.hh
rename to dune/codegen/sumfact/invertgeometry.hh
index a20708e8a2c305a35d642124b3c01a2ad0d387f6..2a0b364cc9df2daea9088af053c89a4da129cae2 100644
--- a/dune/perftool/sumfact/invertgeometry.hh
+++ b/dune/codegen/sumfact/invertgeometry.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_SUMFACT_INVERTGEOMETRY_HH
-#define DUNE_PERFTOOL_SUMFACT_INVERTGEOMETRY_HH
+#ifndef DUNE_CODEGEN_SUMFACT_INVERTGEOMETRY_HH
+#define DUNE_CODEGEN_SUMFACT_INVERTGEOMETRY_HH
 
 
 template<typename T>
diff --git a/dune/perftool/sumfact/onedquadrature.hh b/dune/codegen/sumfact/onedquadrature.hh
similarity index 92%
rename from dune/perftool/sumfact/onedquadrature.hh
rename to dune/codegen/sumfact/onedquadrature.hh
index 6ff3195c54f29c843ca5822fdaf05710834f57de..ab17e6cc3ed7fc6fa017fdb8f4a9fcde81da6d4a 100644
--- a/dune/perftool/sumfact/onedquadrature.hh
+++ b/dune/codegen/sumfact/onedquadrature.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_SUMFACT_ONEDQUADRATURE_HH
-#define DUNE_PERFTOOL_SUMFACT_ONEDQUADRATURE_HH
+#ifndef DUNE_CODEGEN_SUMFACT_ONEDQUADRATURE_HH
+#define DUNE_CODEGEN_SUMFACT_ONEDQUADRATURE_HH
 
 
 #include <dune/geometry/quadraturerules.hh>
diff --git a/dune/perftool/sumfact/transposereg.hh b/dune/codegen/sumfact/transposereg.hh
similarity index 98%
rename from dune/perftool/sumfact/transposereg.hh
rename to dune/codegen/sumfact/transposereg.hh
index a3b8372288d9461c85f6761328fa96e7db465ea4..7a1ac55f9eb9aa97b968e5d9f4d33cfe1a0c8079 100644
--- a/dune/perftool/sumfact/transposereg.hh
+++ b/dune/codegen/sumfact/transposereg.hh
@@ -1,7 +1,7 @@
-#ifndef DUNE_PERFTOOL_SUMFACT_TRANSPOSEREG_HH
-#define DUNE_PERFTOOL_SUMFACT_TRANSPOSEREG_HH
+#ifndef DUNE_CODEGEN_SUMFACT_TRANSPOSEREG_HH
+#define DUNE_CODEGEN_SUMFACT_TRANSPOSEREG_HH
 
-#include<dune/perftool/common/vectorclass.hh>
+#include<dune/codegen/common/vectorclass.hh>
 
 // DOUBLE 2 x 2
 void transpose_reg(Vec2d& a0, Vec2d& a1)
diff --git a/dune/perftool/test/CMakeLists.txt b/dune/codegen/test/CMakeLists.txt
similarity index 100%
rename from dune/perftool/test/CMakeLists.txt
rename to dune/codegen/test/CMakeLists.txt
diff --git a/dune/perftool/test/test_transpose.cc b/dune/codegen/test/test_transpose.cc
similarity index 94%
rename from dune/perftool/test/test_transpose.cc
rename to dune/codegen/test/test_transpose.cc
index 8d265b1bd266969ce900957dff547a20d5a04607..8c37ee0e0712ae9bccd15cbe448e22a86fb6ec51 100644
--- a/dune/perftool/test/test_transpose.cc
+++ b/dune/codegen/test/test_transpose.cc
@@ -2,8 +2,8 @@
 
 #define MAX_VECTOR_SIZE 512
 
-#include<dune/perftool/common/vectorclass.hh>
-#include<dune/perftool/sumfact/transposereg.hh>
+#include<dune/codegen/common/vectorclass.hh>
+#include<dune/codegen/sumfact/transposereg.hh>
 
 #include<array>
 #include<iostream>
diff --git a/dune/perftool/test/transpose.mini b/dune/codegen/test/transpose.mini
similarity index 100%
rename from dune/perftool/test/transpose.mini
rename to dune/codegen/test/transpose.mini
diff --git a/dune/perftool/vectorclass b/dune/codegen/vectorclass
similarity index 100%
rename from dune/perftool/vectorclass
rename to dune/codegen/vectorclass
diff --git a/dune/perftool/vtkpredicate.hh b/dune/codegen/vtkpredicate.hh
similarity index 83%
rename from dune/perftool/vtkpredicate.hh
rename to dune/codegen/vtkpredicate.hh
index d567e01e7a1310b230708c53e7d2372d5e859f2a..193a7e4840d6226a377cf9cb7f329ced3bbbf266 100644
--- a/dune/perftool/vtkpredicate.hh
+++ b/dune/codegen/vtkpredicate.hh
@@ -1,5 +1,5 @@
-#ifndef DUNE_PERFTOOL_VTKPREDICATE_HH
-#define DUNE_PERFTOOL_VTKPREDICATE_HH
+#ifndef DUNE_CODEGEN_VTKPREDICATE_HH
+#define DUNE_CODEGEN_VTKPREDICATE_HH
 
 #include <dune/typetree/nodeinterface.hh>
 
diff --git a/dune/perftool/common/timer.hh b/dune/perftool/common/timer.hh
deleted file mode 100644
index cd1bc47457664d0ae20736d5b74d941b41e9096c..0000000000000000000000000000000000000000
--- a/dune/perftool/common/timer.hh
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef DUNE_PERFTOOL_COMMON_TIMER_HH
-#define DUNE_PERFTOOL_COMMON_TIMER_HH
-
-#define _GONE_THROUGH_TIMER_HH
-
-#if ENABLE_CHRONO_TIMER
-#include<dune/perftool/common/timer_chrono.hh>
-#else
-#include<dune/perftool/common/timer_tsc.hh>
-#endif
-
-#undef _GONE_THROUGH_TIMER_HH
-
-#endif
diff --git a/patches/apply_patches.sh b/patches/apply_patches.sh
index 9d25dfeeace347316b17f45328c75a4cdde3b368..7d1d45112d392a13a3dec4881ba43222cf60054b 100755
--- a/patches/apply_patches.sh
+++ b/patches/apply_patches.sh
@@ -5,7 +5,7 @@ git apply ../../patches/loopy/Current.patch
 git apply ../../patches/loopy/0001-Disable-a-logging-statement-that-breaks.patch
 popd
 
-pushd dune/perftool/vectorclass
+pushd dune/codegen/vectorclass
 git apply ../../../patches/vectorclass/0001-Better-implementation-of-horizontal_add.patch
 popd
 
diff --git a/python/.gitignore b/python/.gitignore
index b37d79f9ee74f2d7f041e833ae2f9f5ce3304c5c..4ba28af14bafa6464c34fc4f72b4db75f6699b40 100644
--- a/python/.gitignore
+++ b/python/.gitignore
@@ -1,2 +1,2 @@
-dune.perftool.egg-info/*
+dune.codegen.egg-info/*
 *.pyc
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index a4c8a3702eccd689568cd9def3f24462e09d3f4f..15855eb3c056fc51501bd40c3b4633673def94e3 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -16,7 +16,7 @@ dune_python_install_package(PATH ufl)
 dune_python_install_package(PATH .)
 
 dune_python_add_test(NAME pep8-ourcode
-                     COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pytest --pep8 ${CMAKE_SOURCE_DIR}/python/dune/perftool
+                     COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pytest --pep8 ${CMAKE_SOURCE_DIR}/python/dune/codegen
                      )
 
 add_subdirectory(test)
diff --git a/python/dune/perftool/__init__.py b/python/dune/codegen/__init__.py
similarity index 66%
rename from python/dune/perftool/__init__.py
rename to python/dune/codegen/__init__.py
index c822006fb2d77f7ca7e4125e379807baff3aa800..243911af33e57531a147b9b4814b14ad65fd408b 100644
--- a/python/dune/perftool/__init__.py
+++ b/python/dune/codegen/__init__.py
@@ -4,10 +4,10 @@ import os
 os.environ["OMP_NUM_THREADS"] = "1"
 
 # Trigger imports that involve monkey patching!
-import dune.perftool.loopy.symbolic  # noqa
+import dune.codegen.loopy.symbolic  # noqa
 
 # Trigger some imports that are needed to have all backend implementations visible
 # to the selection mechanisms
-import dune.perftool.pdelab  # noqa
-import dune.perftool.sumfact  # noqa
-import dune.perftool.blockstructured  # noqa
+import dune.codegen.pdelab  # noqa
+import dune.codegen.sumfact  # noqa
+import dune.codegen.blockstructured  # noqa
diff --git a/python/dune/perftool/blockstructured/__init__.py b/python/dune/codegen/blockstructured/__init__.py
similarity index 57%
rename from python/dune/perftool/blockstructured/__init__.py
rename to python/dune/codegen/blockstructured/__init__.py
index 5c1283b2096cf8bcfe55ef107c77d1ece2f8aa5e..138b11463a554ee58ac236d4439120172aabb640 100644
--- a/python/dune/perftool/blockstructured/__init__.py
+++ b/python/dune/codegen/blockstructured/__init__.py
@@ -1,20 +1,20 @@
-import dune.perftool.blockstructured.quadrature
-import dune.perftool.blockstructured.argument
-import dune.perftool.blockstructured.geometry
-import dune.perftool.blockstructured.spaces
-import dune.perftool.blockstructured.basis
-import dune.perftool.blockstructured.transformations
-from dune.perftool.options import get_form_option
-from dune.perftool.pdelab.quadrature import pymbolic_quadrature_position
-from dune.perftool.blockstructured.spaces import lfs_inames
-from dune.perftool.blockstructured.basis import (pymbolic_reference_gradient,
-                                                 pymbolic_basis)
-from dune.perftool.blockstructured.geometry import (pymbolic_jacobian_inverse,
-                                                    pymbolic_jacobian_determinant,
-                                                    pymbolic_facet_jacobian_determinant,
-                                                    to_global)
-from dune.perftool.blockstructured.tools import sub_element_inames
-from dune.perftool.pdelab import PDELabInterface
+import dune.codegen.blockstructured.quadrature
+import dune.codegen.blockstructured.argument
+import dune.codegen.blockstructured.geometry
+import dune.codegen.blockstructured.spaces
+import dune.codegen.blockstructured.basis
+import dune.codegen.blockstructured.transformations
+from dune.codegen.options import get_form_option
+from dune.codegen.pdelab.quadrature import pymbolic_quadrature_position
+from dune.codegen.blockstructured.spaces import lfs_inames
+from dune.codegen.blockstructured.basis import (pymbolic_reference_gradient,
+                                                pymbolic_basis)
+from dune.codegen.blockstructured.geometry import (pymbolic_jacobian_inverse,
+                                                   pymbolic_jacobian_determinant,
+                                                   pymbolic_facet_jacobian_determinant,
+                                                   to_global)
+from dune.codegen.blockstructured.tools import sub_element_inames
+from dune.codegen.pdelab import PDELabInterface
 
 
 class BlockStructuredInterface(PDELabInterface):
@@ -23,7 +23,7 @@ class BlockStructuredInterface(PDELabInterface):
 
     def generate_accumulation_instruction(self, expr, visitor):
         if get_form_option('vectorization_blockstructured'):
-            from dune.perftool.blockstructured.accumulation import generate_accumulation_instruction
+            from dune.codegen.blockstructured.accumulation import generate_accumulation_instruction
             return generate_accumulation_instruction(expr, visitor)
         else:
             return PDELabInterface.generate_accumulation_instruction(self, expr, visitor)
diff --git a/python/dune/perftool/blockstructured/accumulation.py b/python/dune/codegen/blockstructured/accumulation.py
similarity index 84%
rename from python/dune/perftool/blockstructured/accumulation.py
rename to python/dune/codegen/blockstructured/accumulation.py
index fbe3b88f8153228e4e51577e550382cf779bfaf4..469e69b4bba506ed50d2800c8bdd98c71338ca03 100644
--- a/python/dune/perftool/blockstructured/accumulation.py
+++ b/python/dune/codegen/blockstructured/accumulation.py
@@ -1,11 +1,11 @@
-from dune.perftool.generation import instruction
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.options import get_form_option
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.pdelab.localoperator import determine_accumulation_space
-from dune.perftool.pdelab.argument import name_accumulation_variable
-from dune.perftool.pdelab.localoperator import boundary_predicates
-from dune.perftool.generation.loopy import function_mangler, globalarg
+from dune.codegen.generation import instruction
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.options import get_form_option
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.pdelab.localoperator import determine_accumulation_space
+from dune.codegen.pdelab.argument import name_accumulation_variable
+from dune.codegen.pdelab.localoperator import boundary_predicates
+from dune.codegen.generation.loopy import function_mangler, globalarg
 import loopy as lp
 import pymbolic.primitives as prim
 
diff --git a/python/dune/perftool/blockstructured/argument.py b/python/dune/codegen/blockstructured/argument.py
similarity index 79%
rename from python/dune/perftool/blockstructured/argument.py
rename to python/dune/codegen/blockstructured/argument.py
index ff08627822fbad61bea36d6873377324deb34050..afe120a8ec142820cf8ea3944538802b721f4469 100644
--- a/python/dune/perftool/blockstructured/argument.py
+++ b/python/dune/codegen/blockstructured/argument.py
@@ -1,10 +1,10 @@
-from dune.perftool.generation import (backend,
-                                      kernel_cached,
-                                      valuearg, instruction, globalarg)
-from dune.perftool.options import get_form_option
-from dune.perftool.pdelab.argument import CoefficientAccess
-from dune.perftool.blockstructured.tools import micro_index_to_macro_index, sub_element_inames
-from dune.perftool.pdelab.geometry import world_dimension
+from dune.codegen.generation import (backend,
+                                     kernel_cached,
+                                     valuearg, instruction, globalarg)
+from dune.codegen.options import get_form_option
+from dune.codegen.pdelab.argument import CoefficientAccess
+from dune.codegen.blockstructured.tools import micro_index_to_macro_index, sub_element_inames
+from dune.codegen.pdelab.geometry import world_dimension
 from loopy.types import NumpyType
 import pymbolic.primitives as prim
 
diff --git a/python/dune/perftool/blockstructured/basis.py b/python/dune/codegen/blockstructured/basis.py
similarity index 76%
rename from python/dune/perftool/blockstructured/basis.py
rename to python/dune/codegen/blockstructured/basis.py
index 98ab1bbd66f99af2451a7de1e74e5fe24719c3be..dcaf258b17e0dc4128860d3c58b9801a454f4471 100644
--- a/python/dune/perftool/blockstructured/basis.py
+++ b/python/dune/codegen/blockstructured/basis.py
@@ -1,27 +1,27 @@
-from dune.perftool.generation import (backend,
-                                      kernel_cached,
-                                      get_backend,
-                                      instruction,
-                                      temporary_variable,
-                                      globalarg,
-                                      class_member,
-                                      initializer_list,
-                                      include_file,)
-from dune.perftool.tools import get_pymbolic_basename
-from dune.perftool.loopy.target import type_floatingpoint
-from dune.perftool.pdelab.basis import (declare_cache_temporary,
-                                        name_localbasis_cache,
-                                        type_localbasis,
-                                        FEM_name_mangling)
-from dune.perftool.pdelab.driver import (isPk,
-                                         isQk,
-                                         )
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.pdelab.quadrature import pymbolic_quadrature_position_in_cell
-from dune.perftool.pdelab.spaces import type_leaf_gfs
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.blockstructured.spaces import lfs_inames
-from dune.perftool.blockstructured.tools import tensor_index_to_sequential_index
+from dune.codegen.generation import (backend,
+                                     kernel_cached,
+                                     get_backend,
+                                     instruction,
+                                     temporary_variable,
+                                     globalarg,
+                                     class_member,
+                                     initializer_list,
+                                     include_file,)
+from dune.codegen.tools import get_pymbolic_basename
+from dune.codegen.loopy.target import type_floatingpoint
+from dune.codegen.pdelab.basis import (declare_cache_temporary,
+                                       name_localbasis_cache,
+                                       type_localbasis,
+                                       FEM_name_mangling)
+from dune.codegen.pdelab.driver import (isPk,
+                                        isQk,
+                                        )
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.pdelab.quadrature import pymbolic_quadrature_position_in_cell
+from dune.codegen.pdelab.spaces import type_leaf_gfs
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.blockstructured.spaces import lfs_inames
+from dune.codegen.blockstructured.tools import tensor_index_to_sequential_index
 
 from ufl import MixedElement
 
diff --git a/python/dune/perftool/blockstructured/geometry.py b/python/dune/codegen/blockstructured/geometry.py
similarity index 94%
rename from python/dune/perftool/blockstructured/geometry.py
rename to python/dune/codegen/blockstructured/geometry.py
index f0d1ed6bf78796a150e7a5991217a96cf2c1d318..4f1a71d3e3674ea768ef63842ca5aa4def21db61 100644
--- a/python/dune/perftool/blockstructured/geometry.py
+++ b/python/dune/codegen/blockstructured/geometry.py
@@ -1,18 +1,18 @@
-from dune.perftool.pdelab.restriction import restricted_name
-
-from dune.perftool.generation import (get_backend,
-                                      temporary_variable,
-                                      instruction,
-                                      get_global_context_value)
-from dune.perftool.tools import get_pymbolic_basename
-from dune.perftool.options import (get_form_option,
-                                   option_switch, get_option)
-from dune.perftool.pdelab.geometry import (world_dimension,
-                                           local_dimension,
-                                           name_facet_jacobian_determinant,
-                                           name_element_corners,
-                                           component_iname)
-from dune.perftool.blockstructured.tools import sub_element_inames
+from dune.codegen.pdelab.restriction import restricted_name
+
+from dune.codegen.generation import (get_backend,
+                                     temporary_variable,
+                                     instruction,
+                                     get_global_context_value)
+from dune.codegen.tools import get_pymbolic_basename
+from dune.codegen.options import (get_form_option,
+                                  option_switch, get_option)
+from dune.codegen.pdelab.geometry import (world_dimension,
+                                          local_dimension,
+                                          name_facet_jacobian_determinant,
+                                          name_element_corners,
+                                          component_iname)
+from dune.codegen.blockstructured.tools import sub_element_inames
 import pymbolic.primitives as prim
 from loopy.match import Writes
 
@@ -189,7 +189,7 @@ def name_jacobian_determinant_abs():
 # scale determinant according to the order of the blockstructuring
 def pymbolic_jacobian_determinant():
     if get_form_option("constant_transformation_matrix"):
-        from dune.perftool.pdelab.geometry import name_jacobian_determinant
+        from dune.codegen.pdelab.geometry import name_jacobian_determinant
         n_det = name_jacobian_determinant()
     else:
         n_det = name_jacobian_determinant_abs()
@@ -264,7 +264,7 @@ def name_jacobian_inverse_transposed(restriction):
 # scale Jacobian according to the order of the blockstructure
 def pymbolic_jacobian_inverse(i, j, restriction):
     if get_form_option("constant_transformation_matrix"):
-        from dune.perftool.pdelab.geometry import name_constant_jacobian_inverse_transposed
+        from dune.codegen.pdelab.geometry import name_constant_jacobian_inverse_transposed
         name_jit = name_constant_jacobian_inverse_transposed(restriction)
     else:
         name_jit = name_jacobian_inverse_transposed(restriction)
@@ -385,7 +385,7 @@ def to_global(local):
         else:
             apply_default_to_global_transformation(name, prim.Variable(macro))
     elif it == 'exterior_facet' or it == 'interior_facet':
-        from dune.perftool.pdelab.geometry import apply_to_global_transformation
+        from dune.codegen.pdelab.geometry import apply_to_global_transformation
         apply_to_global_transformation(name, prim.Variable(macro))
     else:
         raise NotImplementedError
diff --git a/python/dune/perftool/blockstructured/quadrature.py b/python/dune/codegen/blockstructured/quadrature.py
similarity index 64%
rename from python/dune/perftool/blockstructured/quadrature.py
rename to python/dune/codegen/blockstructured/quadrature.py
index cb97bac4db61f2b22c6606a6c7d67905e512036b..4c78d733866b79817f1d7f43189e157d8967fa76 100644
--- a/python/dune/perftool/blockstructured/quadrature.py
+++ b/python/dune/codegen/blockstructured/quadrature.py
@@ -1,7 +1,7 @@
-from dune.perftool.generation import (backend)
-from dune.perftool.pdelab.quadrature import (name_quadrature_points,
-                                             quadrature_iname)
-from dune.perftool.blockstructured.geometry import name_point_in_macro
+from dune.codegen.generation import (backend)
+from dune.codegen.pdelab.quadrature import (name_quadrature_points,
+                                            quadrature_iname)
+from dune.codegen.blockstructured.geometry import name_point_in_macro
 import pymbolic.primitives as prim
 
 
@@ -17,6 +17,6 @@ def pymbolic_quadrature_position():
 
 @backend(interface="qp_in_cell", name="blockstructured")
 def pymbolic_quadrature_position_in_cell(restriction):
-    from dune.perftool.pdelab.geometry import to_cell_coordinates
+    from dune.codegen.pdelab.geometry import to_cell_coordinates
     quad_pos = pymbolic_quadrature_position()
     return to_cell_coordinates(quad_pos, restriction)
diff --git a/python/dune/perftool/blockstructured/spaces.py b/python/dune/codegen/blockstructured/spaces.py
similarity index 69%
rename from python/dune/perftool/blockstructured/spaces.py
rename to python/dune/codegen/blockstructured/spaces.py
index 1f39a9d2ee51c228f9dc4acb96c7530ad9dea3ce..688b1984a7cac29922de43d2dae5ad35313cebc5 100644
--- a/python/dune/perftool/blockstructured/spaces.py
+++ b/python/dune/codegen/blockstructured/spaces.py
@@ -1,7 +1,7 @@
-from dune.perftool.generation import (backend,
-                                      domain)
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.pdelab.spaces import name_leaf_lfs
+from dune.codegen.generation import (backend,
+                                     domain)
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.pdelab.spaces import name_leaf_lfs
 
 
 def lfs_inames(element, restriction, count=None, context=''):
@@ -16,8 +16,8 @@ def lfs_inames(element, restriction, count=None, context=''):
 
     # register transformation
     # warning: this will register the transformation a couple of times
-    from dune.perftool.generation import transform
-    from dune.perftool. blockstructured.transformations import blockstructured_iname_duplication
+    from dune.codegen.generation import transform
+    from dune.codegen. blockstructured.transformations import blockstructured_iname_duplication
     transform(blockstructured_iname_duplication)
 
     dim_names = ["x", "y", "z"] + [str(i) for i in range(4, world_dimension() + 1)]
diff --git a/python/dune/perftool/blockstructured/tools.py b/python/dune/codegen/blockstructured/tools.py
similarity index 85%
rename from python/dune/perftool/blockstructured/tools.py
rename to python/dune/codegen/blockstructured/tools.py
index a9bf01f26f5a52daa91f6cbbcf01bd31dffabb36..3eafcae5914f21538766960d75dbdb2fa2e728ad 100644
--- a/python/dune/perftool/blockstructured/tools.py
+++ b/python/dune/codegen/blockstructured/tools.py
@@ -1,17 +1,17 @@
-from dune.perftool.ufl.modified_terminals import Restriction
-from dune.perftool.generation import (iname,
-                                      domain,
-                                      get_global_context_value,
-                                      temporary_variable,
-                                      instruction)
-from dune.perftool.pdelab.geometry import (local_dimension,
-                                           world_dimension,
-                                           name_localcenter,
-                                           pymbolic_in_cell_coordinates)
-
-from dune.perftool.pdelab.quadrature import quadrature_inames
-from dune.perftool.generation.counter import get_counted_variable
-from dune.perftool.options import get_form_option
+from dune.codegen.ufl.modified_terminals import Restriction
+from dune.codegen.generation import (iname,
+                                     domain,
+                                     get_global_context_value,
+                                     temporary_variable,
+                                     instruction)
+from dune.codegen.pdelab.geometry import (local_dimension,
+                                          world_dimension,
+                                          name_localcenter,
+                                          pymbolic_in_cell_coordinates)
+
+from dune.codegen.pdelab.quadrature import quadrature_inames
+from dune.codegen.generation.counter import get_counted_variable
+from dune.codegen.options import get_form_option
 import pymbolic.primitives as prim
 
 
diff --git a/python/dune/perftool/blockstructured/transformations.py b/python/dune/codegen/blockstructured/transformations.py
similarity index 100%
rename from python/dune/perftool/blockstructured/transformations.py
rename to python/dune/codegen/blockstructured/transformations.py
diff --git a/python/dune/perftool/blockstructured/vectorization.py b/python/dune/codegen/blockstructured/vectorization.py
similarity index 97%
rename from python/dune/perftool/blockstructured/vectorization.py
rename to python/dune/codegen/blockstructured/vectorization.py
index f8caeef4e562bd7550aee96c51ca86b38e5a9b53..b35918b23b3d6e8eebf12d6ef08c94a927d692f9 100644
--- a/python/dune/perftool/blockstructured/vectorization.py
+++ b/python/dune/codegen/blockstructured/vectorization.py
@@ -4,14 +4,14 @@ import pymbolic.primitives as prim
 
 from loopy.match import Tagged, Id, Writes, Or
 
-from dune.perftool.generation import get_global_context_value
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.loopy.temporary import DuneTemporaryVariable
-from dune.perftool.loopy.symbolic import substitute
-from dune.perftool.loopy.vcl import get_vcl_type_size, VCLPermute, VCLLoad, VCLStore
-from dune.perftool.options import get_form_option
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.tools import get_pymbolic_basename
+from dune.codegen.generation import get_global_context_value
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.loopy.temporary import DuneTemporaryVariable
+from dune.codegen.loopy.symbolic import substitute
+from dune.codegen.loopy.vcl import get_vcl_type_size, VCLPermute, VCLLoad, VCLStore
+from dune.codegen.options import get_form_option
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.tools import get_pymbolic_basename
 
 
 def add_vcl_temporaries(knl):
@@ -308,8 +308,8 @@ def add_vcl_access(knl, iname_inner):
                                          expr.aggregate.name.replace('vec', 'alias') ==
                                          assignee_alias.aggregate.name.replace('dummy_', '')))
                 except StopIteration:
-                    from dune.perftool.error import PerftoolVectorizationError
-                    raise PerftoolVectorizationError
+                    from dune.codegen.error import CodegenVectorizationError
+                    raise CodegenVectorizationError
                 new_insns.append(insn.copy(assignee=assignee_vec,
                                            depends_on=(insn.depends_on | read_dependencies[insn.id] |
                                                        write_ids)))
diff --git a/python/dune/perftool/cgen/__init__.py b/python/dune/codegen/cgen/__init__.py
similarity index 83%
rename from python/dune/perftool/cgen/__init__.py
rename to python/dune/codegen/cgen/__init__.py
index 24af73e0d8a2b6dfce3c1146d86c9eeccf7e5a2a..a2fceb656af96f29348393265ad386d8a2358cea 100644
--- a/python/dune/perftool/cgen/__init__.py
+++ b/python/dune/codegen/cgen/__init__.py
@@ -2,8 +2,8 @@ from __future__ import absolute_import
 
 from cgen import *
 
-from dune.perftool.cgen.clazz import Class
-from dune.perftool.cgen.exceptions import TryCatchBlock, CatchBlock
+from dune.codegen.cgen.clazz import Class
+from dune.codegen.cgen.exceptions import TryCatchBlock, CatchBlock
 
 
 class Namespace(PrivateNamespace):
diff --git a/python/dune/perftool/cgen/clazz.py b/python/dune/codegen/cgen/clazz.py
similarity index 95%
rename from python/dune/perftool/cgen/clazz.py
rename to python/dune/codegen/cgen/clazz.py
index 7f74353f8a8ad09960e4aaa5340c83c8fe0357b6..427e3451aadb4552ecd110189b00ca1853b812e3 100644
--- a/python/dune/perftool/cgen/clazz.py
+++ b/python/dune/codegen/cgen/clazz.py
@@ -1,4 +1,4 @@
-from dune.perftool.error import PerftoolCodegenError
+from dune.codegen.error import CodegenCodegenError
 
 from cgen import Generable, Block
 
@@ -16,7 +16,7 @@ def access_modifier_string(am):
         return "public"
     if am == AccessModifier.PROTECTED:
         return "protected"
-    raise PerftoolCodegenError("Unknown access modifier in class generation")
+    raise CodegenCodegenError("Unknown access modifier in class generation")
 
 
 class BaseClass(Generable):
diff --git a/python/dune/perftool/cgen/exceptions.py b/python/dune/codegen/cgen/exceptions.py
similarity index 100%
rename from python/dune/perftool/cgen/exceptions.py
rename to python/dune/codegen/cgen/exceptions.py
diff --git a/python/dune/perftool/compile.py b/python/dune/codegen/compile.py
similarity index 80%
rename from python/dune/perftool/compile.py
rename to python/dune/codegen/compile.py
index ed4c1310a9274528a3764f2739d7ee59c025ef21..8a6e66b09f2c22135dfe4aa1ca4c9605e07579ae 100644
--- a/python/dune/perftool/compile.py
+++ b/python/dune/codegen/compile.py
@@ -13,18 +13,18 @@ import loopy
 from ufl.algorithms import compute_form_data, read_ufl_file
 from ufl.algorithms.formfiles import interpret_ufl_namespace
 
-from dune.perftool.generation import (delete_cache_items,
-                                      global_context,
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   initialize_options,
-                                   )
-from dune.perftool.pdelab.driver import generate_driver
-from dune.perftool.pdelab.localoperator import (generate_localoperator_file,
-                                                generate_localoperator_kernels,
-                                                )
-from dune.perftool.ufl.preprocess import preprocess_form
+from dune.codegen.generation import (delete_cache_items,
+                                     global_context,
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  initialize_options,
+                                  )
+from dune.codegen.pdelab.driver import generate_driver
+from dune.codegen.pdelab.localoperator import (generate_localoperator_file,
+                                               generate_localoperator_kernels,
+                                               )
+from dune.codegen.ufl.preprocess import preprocess_form
 
 from os.path import splitext, basename, join, dirname, abspath
 
@@ -71,13 +71,13 @@ def read_ufl(uflfile):
             namespace[k] = type_guessing(v)
 
     try:
-        exec("from dune.perftool.ufl.execution import *\n" + uflcode, namespace)
+        exec("from dune.codegen.ufl.execution import *\n" + uflcode, namespace)
     except:
         name = splitext(basename(uflfile))[0]
         name = "{}_debug".format(name)
         pyname = "{}.py".format(name)
         print(pyname)
-        pycode = "#!/usr/bin/env python\nfrom dune.perftool.ufl.execution import *\nset_level(DEBUG)\n"
+        pycode = "#!/usr/bin/env python\nfrom dune.codegen.ufl.execution import *\nset_level(DEBUG)\n"
         for k, v in ini.get("formcompiler.ufl_variants", {}).items():
             pycode = pycode + "{} = {}\n".format(k, repr(type_guessing(v)))
         pycode = pycode + uflcode
diff --git a/python/dune/codegen/error.py b/python/dune/codegen/error.py
new file mode 100644
index 0000000000000000000000000000000000000000..04484f25a9874fe1c753b9a0adb40e6501dfe5ab
--- /dev/null
+++ b/python/dune/codegen/error.py
@@ -0,0 +1,25 @@
+""" Some error classes for dune-codegen """
+
+
+class CodegenError(Exception):
+    pass
+
+
+class CodegenUFLError(CodegenError):
+    pass
+
+
+class CodegenCodegenError(CodegenError):
+    pass
+
+
+class CodegenLoopyError(CodegenError):
+    pass
+
+
+class CodegenVectorizationError(CodegenCodegenError):
+    pass
+
+
+class CodegenAutotuneError(CodegenVectorizationError):
+    pass
diff --git a/python/dune/perftool/file.py b/python/dune/codegen/file.py
similarity index 97%
rename from python/dune/perftool/file.py
rename to python/dune/codegen/file.py
index 187f32dbe24f4d00cf6b76581e7b55434298d236..cf60f37d848b088dc4088b6c36b34a045533b62f 100644
--- a/python/dune/perftool/file.py
+++ b/python/dune/codegen/file.py
@@ -2,7 +2,7 @@
 
 from cgen import Generable, Include
 
-from dune.perftool.generation import retrieve_cache_items
+from dune.codegen.generation import retrieve_cache_items
 
 
 def generate_file(filename, tag, content, headerguard=True):
diff --git a/python/dune/codegen/generation/__init__.py b/python/dune/codegen/generation/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3103bac657648779921eb66c7170f5a55059e209
--- /dev/null
+++ b/python/dune/codegen/generation/__init__.py
@@ -0,0 +1,60 @@
+from __future__ import absolute_import
+
+from dune.codegen.generation.backend import (backend,
+                                             get_backend,
+                                             )
+
+from dune.codegen.generation.counter import (get_counter,
+                                             get_counted_variable,
+                                             )
+
+from dune.codegen.generation.cache import (cached,
+                                           generator_factory,
+                                           no_caching,
+                                           retrieve_cache_functions,
+                                           retrieve_cache_items,
+                                           delete_cache_items,
+                                           inspect_generator,
+                                           )
+
+from dune.codegen.generation.cpp import (base_class,
+                                         class_basename,
+                                         class_member,
+                                         constructor_parameter,
+                                         dump_accumulate_timer,
+                                         end_of_file,
+                                         include_file,
+                                         initializer_list,
+                                         pre_include,
+                                         preamble,
+                                         post_include,
+                                         template_parameter,
+                                         )
+
+from dune.codegen.generation.hooks import (hook,
+                                           ReturnArg,
+                                           run_hook,
+                                           )
+
+from dune.codegen.generation.loopy import (barrier,
+                                           constantarg,
+                                           domain,
+                                           function_mangler,
+                                           get_temporary_name,
+                                           globalarg,
+                                           iname,
+                                           instruction,
+                                           loopy_class_member,
+                                           kernel_cached,
+                                           noop_instruction,
+                                           silenced_warning,
+                                           subst_rule,
+                                           temporary_variable,
+                                           transform,
+                                           valuearg,
+                                           )
+
+from dune.codegen.generation.context import (cache_restoring,
+                                             global_context,
+                                             get_global_context_value,
+                                             )
diff --git a/python/dune/perftool/generation/backend.py b/python/dune/codegen/generation/backend.py
similarity index 91%
rename from python/dune/perftool/generation/backend.py
rename to python/dune/codegen/generation/backend.py
index 6bd6544c019f3f882bc541e3cce883d7a481f096..a45f7ac8be21f3c358e3473a4bc9a51e4deeb9f2 100644
--- a/python/dune/perftool/generation/backend.py
+++ b/python/dune/codegen/generation/backend.py
@@ -1,5 +1,5 @@
-from dune.perftool.generation.cache import _RegisteredFunction
-from dune.perftool.options import option_switch
+from dune.codegen.generation.cache import _RegisteredFunction
+from dune.codegen.options import option_switch
 from pytools import Record
 
 
diff --git a/python/dune/perftool/generation/cache.py b/python/dune/codegen/generation/cache.py
similarity index 96%
rename from python/dune/perftool/generation/cache.py
rename to python/dune/codegen/generation/cache.py
index 31b1b85e0da2797a158b4d49ed10bdf89d7dfe0b..223ab1bf6012bab7e19043a6163b936221735fe2 100644
--- a/python/dune/perftool/generation/cache.py
+++ b/python/dune/codegen/generation/cache.py
@@ -3,11 +3,11 @@ generating functions.
 """
 import inspect
 
-from dune.perftool.generation.context import (get_global_context_value,
-                                              global_context,
-                                              )
-from dune.perftool.generation.counter import get_counter
-from dune.perftool.options import get_option
+from dune.codegen.generation.context import (get_global_context_value,
+                                             global_context,
+                                             )
+from dune.codegen.generation.counter import get_counter
+from dune.codegen.options import get_option
 
 # Store a global list of generator functions
 _generators = []
@@ -90,7 +90,7 @@ class _RegisteredFunction(object):
 
         # Allow order independence of the backend and the generator decorators.
         # If backend was applied first, we resolve the issued FuncProxy object
-        from dune.perftool.generation.backend import FuncProxy, register_backend
+        from dune.codegen.generation.backend import FuncProxy, register_backend
         if isinstance(self.func, FuncProxy):
             register_backend(self.func.interface, self.func.name, self)
             self.func = self.func.func
diff --git a/python/dune/perftool/generation/context.py b/python/dune/codegen/generation/context.py
similarity index 95%
rename from python/dune/perftool/generation/context.py
rename to python/dune/codegen/generation/context.py
index 4be1125a2deb0a695f1815f82293d29dc81880f2..cf22ddd4ef4a0dd731c2d3f6cffd805b8b47248c 100644
--- a/python/dune/perftool/generation/context.py
+++ b/python/dune/codegen/generation/context.py
@@ -35,7 +35,7 @@ def get_global_context_value(key, default=None):
 
 class _CacheRestoringContext(object):
     def __enter__(self):
-        from dune.perftool.generation.cache import _generators as g
+        from dune.codegen.generation.cache import _generators as g
         self.cache = {}
         for i in g:
             self.cache[i] = {}
diff --git a/python/dune/perftool/generation/counter.py b/python/dune/codegen/generation/counter.py
similarity index 100%
rename from python/dune/perftool/generation/counter.py
rename to python/dune/codegen/generation/counter.py
diff --git a/python/dune/perftool/generation/cpp.py b/python/dune/codegen/generation/cpp.py
similarity index 89%
rename from python/dune/perftool/generation/cpp.py
rename to python/dune/codegen/generation/cpp.py
index 858dc1fcaf50d07b08c044525db994f85ca8de29..29384f98554ab895d37670c017fe5ecc4f191655 100644
--- a/python/dune/perftool/generation/cpp.py
+++ b/python/dune/codegen/generation/cpp.py
@@ -2,9 +2,9 @@
 Define some generators based on the caching mechanism that
 are commonly needed for code generation
 """
-from dune.perftool.options import get_option
-from dune.perftool.generation import generator_factory
-from dune.perftool.cgen.clazz import AccessModifier, BaseClass, ClassMember
+from dune.codegen.options import get_option
+from dune.codegen.generation import generator_factory
+from dune.codegen.cgen.clazz import AccessModifier, BaseClass, ClassMember
 
 import cgen
 
@@ -43,7 +43,7 @@ def constructor_parameter(_type, name):
 
 @generator_factory(item_tags=("dump_timers",))
 def dump_accumulate_timer(name):
-    from dune.perftool.pdelab.localoperator import name_time_dumper_os
+    from dune.codegen.pdelab.localoperator import name_time_dumper_os
     os = name_time_dumper_os()
     # reset = name_time_dumper_reset()
     reset = 'false'
diff --git a/python/dune/perftool/generation/hooks.py b/python/dune/codegen/generation/hooks.py
similarity index 94%
rename from python/dune/perftool/generation/hooks.py
rename to python/dune/codegen/generation/hooks.py
index 31b35754ad44badfabea090e7c82b0ed55c1871d..96e68c83a58e3e3e130bfc0b2407e1670d353709 100644
--- a/python/dune/perftool/generation/hooks.py
+++ b/python/dune/codegen/generation/hooks.py
@@ -29,7 +29,7 @@ class ReturnArg(object):
 
 def run_hook(name=None, args=[], kwargs={}):
     if name is None:
-        raise PerftoolError("Running hook requires the hook name!")
+        raise CodegenError("Running hook requires the hook name!")
 
     # Handle occurences of ReturnArg in the given arguments
     occ = list(isinstance(a, ReturnArg) for a in args)
diff --git a/python/dune/perftool/generation/loopy.py b/python/dune/codegen/generation/loopy.py
similarity index 93%
rename from python/dune/perftool/generation/loopy.py
rename to python/dune/codegen/generation/loopy.py
index a4d8292f5f88bc315980efb521bf7c2cf6a95153..47d78fb8d4ea2eb405ed57b0e0ffab10babbd7b2 100644
--- a/python/dune/perftool/generation/loopy.py
+++ b/python/dune/codegen/generation/loopy.py
@@ -1,12 +1,12 @@
 """ The loopy specific generators """
 from __future__ import absolute_import
 
-from dune.perftool.generation import (get_counter,
-                                      generator_factory,
-                                      no_caching,
-                                      preamble,
-                                      )
-from dune.perftool.error import PerftoolLoopyError
+from dune.codegen.generation import (get_counter,
+                                     generator_factory,
+                                     no_caching,
+                                     preamble,
+                                     )
+from dune.codegen.error import CodegenLoopyError
 
 import loopy as lp
 import numpy as np
@@ -27,7 +27,7 @@ class DuneGlobalArg(lp.GlobalArg):
 def globalarg(name, shape=lp.auto, managed=True, **kw):
     if isinstance(shape, str):
         shape = (shape,)
-    from dune.perftool.loopy.target import dtype_floatingpoint
+    from dune.codegen.loopy.target import dtype_floatingpoint
     dtype = kw.pop("dtype", dtype_floatingpoint())
     return DuneGlobalArg(name, dtype=dtype, shape=shape, managed=managed, **kw)
 
@@ -39,7 +39,7 @@ def constantarg(name, shape=None, **kw):
     if isinstance(shape, str):
         shape = (shape,)
 
-    from dune.perftool.loopy.target import dtype_floatingpoint
+    from dune.codegen.loopy.target import dtype_floatingpoint
     dtype = kw.pop("dtype", dtype_floatingpoint())
     return lp.GlobalArg(name, dtype=dtype, shape=shape, **kw)
 
@@ -48,7 +48,7 @@ def constantarg(name, shape=None, **kw):
                    context_tags="kernel",
                    cache_key_generator=lambda n, **kw: n)
 def valuearg(name, **kw):
-    from dune.perftool.loopy.target import dtype_floatingpoint
+    from dune.codegen.loopy.target import dtype_floatingpoint
     dtype = kw.pop("dtype", dtype_floatingpoint())
     return lp.ValueArg(name, dtype=dtype, **kw)
 
@@ -81,7 +81,7 @@ def get_temporary_name():
                    context_tags="kernel",
                    cache_key_generator=lambda n, **kw: n)
 def temporary_variable(name, **kwargs):
-    from dune.perftool.loopy.temporary import DuneTemporaryVariable
+    from dune.codegen.loopy.temporary import DuneTemporaryVariable
     return DuneTemporaryVariable(name, scope=lp.temp_var_scope.PRIVATE, **kwargs)
 
 
diff --git a/python/dune/perftool/logging.conf b/python/dune/codegen/logging.conf
similarity index 60%
rename from python/dune/perftool/logging.conf
rename to python/dune/codegen/logging.conf
index e89555eddae02f3e5ea251e42ad2b70ded41e7a6..32974b12744dd1c23c36f561148943ec936b3ccb 100644
--- a/python/dune/perftool/logging.conf
+++ b/python/dune/codegen/logging.conf
@@ -1,5 +1,5 @@
 [loggers]
-keys=root,dune.perftool.pdelab.localoperator,dune.perftool.sumfact.vectorization
+keys=root,dune.codegen.pdelab.localoperator,dune.codegen.sumfact.vectorization
 
 [handlers]
 keys=consoleHandler
@@ -10,16 +10,16 @@ keys=simpleFormatter
 [logger_root]
 handlers=consoleHandler
 
-[logger_dune.perftool.pdelab.localoperator]
+[logger_dune.codegen.pdelab.localoperator]
 level=INFO
 handlers=consoleHandler
-qualname=dune.perftool.pdelab.localoperator
+qualname=dune.codegen.pdelab.localoperator
 propagate=0
 
-[logger_dune.perftool.sumfact.vectorization]
+[logger_dune.codegen.sumfact.vectorization]
 level=INFO
 handlers=consoleHandler
-qualname=dune.perftool.sumfact.vectorization
+qualname=dune.codegen.sumfact.vectorization
 propagate=0
 
 [handler_consoleHandler]
diff --git a/python/dune/codegen/loopy/__init__.py b/python/dune/codegen/loopy/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd25095a28606aa9b63248a0f6c9773f6a34c93a
--- /dev/null
+++ b/python/dune/codegen/loopy/__init__.py
@@ -0,0 +1,3 @@
+""" Export the interface interesting to the rest of the project """
+
+from dune.codegen.loopy.transformations.duplicate import heuristic_duplication
diff --git a/python/dune/perftool/loopy/flatten.py b/python/dune/codegen/loopy/flatten.py
similarity index 100%
rename from python/dune/perftool/loopy/flatten.py
rename to python/dune/codegen/loopy/flatten.py
diff --git a/python/dune/perftool/loopy/mangler.py b/python/dune/codegen/loopy/mangler.py
similarity index 84%
rename from python/dune/perftool/loopy/mangler.py
rename to python/dune/codegen/loopy/mangler.py
index 21dc1a1caf5996befc4ad436dbbdbc9db89b1493..1f082cfddce8d378e4df98037afbe6c2925f2e92 100644
--- a/python/dune/perftool/loopy/mangler.py
+++ b/python/dune/codegen/loopy/mangler.py
@@ -1,9 +1,9 @@
 """ Function manglers for math functions in C++ """
 
-from dune.perftool.generation import (function_mangler,
-                                      include_file,
-                                      post_include
-                                      )
+from dune.codegen.generation import (function_mangler,
+                                     include_file,
+                                     post_include
+                                     )
 
 from loopy import CallMangleInfo
 from loopy.types import to_loopy_type
@@ -20,7 +20,7 @@ def dune_math_manglers(kernel, name, arg_dtypes):
     if name == "exp":
         dt = arg_dtypes[0]
         using_std_statement(name)
-        include_file("dune/perftool/common/vectorclass.hh", filetag="operatorfile")
+        include_file("dune/codegen/common/vectorclass.hh", filetag="operatorfile")
         return CallMangleInfo("exp",
                               arg_dtypes,
                               arg_dtypes,
@@ -63,5 +63,5 @@ def get_time_function_mangler(kernel, name, arg_dtypes):
     """
     if name == "getTime":
         assert(len(arg_dtypes) == 0)
-        from dune.perftool.loopy.target import dtype_floatingpoint
+        from dune.codegen.loopy.target import dtype_floatingpoint
         return CallMangleInfo("this->getTime", (to_loopy_type(dtype_floatingpoint()),), ())
diff --git a/python/dune/perftool/loopy/symbolic.py b/python/dune/codegen/loopy/symbolic.py
similarity index 95%
rename from python/dune/perftool/loopy/symbolic.py
rename to python/dune/codegen/loopy/symbolic.py
index 01a992254ede29057ab972cf1b494c1e99f21237..799c7d6040e2e7d9e40c296d73c391aeb43cc6f3 100644
--- a/python/dune/perftool/loopy/symbolic.py
+++ b/python/dune/codegen/loopy/symbolic.py
@@ -2,8 +2,8 @@
 
 Use this module to insert pymbolic nodes and the likes.
 """
-from dune.perftool.error import PerftoolError
-from dune.perftool.sumfact.symbolic import SumfactKernel, VectorizedSumfactKernel
+from dune.codegen.error import CodegenError
+from dune.codegen.sumfact.symbolic import SumfactKernel, VectorizedSumfactKernel
 from pymbolic.mapper.substitutor import make_subst_func
 
 import loopy as lp
@@ -57,7 +57,7 @@ def dependency_map_sumfact_kernel(self, expr):
 
 
 def needs_resolution(self, expr):
-    raise PerftoolError("SumfactKernel node is a placeholder and needs to be removed!")
+    raise CodegenError("SumfactKernel node is a placeholder and needs to be removed!")
 
 
 def identity_map_fused_multiply_add(self, expr, *args):
diff --git a/python/dune/perftool/loopy/target.py b/python/dune/codegen/loopy/target.py
similarity index 93%
rename from python/dune/perftool/loopy/target.py
rename to python/dune/codegen/loopy/target.py
index 9c551db9a6788b5628a3eb8c5eba287846b5a281..b8dd4d2552fb38b753be02fd6279074b4276d825 100644
--- a/python/dune/perftool/loopy/target.py
+++ b/python/dune/codegen/loopy/target.py
@@ -1,15 +1,15 @@
 import numpy as np
 
-from dune.perftool.generation import post_include
+from dune.codegen.generation import post_include
 
-from dune.perftool.generation.loopy import DuneGlobalArg
-from dune.perftool.loopy.temporary import DuneTemporaryVariable
-from dune.perftool.loopy.vcl import VCLTypeRegistry
-from dune.perftool.generation import (include_file,
-                                      retrieve_cache_functions,
-                                      )
-from dune.perftool.options import get_form_option, get_option
-from dune.perftool.tools import round_to_multiple
+from dune.codegen.generation.loopy import DuneGlobalArg
+from dune.codegen.loopy.temporary import DuneTemporaryVariable
+from dune.codegen.loopy.vcl import VCLTypeRegistry
+from dune.codegen.generation import (include_file,
+                                     retrieve_cache_functions,
+                                     )
+from dune.codegen.options import get_form_option, get_option
+from dune.codegen.tools import round_to_multiple
 
 from loopy.symbolic import Literal
 from loopy.target import (TargetBase,
@@ -104,7 +104,7 @@ class DuneExpressionToCExpressionMapper(ExpressionToCExpressionMapper):
 
     def map_fused_multiply_add(self, expr, type_context):
         if self.codegen_state.vectorization_info:
-            include_file("dune/perftool/common/muladd_workarounds.hh", filetag="operatorfile")
+            include_file("dune/codegen/common/muladd_workarounds.hh", filetag="operatorfile")
             # If this is vectorized we call the VCL function mul_add
             return prim.Call(prim.Variable("mul_add"),
                              (self.rec(expr.mul_op1, type_context),
@@ -256,7 +256,7 @@ class DuneTarget(TargetBase):
 
     def dtype_to_typename(self, dtype):
         if dtype.dtype.kind == "V":
-            include_file("dune/perftool/common/vectorclass.hh", filetag="operatorfile")
+            include_file("dune/codegen/common/vectorclass.hh", filetag="operatorfile")
             return VCLTypeRegistry.names[dtype.dtype]
         else:
             return numpy_to_cpp_dtype(dtype.dtype.name)
diff --git a/python/dune/perftool/loopy/temporary.py b/python/dune/codegen/loopy/temporary.py
similarity index 92%
rename from python/dune/perftool/loopy/temporary.py
rename to python/dune/codegen/loopy/temporary.py
index 89d7b0596a38a2373a48b90b80a0740ce91fd9bd..716d1c86ff6c4f9ae7b3b6d04892bde9167ce72a 100644
--- a/python/dune/perftool/loopy/temporary.py
+++ b/python/dune/codegen/loopy/temporary.py
@@ -1,7 +1,7 @@
 """
 Class for temporary variables that allows us to use very non-standard types.
 """
-from dune.perftool.error import PerftoolLoopyError
+from dune.codegen.error import CodegenLoopyError
 
 from loopy import TemporaryVariable
 
@@ -10,12 +10,12 @@ import numpy
 
 
 def _temporary_type(shape_impl, shape, first=True):
-    from dune.perftool.loopy.target import type_floatingpoint
+    from dune.codegen.loopy.target import type_floatingpoint
     if len(shape_impl) == 0:
         return type_floatingpoint()
     if shape_impl[0] == 'arr':
         if not first or len(set(shape_impl)) != 1:
-            raise PerftoolLoopyError("We do not allow mixing of C++ containers and plain C arrays, for reasons of mental sanity")
+            raise CodegenLoopyError("We do not allow mixing of C++ containers and plain C arrays, for reasons of mental sanity")
         return type_floatingpoint()
     if shape_impl[0] == 'vec':
         return "std::vector<{}>".format(_temporary_type(shape_impl[1:], shape[1:], first=False))
@@ -86,7 +86,7 @@ class DuneTemporaryVariable(TemporaryVariable):
         if shape_impl is not None:
             self.decl_method = default_declaration
 
-        from dune.perftool.loopy.target import dtype_floatingpoint
+        from dune.codegen.loopy.target import dtype_floatingpoint
         kwargs.setdefault('dtype', dtype_floatingpoint())
 
         if custom_base_storage and self.decl_method is None:
diff --git a/python/dune/perftool/loopy/transformations/__init__.py b/python/dune/codegen/loopy/transformations/__init__.py
similarity index 100%
rename from python/dune/perftool/loopy/transformations/__init__.py
rename to python/dune/codegen/loopy/transformations/__init__.py
diff --git a/python/dune/perftool/loopy/transformations/duplicate.py b/python/dune/codegen/loopy/transformations/duplicate.py
similarity index 100%
rename from python/dune/perftool/loopy/transformations/duplicate.py
rename to python/dune/codegen/loopy/transformations/duplicate.py
diff --git a/python/dune/perftool/loopy/transformations/instrumentation.py b/python/dune/codegen/loopy/transformations/instrumentation.py
similarity index 96%
rename from python/dune/perftool/loopy/transformations/instrumentation.py
rename to python/dune/codegen/loopy/transformations/instrumentation.py
index 2771ba141ccf5978067e3569038c4307bd01a357..7b13a09e597490dd1bef85344c9be6bdfb859dd3 100644
--- a/python/dune/perftool/loopy/transformations/instrumentation.py
+++ b/python/dune/codegen/loopy/transformations/instrumentation.py
@@ -1,9 +1,9 @@
 """ Add instrumentation instructions to a kernel """
 
-from dune.perftool.generation import (dump_accumulate_timer,
-                                      post_include,
-                                      )
-from dune.perftool.options import get_option
+from dune.codegen.generation import (dump_accumulate_timer,
+                                     post_include,
+                                     )
+from dune.codegen.options import get_option
 
 import loopy as lp
 
diff --git a/python/dune/perftool/loopy/transformations/matchfma.py b/python/dune/codegen/loopy/transformations/matchfma.py
similarity index 94%
rename from python/dune/perftool/loopy/transformations/matchfma.py
rename to python/dune/codegen/loopy/transformations/matchfma.py
index ee1d81eb1b11a44f3721e49b1bf97e13d0cf61ad..c6ed8eb3a61042ae131d3b4c9d932e7af6f4af61 100644
--- a/python/dune/perftool/loopy/transformations/matchfma.py
+++ b/python/dune/codegen/loopy/transformations/matchfma.py
@@ -1,6 +1,6 @@
 """ Match FMA in expressions! """
 
-from dune.perftool.loopy.symbolic import FusedMultiplyAdd as FMA
+from dune.codegen.loopy.symbolic import FusedMultiplyAdd as FMA
 from loopy.symbolic import SubstitutionMapper
 
 import loopy as lp
diff --git a/python/dune/perftool/loopy/transformations/vectorize_quad.py b/python/dune/codegen/loopy/transformations/vectorize_quad.py
similarity index 94%
rename from python/dune/perftool/loopy/transformations/vectorize_quad.py
rename to python/dune/codegen/loopy/transformations/vectorize_quad.py
index f1b3ce12100731e87eff358a0cc3bcef49db6beb..2ff6361f445ce44e73c659aa34bf7e4e7f02646b 100644
--- a/python/dune/perftool/loopy/transformations/vectorize_quad.py
+++ b/python/dune/codegen/loopy/transformations/vectorize_quad.py
@@ -1,19 +1,19 @@
 """ A kernel transformation that precomputes data and then splits computation
 in chunks of vector size independent of divisibility of the loop bounds. """
 
-from dune.perftool.generation import (function_mangler,
-                                      include_file,
-                                      loopy_class_member,
-                                      )
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.loopy.vcl import get_vcl_type, get_vcl_type_size
-from dune.perftool.loopy.transformations.vectorview import (add_vector_view,
-                                                            get_vector_view_name,
-                                                            )
-from dune.perftool.loopy.symbolic import substitute
-from dune.perftool.sumfact.quadrature import quadrature_inames
-from dune.perftool.tools import get_pymbolic_basename, get_pymbolic_tag, ceildiv
-from dune.perftool.options import get_option
+from dune.codegen.generation import (function_mangler,
+                                     include_file,
+                                     loopy_class_member,
+                                     )
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.loopy.vcl import get_vcl_type, get_vcl_type_size
+from dune.codegen.loopy.transformations.vectorview import (add_vector_view,
+                                                           get_vector_view_name,
+                                                           )
+from dune.codegen.loopy.symbolic import substitute
+from dune.codegen.sumfact.quadrature import quadrature_inames
+from dune.codegen.tools import get_pymbolic_basename, get_pymbolic_tag, ceildiv
+from dune.codegen.options import get_option
 
 from loopy.kernel.creation import parse_domains
 from loopy.symbolic import pw_aff_to_expr
@@ -50,7 +50,7 @@ def rotate_function_mangler(knl, func, arg_dtypes):
         # This is not 100% within the loopy philosophy, as we are
         # passing the vector registers as references and have them
         # changed. Loopy assumes this function to be read-only.
-        include_file("dune/perftool/sumfact/transposereg.hh", filetag="operatorfile")
+        include_file("dune/codegen/sumfact/transposereg.hh", filetag="operatorfile")
         vcl = lp.types.NumpyType(get_vcl_type(dtype_floatingpoint(), vector_width=func.horizontal * func.vertical))
         return lp.CallMangleInfo(func.name, (), (vcl,) * func.horizontal)
 
@@ -330,7 +330,7 @@ def vectorize_quadrature_loop(knl):
         if element is None:
             suffix = ''
         else:
-            from dune.perftool.pdelab.driver import FEM_name_mangling
+            from dune.codegen.pdelab.driver import FEM_name_mangling
             suffix = "_{}".format(FEM_name_mangling(element))
         knl = _vectorize_quadrature_loop(knl, inames.value, suffix)
 
diff --git a/python/dune/perftool/loopy/transformations/vectorview.py b/python/dune/codegen/loopy/transformations/vectorview.py
similarity index 90%
rename from python/dune/perftool/loopy/transformations/vectorview.py
rename to python/dune/codegen/loopy/transformations/vectorview.py
index 3a812abf50289b58e14bd2f155d155cc7bc3155d..0ac8bfaeb4015ffd5aef306fe00222daaa9f364d 100644
--- a/python/dune/perftool/loopy/transformations/vectorview.py
+++ b/python/dune/codegen/loopy/transformations/vectorview.py
@@ -4,10 +4,10 @@ One being an ordinary array with proper shape and so on, and one
 being a an array of SIMD vectors
 """
 
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.loopy.temporary import DuneTemporaryVariable
-from dune.perftool.loopy.vcl import get_vcl_type_size
-from dune.perftool.tools import round_to_multiple
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.loopy.temporary import DuneTemporaryVariable
+from dune.codegen.loopy.vcl import get_vcl_type_size
+from dune.codegen.tools import round_to_multiple
 
 import loopy as lp
 import numpy as np
diff --git a/python/dune/perftool/loopy/vcl.py b/python/dune/codegen/loopy/vcl.py
similarity index 96%
rename from python/dune/perftool/loopy/vcl.py
rename to python/dune/codegen/loopy/vcl.py
index 345dec931596c07c8641a03f5c0c5035f86d06b6..e0943a69ac35136abfe59a7f641e0f076681643c 100644
--- a/python/dune/perftool/loopy/vcl.py
+++ b/python/dune/codegen/loopy/vcl.py
@@ -1,8 +1,8 @@
 """
 Our extensions to the loopy type system
 """
-from dune.perftool.options import get_option
-from dune.perftool.generation import function_mangler, include_file
+from dune.codegen.options import get_option
+from dune.codegen.generation import function_mangler, include_file
 
 import loopy as lp
 import numpy as np
@@ -121,7 +121,7 @@ def vcl_function_mangler(knl, func, arg_dtypes):
     if func in ("horizontal_add", "horizontal_add_lower", "horizontal_add_upper"):
         dtype = arg_dtypes[0]
         vcl = lp.types.NumpyType(get_vcl_type(dtype))
-        include_file("dune/perftool/sumfact/horizontaladd.hh", filetag="operatorfile")
+        include_file("dune/codegen/sumfact/horizontaladd.hh", filetag="operatorfile")
         return lp.CallMangleInfo(func, (lp.types.NumpyType(dtype.dtype),), (vcl,))
 
     if isinstance(func, VCLPermute):
diff --git a/python/dune/codegen/options.py b/python/dune/codegen/options.py
new file mode 100644
index 0000000000000000000000000000000000000000..e511ccee2064fd99475b40d0d559502457305513
--- /dev/null
+++ b/python/dune/codegen/options.py
@@ -0,0 +1,263 @@
+""" Manage the command line options to the form compiler executable """
+
+from argparse import ArgumentParser
+from os.path import abspath
+from pytools import ImmutableRecord, memoize
+
+from dune.testtools.parametertree.parser import parse_ini_file
+
+
+class CodegenOption(ImmutableRecord):
+    """ Data structure representing a single formcompiler option """
+    def __init__(self,
+                 default=None,
+                 helpstr="Undocumented feature!",
+                 process=lambda x: x,
+                 _type=type(None),
+                 ):
+        _type = type(default)
+        if issubclass(_type, type(None)):
+            _type = str
+        ImmutableRecord.__init__(self,
+                                 helpstr=helpstr,
+                                 default=default,
+                                 type=_type,
+                                 )
+
+
+class CodegenGlobalOptionsArray(ImmutableRecord):
+    """ A collection of form compiler arguments """
+    def __init__(self, **kwargs):
+        opts = {k: v.default for k, v in CodegenGlobalOptionsArray.__dict__.items() if isinstance(v, CodegenOption)}
+        opts.update(**kwargs)
+        ImmutableRecord.__init__(self, **opts)
+
+    # Arguments that are to be set from the outside
+    uflfile = CodegenOption(helpstr="the UFL file to compile")
+    debug_cache_with_stack = CodegenOption(default=False, helpstr="Store stack along with cache objects. Makes debugging caching issues easier.")
+    driver_file = CodegenOption(helpstr="The filename for the generated driver header")
+    explicit_time_stepping = CodegenOption(default=False, helpstr="use explicit time stepping")
+    exact_solution_expression = CodegenOption(helpstr="name of the exact solution expression in the ufl file")
+    compare_l2errorsquared = CodegenOption(helpstr="maximal allowed l2 error squared of difference between numerical solution and interpolation of exact solution (NOTE: requires --exact-solution-expression)")
+    grid_info = CodegenOption(default=None, helpstr="Path to file with information about facedir and facemod variations. This can be used to limit the generation of skeleton kernels.")
+    l2error_tree_path = CodegenOption(default=None, helpstr="Tree pathes that should be considered for l2 error calculation. Default None means we take all of them into account.")
+    ini_file = CodegenOption(helpstr="An inifile to use. A generated driver will be hard-coded to it, a [formcompiler] section will be used as default values to form compiler arguments (use snake case)")
+    opcounter = CodegenOption(default=False, helpstr="Count operations. Note: In this case only operator applications are generated since solving and operator counting does not work. You probably want to set instrumentation level>0.")
+    performance_measuring = CodegenOption(default=False, helpstr="Generate opcounter codepath, but only measure times!")
+    instrumentation_level = CodegenOption(default=0, helpstr="Control time/opcounter measurements. 0-do nothing, 1-measure program as a whole, 2-operator applications, 3-measure kernel (eg. alpha-volume, ...), 4-parts of kernel (eg. stage 1-3 of SF)")
+    project_basedir = CodegenOption(helpstr="The base (build) directory of the dune-codegen project")
+    architecture = CodegenOption(default="haswell", helpstr="The architecture to optimize for. Possible values: haswell|knl|skylake")
+    yaspgrid_offset = CodegenOption(default=False, helpstr="Set to true if you want a yasp grid where the lower left corner is not in the origin.")
+    grid_unstructured = CodegenOption(default=False, helpstr="Set to true if you want to use an unstructured grid.")
+    precision_bits = CodegenOption(default=64, helpstr="The number of bits for the floating point type")
+    overlapping = CodegenOption(default=False, helpstr="Use an overlapping solver and constraints. You still need to make sure to construct a grid with overlap! The parallel option will be set automatically.")
+    operators = CodegenOption(default="r", helpstr="A comma separated list of operators, each name will be interpreted as a subsection name within the formcompiler section")
+    target_name = CodegenOption(default=None, helpstr="The target name from CMake")
+    operator_to_build = CodegenOption(default=None, helpstr="The operators from the list that is about to be build now. CMake sets this one!!!")
+    debug_interpolate_input = CodegenOption(default=False, helpstr="Should the input for printresidual and printmatix be interpolated (instead of random input).")
+
+    # Arguments that are mainly to be set by logic depending on other options
+    max_vector_width = CodegenOption(default=256, helpstr=None)
+    parallel = CodegenOption(default=False, helpstr="Mark that this program should be run in parallel. If set to true the c++ code will check that there are more than 1 MPI-ranks involved and the error computation will use communication.")
+
+
+class CodegenFormOptionsArray(ImmutableRecord):
+    """ A collection of form-specific form compiler arguments """
+    def __init__(self, **kwargs):
+        opts = {k: v.default for k, v in CodegenFormOptionsArray.__dict__.items() if isinstance(v, CodegenOption)}
+        opts.update(**kwargs)
+        ImmutableRecord.__init__(self, **opts)
+
+    # Form specific options
+    form = CodegenOption(default=None, helpstr="The name of the UFL object representing the form in the UFL file")
+    filename = CodegenOption(default=None, helpstr="The filename to use for this LocalOperator")
+    classname = CodegenOption(default=None, helpstr="The name of the C++ class to generate")
+    numerical_jacobian = CodegenOption(default=False, helpstr="use numerical jacobians (only makes sense, if uflpdelab for some reason fails to generate analytic jacobians)")
+    matrix_free = CodegenOption(default=False, helpstr="Generate jacobian_apply_* methods for matrix free solvers")
+    print_transformations = CodegenOption(default=False, helpstr="print out dot files after ufl tree transformations")
+    print_transformations_dir = CodegenOption(default=".", helpstr="place where to put dot files (can be omitted)")
+    quadrature_order = CodegenOption(_type=int, helpstr="Quadrature order used for all integrals.")
+    diagonal_transformation_matrix = CodegenOption(default=False, helpstr="set option if the jacobian of the transformation is diagonal (axiparallel grids)")
+    constant_transformation_matrix = CodegenOption(default=False, helpstr="set option if the jacobian of the transformation is constant on a cell")
+    fastdg = CodegenOption(default=False, helpstr="Use FastDGGridOperator from PDELab.")
+    sumfact = CodegenOption(default=False, helpstr="Use sumfactorization")
+    sumfact_regular_jacobians = CodegenOption(default=False, helpstr="Generate non sum-factorized jacobians (only useful if sumfact is set)")
+    vectorization_quadloop = CodegenOption(default=False, helpstr="whether to generate code with explicit vectorization")
+    vectorization_strategy = CodegenOption(default="none", helpstr="The identifier of the vectorization cost model. Possible values: none|explicit|model|target|autotune")
+    vectorization_not_fully_vectorized_error = CodegenOption(default=False, helpstr="throw an error if nonquadloop vectorization did not fully vectorize")
+    vectorization_horizontal = CodegenOption(default=None, helpstr="an explicit value for horizontal vectorization read by the 'explicit' strategy")
+    vectorization_vertical = CodegenOption(default=None, helpstr="an explicit value for vertical vectorization read by the 'explicit' strategy")
+    vectorization_padding = CodegenOption(default=None, helpstr="an explicit value for the allowed padding in vectorization")
+    vectorization_allow_quadrature_changes = CodegenOption(default=False, helpstr="whether the vectorization strategy is allowed to alter quadrature point numbers")
+    vectorization_list_index = CodegenOption(default=None, helpstr="Which vectorization to pick from a list (only valid with vectorization_strategy=fromlist).")
+    vectorization_jacobians = CodegenOption(default=True, helpstr="Whether to attempt to vectorize jacobians (takes time, often not needed)")
+    vectorization_target = CodegenOption(_type=float, helpstr="The cost function target for the 'target' cost model. Only needed to verify the cost model itself, do not use light-heartedly!!!")
+    simplify = CodegenOption(default=False, helpstr="Whether to simplify expressions using sympy")
+    generate_jacobians = CodegenOption(default=True, helpstr="Whether jacobian_* methods should be generated. This is set to false automatically, when numerical_jacobian is set to true.")
+    generate_jacobian_apply = CodegenOption(default=False, helpstr="Wether jacobian_allpy_* methods should be generated.")
+    generate_residuals = CodegenOption(default=True, helpstr="Whether alpha_* methods should be generated.")
+    unroll_dimension_loops = CodegenOption(default=False, helpstr="whether loops over the geometric dimension should be unrolled")
+    precompute_quadrature_info = CodegenOption(default=True, helpstr="compute quadrature points and weights in the constructor of the local operator")
+    blockstructured = CodegenOption(default=False, helpstr="Use block structure")
+    number_of_blocks = CodegenOption(default=1, helpstr="Number of sub blocks in one direction")
+    vectorization_blockstructured = CodegenOption(default=False, helpstr="Vectorize block structuring")
+    adjoint = CodegenOption(default=False, helpstr="Generate adjoint operator")
+    control = CodegenOption(default=False, helpstr="Generate operator of derivative w.r.t. the control variable")
+    objective_function = CodegenOption(default=None, helpstr="Name of form representing the objective function in UFL file")
+    control_variable = CodegenOption(default=None, helpstr="Name of control variable in UFL file")
+    block_preconditioner_diagonal = CodegenOption(default=False, helpstr="Whether this operator should implement the diagonal part of a block preconditioner")
+    block_preconditioner_offdiagonal = CodegenOption(default=False, helpstr="Whether this operator should implement the off-diagonal part of a block preconditioner")
+
+# Until more sophisticated logic is needed, we keep the actual option data in this module
+_global_options = CodegenGlobalOptionsArray()
+_form_options = {}
+
+
+def initialize_options():
+    """ Initialize the options from the command line """
+    global _global_options
+    _global_options = update_options_from_commandline(_global_options)
+    _global_options = update_options_from_inifile(_global_options)
+
+
+def update_options_from_commandline(opt):
+    """ Return an options array object with updated values from the commandline """
+    assert isinstance(opt, CodegenGlobalOptionsArray)
+    parser = ArgumentParser(description="Compile UFL files to PDELab C++ code",
+                            epilog="Please report bugs to dominic.kempf@iwr.uni-heidelberg.de",
+                            )
+    parser.add_argument('--version', action='version', version='%(prog)s 0.1')
+    for k, v in type(opt).__dict__.items():
+        if isinstance(v, CodegenOption) and v.helpstr is not None:
+            cmdopt = "--{}".format(k.replace('_', '-'))
+            parser.add_argument(cmdopt, help=v.helpstr, type=v.type)
+    parsedargs = {k: v for k, v in vars(parser.parse_args()).items() if v is not None}
+    return opt.copy(**parsedargs)
+
+
+def update_options_from_inifile(opt):
+    """ Return an options array object with updated values from an inifile """
+    if opt.ini_file:
+        def parse_ini(section, opttype):
+            def _fix_types(k, v):
+                if hasattr(opttype, k) and getattr(opttype, k).type is bool:
+                    return bool(eval(v))
+                if hasattr(opttype, k):
+                    return getattr(opttype, k).type(v)
+                return v
+            ini = parse_ini_file(opt.ini_file).get(section, {})
+            return {k: _fix_types(k, v) for k, v in ini.items()}
+
+        opt = opt.copy(**parse_ini("formcompiler", CodegenGlobalOptionsArray))
+        # Also parse form-specific options
+        for form in [i.strip() for i in opt.operators.split(",")]:
+            _form_options[form] = CodegenFormOptionsArray(**parse_ini("formcompiler.{}".format(form), CodegenFormOptionsArray))
+
+    return opt
+
+
+@memoize
+def process_global_options(opt):
+    """ Make sure that the options have been fully processed """
+    opt = expand_architecture_options(opt)
+
+    if opt.overlapping:
+        opt = opt.copy(parallel=True)
+
+    return opt
+
+
+@memoize
+def process_form_options(opt, form):
+    if opt.sumfact:
+        opt = opt.copy(unroll_dimension_loops=True)
+
+    if opt.numerical_jacobian:
+        opt = opt.copy(generate_jacobians=False, generate_jacobian_apply=False)
+
+    if opt.form is None:
+        opt = opt.copy(form=form)
+
+    if opt.classname is None:
+        opt = opt.copy(classname="{}Operator".format(form))
+
+    if opt.filename is None:
+        opt = opt.copy(filename="{}_{}_file.hh".format(get_option("target_name"), opt.classname))
+
+    if opt.block_preconditioner_diagonal or opt.block_preconditioner_offdiagonal:
+        assert opt.numerical_jacobian is False
+        opt = opt.copy(generate_residuals=False,
+                       generate_jacobians=False,
+                       matrix_free=True,
+                       )
+
+    if opt.matrix_free:
+        opt = opt.copy(generate_jacobian_apply=True)
+
+    return opt
+
+
+def expand_architecture_options(opt):
+    if opt.architecture == "haswell":
+        return opt.copy(max_vector_width=256)
+    elif opt.architecture == "knl":
+        return opt.copy(max_vector_width=512)
+    elif opt.architecture == "skylake":
+        return opt.copy(max_vector_width=512)
+    else:
+        raise NotImplementedError("Architecture {} not known!".format(opt.architecture))
+
+
+def set_option(key, value):
+    """Add the key value pair to the options.
+
+    If the key is already in the options dictionary its value will be
+    overwritten.  Form compiler arguments will always be set before
+    any other options.
+    """
+    global _global_options
+    _global_options = process_global_options(_global_options).copy(**{key: value})
+
+
+def set_form_option(key, value, form=None):
+    if form is None:
+        from dune.codegen.generation import get_global_context_value
+        form = get_global_context_value("form_identifier", 0)
+    if isinstance(form, int):
+        form = get_option("operators").split(",")[form].strip()
+    _form_options[form] = _form_options[form].copy(**{key: value})
+
+
+def get_option(key):
+    processed_global_opts = process_global_options(_global_options)
+    return getattr(processed_global_opts, key)
+
+
+def get_form_option(key, form=None):
+    if form is None:
+        from dune.codegen.generation import get_global_context_value
+        form = get_global_context_value("form_identifier", 0)
+    if isinstance(form, int):
+        form = get_option("operators").split(",")[form].strip()
+    processed_form_opts = process_form_options(_form_options[form], form)
+    return getattr(processed_form_opts, key)
+
+
+def option_switch(opt):
+    def _switch():
+        if isinstance(opt, tuple):
+            opts = opt
+        else:
+            assert isinstance(opt, str)
+            opts = (opt,)
+        try:
+            for o in opts:
+                if get_option(o):
+                    return o
+            return "default"
+        except AttributeError:
+            for o in opts:
+                if get_form_option(o):
+                    return o
+            return "default"
+    return _switch
diff --git a/python/dune/perftool/pdelab/__init__.py b/python/dune/codegen/pdelab/__init__.py
similarity index 65%
rename from python/dune/perftool/pdelab/__init__.py
rename to python/dune/codegen/pdelab/__init__.py
index 7f1ab8d17feb6849944233278826dc529fe9fbe9..affa0725c89539fa88e470ac143f5d76fdb8a18b 100644
--- a/python/dune/perftool/pdelab/__init__.py
+++ b/python/dune/codegen/pdelab/__init__.py
@@ -2,40 +2,40 @@
 
 # Trigger some imports that are needed to have all backend implementations visible
 # to the selection mechanisms
-from dune.perftool.generation import (get_backend)
-from dune.perftool.options import option_switch
-from dune.perftool.pdelab.argument import (pymbolic_apply_function,
-                                           pymbolic_apply_function_gradient,
-                                           pymbolic_trialfunction,
-                                           pymbolic_trialfunction_gradient,
-                                           pymbolic_coefficient
-                                           )
-from dune.perftool.pdelab.basis import (pymbolic_basis,
-                                        pymbolic_reference_gradient,
-                                        )
-from dune.perftool.pdelab.function import pymbolic_gridfunction
-from dune.perftool.pdelab.geometry import (component_iname,
-                                           pymbolic_cell_volume,
-                                           pymbolic_facet_area,
-                                           pymbolic_facet_jacobian_determinant,
-                                           pymbolic_jacobian_determinant,
-                                           pymbolic_jacobian_inverse,
-                                           pymbolic_unit_inner_normal,
-                                           pymbolic_unit_outer_normal,
-                                           to_global,
-                                           )
-from dune.perftool.pdelab.index import (name_index,
+from dune.codegen.generation import (get_backend)
+from dune.codegen.options import option_switch
+from dune.codegen.pdelab.argument import (pymbolic_apply_function,
+                                          pymbolic_apply_function_gradient,
+                                          pymbolic_trialfunction,
+                                          pymbolic_trialfunction_gradient,
+                                          pymbolic_coefficient
+                                          )
+from dune.codegen.pdelab.basis import (pymbolic_basis,
+                                       pymbolic_reference_gradient,
+                                       )
+from dune.codegen.pdelab.function import pymbolic_gridfunction
+from dune.codegen.pdelab.geometry import (component_iname,
+                                          pymbolic_cell_volume,
+                                          pymbolic_facet_area,
+                                          pymbolic_facet_jacobian_determinant,
+                                          pymbolic_jacobian_determinant,
+                                          pymbolic_jacobian_inverse,
+                                          pymbolic_unit_inner_normal,
+                                          pymbolic_unit_outer_normal,
+                                          to_global,
+                                          )
+from dune.codegen.pdelab.index import (name_index,
+                                       )
+from dune.codegen.pdelab.quadrature import (pymbolic_quadrature_weight,
+                                            pymbolic_quadrature_position,
+                                            quadrature_inames,
+                                            )
+from dune.codegen.pdelab.spaces import (lfs_inames,
                                         )
-from dune.perftool.pdelab.quadrature import (pymbolic_quadrature_weight,
-                                             pymbolic_quadrature_position,
-                                             quadrature_inames,
-                                             )
-from dune.perftool.pdelab.spaces import (lfs_inames,
+from dune.codegen.pdelab.tensors import (pymbolic_list_tensor,
+                                         pymbolic_identity,
+                                         pymbolic_matrix_inverse,
                                          )
-from dune.perftool.pdelab.tensors import (pymbolic_list_tensor,
-                                          pymbolic_identity,
-                                          pymbolic_matrix_inverse,
-                                          )
 
 
 class PDELabInterface(object):
@@ -45,15 +45,15 @@ class PDELabInterface(object):
 
     # Accumulation interfaces
     def get_accumulation_info(self, expr, visitor):
-        from dune.perftool.pdelab.localoperator import get_accumulation_info
+        from dune.codegen.pdelab.localoperator import get_accumulation_info
         return get_accumulation_info(expr, visitor)
 
     def list_accumulation_infos(self, expr, visitor):
-        from dune.perftool.pdelab.localoperator import list_accumulation_infos
+        from dune.codegen.pdelab.localoperator import list_accumulation_infos
         return list_accumulation_infos(expr, visitor)
 
     def generate_accumulation_instruction(self, expr, visitor):
-        from dune.perftool.pdelab.localoperator import generate_accumulation_instruction
+        from dune.codegen.pdelab.localoperator import generate_accumulation_instruction
         return generate_accumulation_instruction(expr, visitor)
 
     #
@@ -75,7 +75,7 @@ class PDELabInterface(object):
         return lfs_inames(element, restriction, number, context)
 
     def initialize_function_spaces(self, expr, visitor):
-        from dune.perftool.pdelab.spaces import initialize_function_spaces
+        from dune.codegen.pdelab.spaces import initialize_function_spaces
         return initialize_function_spaces(expr, visitor)
 
     #
diff --git a/python/dune/perftool/pdelab/adjoint.py b/python/dune/codegen/pdelab/adjoint.py
similarity index 78%
rename from python/dune/perftool/pdelab/adjoint.py
rename to python/dune/codegen/pdelab/adjoint.py
index aef03bbbf08e45f2510bd90f164bdd70b071580c..2681b00391d46532a37846ab2c550f98ff5a3d96 100644
--- a/python/dune/perftool/pdelab/adjoint.py
+++ b/python/dune/codegen/pdelab/adjoint.py
@@ -8,23 +8,23 @@ from loopy.types import NumpyType
 
 import pymbolic.primitives as prim
 
-from dune.perftool.generation import (class_member,
-                                      constructor_parameter,
-                                      function_mangler,
-                                      get_global_context_value,
-                                      global_context,
-                                      globalarg,
-                                      initializer_list,
-                                      template_parameter,
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   )
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.pdelab import PDELabInterface
-from dune.perftool.pdelab.localoperator import (boundary_predicates,
-                                                determine_accumulation_space,
-                                                extract_kernel_from_cache,
-                                                )
+from dune.codegen.generation import (class_member,
+                                     constructor_parameter,
+                                     function_mangler,
+                                     get_global_context_value,
+                                     global_context,
+                                     globalarg,
+                                     initializer_list,
+                                     template_parameter,
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  )
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.pdelab import PDELabInterface
+from dune.codegen.pdelab.localoperator import (boundary_predicates,
+                                               determine_accumulation_space,
+                                               extract_kernel_from_cache,
+                                               )
 
 
 @template_parameter(classtag="operator")
@@ -60,7 +60,7 @@ def generate_accumulation_instruction(expr, visitor, accumulation_index, number_
     # We need to accumulate
     expr = prim.Sum((assignee, expr))
 
-    from dune.perftool.generation import instruction
+    from dune.codegen.generation import instruction
     quad_inames = visitor.interface.quadrature_inames()
     instruction(assignee=assignee,
                 expression=expr,
@@ -103,7 +103,7 @@ class ControlInterface(PDELabInterface):
 
 def get_visitor(measure, subdomain_id, accumulation_index, number_of_controls):
     interface = ControlInterface(accumulation_index, number_of_controls)
-    from dune.perftool.ufl.visitor import UFL2LoopyVisitor
+    from dune.codegen.ufl.visitor import UFL2LoopyVisitor
     return UFL2LoopyVisitor(interface, measure, subdomain_id)
 
 
@@ -134,26 +134,26 @@ def generate_kernel(forms):
                 visit_integral(integral, i, len(forms))
 
     # Now perform some checks on what should be done
-    from dune.perftool.sumfact.vectorization import decide_vectorization_strategy
+    from dune.codegen.sumfact.vectorization import decide_vectorization_strategy
     logger.debug('generate_kernel: decide_vectorization_strategy')
     decide_vectorization_strategy()
 
     # Delete the cache contents and do the real thing!
     logger.debug('generate_kernel: visit_integrals (no dry run)')
-    from dune.perftool.generation import delete_cache_items
+    from dune.codegen.generation import delete_cache_items
     delete_cache_items("kernel_default")
     for i, form in enumerate(forms):
         for integral in form:
             visit_integral(integral, i, len(forms))
 
-    from dune.perftool.pdelab.signatures import kernel_name, assembly_routine_signature
+    from dune.codegen.pdelab.signatures import kernel_name, assembly_routine_signature
     name = kernel_name()
     signature = assembly_routine_signature()
     knl = extract_kernel_from_cache("kernel_default", name, signature)
     delete_cache_items("kernel_default")
 
     # Reset the quadrature degree
-    from dune.perftool.sumfact.tabulation import set_quadrature_points
+    from dune.codegen.sumfact.tabulation import set_quadrature_points
     set_quadrature_points(None)
 
     # Clean the cache from any data collected after the dry run
diff --git a/python/dune/perftool/pdelab/argument.py b/python/dune/codegen/pdelab/argument.py
similarity index 86%
rename from python/dune/perftool/pdelab/argument.py
rename to python/dune/codegen/pdelab/argument.py
index 30449edea105a0a962c5883559e61ced1fc4cdb0..ce16cd1121458ab27325312a727fd74c98d708cc 100644
--- a/python/dune/perftool/pdelab/argument.py
+++ b/python/dune/codegen/pdelab/argument.py
@@ -5,24 +5,24 @@ Namely:
 * accumulation object (r, jac...)
 """
 
-from dune.perftool.generation import (domain,
-                                      function_mangler,
-                                      iname,
-                                      valuearg,
-                                      get_global_context_value,
-                                      kernel_cached,
-                                      backend
-                                      )
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.pdelab.index import name_index
-from dune.perftool.pdelab.basis import (evaluate_coefficient,
-                                        evaluate_coefficient_gradient,
+from dune.codegen.generation import (domain,
+                                     function_mangler,
+                                     iname,
+                                     valuearg,
+                                     get_global_context_value,
+                                     kernel_cached,
+                                     backend
+                                     )
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.pdelab.index import name_index
+from dune.codegen.pdelab.basis import (evaluate_coefficient,
+                                       evaluate_coefficient_gradient,
+                                       )
+from dune.codegen.pdelab.spaces import (lfs_iname,
+                                        name_lfs_bound,
                                         )
-from dune.perftool.pdelab.spaces import (lfs_iname,
-                                         name_lfs_bound,
-                                         )
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.ufl.modified_terminals import Restriction
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.ufl.modified_terminals import Restriction
 
 from pymbolic.primitives import Call, Subscript, Variable
 
diff --git a/python/dune/perftool/pdelab/basis.py b/python/dune/codegen/pdelab/basis.py
similarity index 75%
rename from python/dune/perftool/pdelab/basis.py
rename to python/dune/codegen/pdelab/basis.py
index 55c9a7ef7676c7647d485486d73440aed9d22aa2..c65e71ebfc9e3a38023033e27dc65d445734edbf 100644
--- a/python/dune/perftool/pdelab/basis.py
+++ b/python/dune/codegen/pdelab/basis.py
@@ -1,42 +1,42 @@
 """ Generators for basis evaluations """
 
-from dune.perftool.generation import (backend,
-                                      class_member,
-                                      get_backend,
-                                      include_file,
-                                      instruction,
-                                      kernel_cached,
-                                      preamble,
-                                      temporary_variable,
-                                      )
-from dune.perftool.options import (option_switch,
-                                   get_form_option,
-                                   )
-from dune.perftool.pdelab.spaces import (lfs_iname,
-                                         lfs_inames,
-                                         name_leaf_lfs,
-                                         name_lfs,
-                                         name_lfs_bound,
-                                         type_gfs,
-                                         type_leaf_gfs,
-                                         )
-from dune.perftool.pdelab.geometry import (component_iname,
-                                           world_dimension,
-                                           name_jacobian_inverse_transposed,
-                                           to_cell_coordinates,
-                                           name_cell,
-                                           )
-from dune.perftool.pdelab.localoperator import (lop_template_ansatz_gfs,
-                                                lop_template_test_gfs,
-                                                )
-from dune.perftool.tools import (get_pymbolic_basename,
-                                 get_pymbolic_indices,
-                                 )
-from dune.perftool.pdelab.driver import FEM_name_mangling
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.pdelab.driver import (isPk,
-                                         isQk,
-                                         isDG)
+from dune.codegen.generation import (backend,
+                                     class_member,
+                                     get_backend,
+                                     include_file,
+                                     instruction,
+                                     kernel_cached,
+                                     preamble,
+                                     temporary_variable,
+                                     )
+from dune.codegen.options import (option_switch,
+                                  get_form_option,
+                                  )
+from dune.codegen.pdelab.spaces import (lfs_iname,
+                                        lfs_inames,
+                                        name_leaf_lfs,
+                                        name_lfs,
+                                        name_lfs_bound,
+                                        type_gfs,
+                                        type_leaf_gfs,
+                                        )
+from dune.codegen.pdelab.geometry import (component_iname,
+                                          world_dimension,
+                                          name_jacobian_inverse_transposed,
+                                          to_cell_coordinates,
+                                          name_cell,
+                                          )
+from dune.codegen.pdelab.localoperator import (lop_template_ansatz_gfs,
+                                               lop_template_test_gfs,
+                                               )
+from dune.codegen.tools import (get_pymbolic_basename,
+                                get_pymbolic_indices,
+                                )
+from dune.codegen.pdelab.driver import FEM_name_mangling
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.pdelab.driver import (isPk,
+                                        isQk,
+                                        isDG)
 
 from pymbolic.primitives import Product, Subscript, Variable
 
@@ -71,7 +71,7 @@ def type_localbasis_cache(element):
 
 @class_member(classtag="operator")
 def define_localbasis_cache(element, name):
-    include_file("dune/perftool/localbasiscache.hh", filetag="operatorfile")
+    include_file("dune/codegen/localbasiscache.hh", filetag="operatorfile")
     t = type_localbasis_cache(element)
     return "{} {};".format(t, name)
 
@@ -174,10 +174,10 @@ def evaluate_coefficient(visitor, element, name, container, restriction, index):
     basis = visitor.interface.pymbolic_basis(sub_element, restriction, 0, context='trial')
     basisindex = get_pymbolic_indices(basis)[:-1]
     if get_form_option("blockstructured"):
-        from dune.perftool.blockstructured.argument import pymbolic_coefficient
+        from dune.codegen.blockstructured.argument import pymbolic_coefficient
         coeff = pymbolic_coefficient(container, lfs, sub_element, basisindex)
     else:
-        from dune.perftool.pdelab.argument import pymbolic_coefficient
+        from dune.codegen.pdelab.argument import pymbolic_coefficient
         coeff = pymbolic_coefficient(container, lfs, basisindex[0])
 
     assignee = Variable(name)
@@ -206,14 +206,14 @@ def evaluate_coefficient_gradient(visitor, element, name, container, restriction
     lfs = name_lfs(element, restriction, index)
     basis = visitor.interface.pymbolic_reference_gradient(sub_element, restriction, 0, context='trialgrad')
     basisindex = get_pymbolic_indices(basis)[:-1]
-    from dune.perftool.tools import maybe_wrap_subscript
+    from dune.codegen.tools import maybe_wrap_subscript
     basis = maybe_wrap_subscript(basis, Variable(dimindex))
 
     if get_form_option("blockstructured"):
-        from dune.perftool.blockstructured.argument import pymbolic_coefficient
+        from dune.codegen.blockstructured.argument import pymbolic_coefficient
         coeff = pymbolic_coefficient(container, lfs, sub_element, basisindex)
     else:
-        from dune.perftool.pdelab.argument import pymbolic_coefficient
+        from dune.codegen.pdelab.argument import pymbolic_coefficient
         coeff = pymbolic_coefficient(container, lfs, basisindex[0])
 
     assignee = Subscript(Variable(name), (Variable(dimindex),))
diff --git a/python/dune/perftool/pdelab/driver/__init__.py b/python/dune/codegen/pdelab/driver/__init__.py
similarity index 86%
rename from python/dune/perftool/pdelab/driver/__init__.py
rename to python/dune/codegen/pdelab/driver/__init__.py
index 591c022ddedd8656102f1594d5148714bd7561de..6526dcbf85cfb60d663a3f0193dde07351a361bd 100644
--- a/python/dune/perftool/pdelab/driver/__init__.py
+++ b/python/dune/codegen/pdelab/driver/__init__.py
@@ -10,18 +10,18 @@ NB: Previously this __init__.py was a module driver.py. As it was growing,
     we made it a package. Some content could and should be separated into
     new modules within this package!
 """
-from dune.perftool.error import PerftoolCodegenError
-from dune.perftool.generation import (generator_factory,
-                                      get_global_context_value,
-                                      global_context,
-                                      include_file,
-                                      cached,
-                                      pre_include,
-                                      preamble,
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   )
+from dune.codegen.error import CodegenCodegenError
+from dune.codegen.generation import (generator_factory,
+                                     get_global_context_value,
+                                     global_context,
+                                     include_file,
+                                     cached,
+                                     pre_include,
+                                     preamble,
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  )
 
 #
 # The following functions are not doing anything useful, but providing easy access
@@ -223,7 +223,7 @@ def name_mpihelper():
 
 @preamble(section="grid")
 def check_parallel_execution():
-    from dune.perftool.pdelab.driver.gridfunctionspace import name_leafview
+    from dune.codegen.pdelab.driver.gridfunctionspace import name_leafview
     gv = name_leafview()
     return ["if ({}.comm().size()==1){{".format(gv),
             '  std::cout << "This program should be run in parallel!"  << std::endl;',
@@ -249,35 +249,35 @@ def generate_driver():
         assert(isQuadrilateral(get_cell()))
         # In case of operator counting we only assemble the matrix and evaluate the residual
         # assemble_matrix_timer()
-        from dune.perftool.pdelab.driver.timings import apply_jacobian_timer, evaluate_residual_timer
-        from dune.perftool.loopy.target import type_floatingpoint
+        from dune.codegen.pdelab.driver.timings import apply_jacobian_timer, evaluate_residual_timer
+        from dune.codegen.loopy.target import type_floatingpoint
         pre_include("#define HP_TIMER_OPCOUNTER {}".format(type_floatingpoint()), filetag="driver")
         evaluate_residual_timer()
         if get_form_option("generate_jacobian_apply"):
             apply_jacobian_timer()
     elif is_stationary():
-        from dune.perftool.pdelab.driver.solve import dune_solve
+        from dune.codegen.pdelab.driver.solve import dune_solve
         vec = dune_solve()
-        from dune.perftool.pdelab.driver.vtk import vtkoutput
+        from dune.codegen.pdelab.driver.vtk import vtkoutput
         vtkoutput()
     else:
-        from dune.perftool.pdelab.driver.instationary import solve_instationary
+        from dune.codegen.pdelab.driver.instationary import solve_instationary
         solve_instationary()
 
-    from dune.perftool.pdelab.driver.error import compare_L2_squared
+    from dune.codegen.pdelab.driver.error import compare_L2_squared
     if get_option("compare_l2errorsquared"):
         compare_L2_squared()
 
     # Make sure that timestream is declared before retrieving chache items
     if get_option("instrumentation_level") >= 1:
-        from dune.perftool.pdelab.driver.timings import setup_timer, name_timing_stream
+        from dune.codegen.pdelab.driver.timings import setup_timer, name_timing_stream
         setup_timer()
         timestream = name_timing_stream()
 
-    from dune.perftool.pdelab.driver.error import return_statement
+    from dune.codegen.pdelab.driver.error import return_statement
     return_statement()
 
-    from dune.perftool.generation import retrieve_cache_items
+    from dune.codegen.generation import retrieve_cache_items
     from cgen import FunctionDeclaration, FunctionBody, Block, Value, LineComment, Line
     driver_signature = FunctionDeclaration(Value('int', 'main'), [Value('int', 'argc'), Value('char**', 'argv')])
 
@@ -306,7 +306,7 @@ def generate_driver():
     add_section("error", "Maybe calculate errors for test results...")
 
     if get_option("instrumentation_level") >= 1:
-        from dune.perftool.generation import post_include
+        from dune.codegen.generation import post_include
         post_include("HP_DECLARE_TIMER(driver);\n", filetag="driver")
         contents.insert(0, Line(text="HP_TIMER_START(driver);\n"))
         contents.insert(len(contents) - 1, Line(text="HP_TIMER_STOP(driver);\n"))
@@ -315,7 +315,7 @@ def generate_driver():
     driver_body = Block(contents)
 
     # Wrap a try/catch block around the driver body
-    from dune.perftool.cgen import CatchBlock, TryCatchBlock, Value, Block, Line
+    from dune.codegen.cgen import CatchBlock, TryCatchBlock, Value, Block, Line
     catch_blocks = [CatchBlock(Value("Dune::Exception&", "e"),
                                Block([Line("std::cerr << \"Dune reported error: \" << e << std::endl;\n"),
                                       Line("return 1;\n"),
@@ -332,9 +332,9 @@ def generate_driver():
 
     filename = get_option("driver_file")
 
-    from dune.perftool.file import generate_file
+    from dune.codegen.file import generate_file
     generate_file(filename, "driver", [driver], headerguard=False)
 
     # Reset the caching data structure
-    from dune.perftool.generation import delete_cache_items
+    from dune.codegen.generation import delete_cache_items
     delete_cache_items()
diff --git a/python/dune/perftool/pdelab/driver/constraints.py b/python/dune/codegen/pdelab/driver/constraints.py
similarity index 83%
rename from python/dune/perftool/pdelab/driver/constraints.py
rename to python/dune/codegen/pdelab/driver/constraints.py
index dc65354a08452b783a377f53f401e8b7f445c766..b903b49fbd128d9ab0ee104ef8ad4441a87e1ead 100644
--- a/python/dune/perftool/pdelab/driver/constraints.py
+++ b/python/dune/codegen/pdelab/driver/constraints.py
@@ -1,18 +1,18 @@
-from dune.perftool.generation import (get_counted_variable,
-                                      global_context,
-                                      include_file,
-                                      preamble,
-                                      )
-from dune.perftool.pdelab.driver import (FEM_name_mangling,
-                                         get_trial_element,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_gfs,
-                                                           name_leafview,
-                                                           name_trial_gfs,
-                                                           type_range,
-                                                           type_trial_gfs,
-                                                           preprocess_leaf_data,
-                                                           )
+from dune.codegen.generation import (get_counted_variable,
+                                     global_context,
+                                     include_file,
+                                     preamble,
+                                     )
+from dune.codegen.pdelab.driver import (FEM_name_mangling,
+                                        get_trial_element,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_gfs,
+                                                          name_leafview,
+                                                          name_trial_gfs,
+                                                          type_range,
+                                                          type_trial_gfs,
+                                                          preprocess_leaf_data,
+                                                          )
 
 from ufl.classes import Expr
 from ufl import FiniteElement, MixedElement, TensorElement, VectorElement, TensorProductElement
@@ -107,7 +107,7 @@ def define_intersection_lambda(name, func):
     if isinstance(func, (int, float)):
         return "auto {} = [&](const auto& x){{ return {}; }};".format(name, float(func))
     elif isinstance(func, Expr):
-        from dune.perftool.pdelab.driver.visitor import ufl_to_code
+        from dune.codegen.pdelab.driver.visitor import ufl_to_code
         return "auto {} = [&](const auto& is, const auto& xl){{ {} }};".format(name, ufl_to_code(func))
 
     raise ValueError("Expression not understood")
diff --git a/python/dune/perftool/pdelab/driver/error.py b/python/dune/codegen/pdelab/driver/error.py
similarity index 81%
rename from python/dune/perftool/pdelab/driver/error.py
rename to python/dune/codegen/pdelab/driver/error.py
index 4934f06d66a7913041214130b51453df8cde979f..cf9fe42933ca41f2696b39324bb4f443c35d9003 100644
--- a/python/dune/perftool/pdelab/driver/error.py
+++ b/python/dune/codegen/pdelab/driver/error.py
@@ -1,26 +1,26 @@
 """ Generator functions to calculate errors in the driver """
 
-from dune.perftool.generation import (cached,
-                                      include_file,
-                                      preamble,
-                                      )
-from dune.perftool.options import get_option
-from dune.perftool.pdelab.driver import (get_form_ident,
-                                         get_trial_element,
-                                         preprocess_leaf_data,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_leafview,
-                                                           name_trial_gfs,
-                                                           name_trial_subgfs,
-                                                           type_range,
-                                                           )
-from dune.perftool.pdelab.driver.interpolate import (interpolate_vector,
-                                                     name_boundary_function,
-                                                     )
-from dune.perftool.pdelab.driver.solve import (define_vector,
-                                               dune_solve,
-                                               name_vector,
-                                               )
+from dune.codegen.generation import (cached,
+                                     include_file,
+                                     preamble,
+                                     )
+from dune.codegen.options import get_option
+from dune.codegen.pdelab.driver import (get_form_ident,
+                                        get_trial_element,
+                                        preprocess_leaf_data,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_leafview,
+                                                          name_trial_gfs,
+                                                          name_trial_subgfs,
+                                                          type_range,
+                                                          )
+from dune.codegen.pdelab.driver.interpolate import (interpolate_vector,
+                                                    name_boundary_function,
+                                                    )
+from dune.codegen.pdelab.driver.solve import (define_vector,
+                                              dune_solve,
+                                              name_vector,
+                                              )
 from ufl import MixedElement, TensorElement, VectorElement
 
 
@@ -188,6 +188,6 @@ def compare_L2_squared():
 
 @preamble(section="error")
 def return_statement():
-    from dune.perftool.pdelab.driver.error import name_test_fail_variable
+    from dune.codegen.pdelab.driver.error import name_test_fail_variable
     fail = name_test_fail_variable()
     return "return {};".format(fail)
diff --git a/python/dune/perftool/pdelab/driver/gridfunctionspace.py b/python/dune/codegen/pdelab/driver/gridfunctionspace.py
similarity index 90%
rename from python/dune/perftool/pdelab/driver/gridfunctionspace.py
rename to python/dune/codegen/pdelab/driver/gridfunctionspace.py
index 659ef658f15f618391981ef607b18eb038cd6214..991b770fde66c26c40e713a04e2c05df181ae357 100644
--- a/python/dune/perftool/pdelab/driver/gridfunctionspace.py
+++ b/python/dune/codegen/pdelab/driver/gridfunctionspace.py
@@ -1,24 +1,24 @@
-from dune.perftool.generation import (include_file,
-                                      preamble,
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   )
-from dune.perftool.pdelab.driver import (FEM_name_mangling,
-                                         get_cell,
-                                         get_dimension,
-                                         get_test_element,
-                                         get_trial_element,
-                                         isLagrange,
-                                         isDG,
-                                         isPk,
-                                         isQk,
-                                         isQuadrilateral,
-                                         isSimplical,
-                                         name_initree,
-                                         preprocess_leaf_data,
-                                         )
-from dune.perftool.loopy.target import type_floatingpoint
+from dune.codegen.generation import (include_file,
+                                     preamble,
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  )
+from dune.codegen.pdelab.driver import (FEM_name_mangling,
+                                        get_cell,
+                                        get_dimension,
+                                        get_test_element,
+                                        get_trial_element,
+                                        isLagrange,
+                                        isDG,
+                                        isPk,
+                                        isQk,
+                                        isQuadrilateral,
+                                        isSimplical,
+                                        name_initree,
+                                        preprocess_leaf_data,
+                                        )
+from dune.codegen.loopy.target import type_floatingpoint
 
 from ufl import FiniteElement, MixedElement, TensorElement, VectorElement, TensorProductElement
 
@@ -65,7 +65,7 @@ def typedef_grid(name):
             gridt = "Dune::ALUGrid<{}, {}, Dune::simplex, Dune::conforming>".format(dim, dim)
             include_file("dune/alugrid/grid.hh", filetag="driver")
         else:
-            raise PerftoolCodegenError("Cant match your geometry with a DUNE grid. Please report bug.")
+            raise CodegenCodegenError("Cant match your geometry with a DUNE grid. Please report bug.")
     return "using {} = {};".format(name, gridt)
 
 
@@ -86,7 +86,7 @@ def define_grid(name):
         # TODO: createConsistentGrid drops boundary faces. Instead of using
         # this we assume that the user already provides a constistent gmsh
         # file. This can be createt by createConsistentGmshFile, see
-        # dune-perftool/bin/analyzegrid/consistent_gmsh.cc
+        # dune-codegen/bin/analyzegrid/consistent_gmsh.cc
         # include_file("dune/consistent-edge-orientation/createconsistentgrid.hh", filetag="driver")
         # return ["IniGridFactory<{}> factory({});".format(_type, ini),
         #         "std::shared_ptr<{}> grid_nonconsistent = factory.getGrid();".format(_type),
@@ -136,7 +136,7 @@ def typedef_fem(element, name):
     dim = get_dimension()
 
     if get_form_option("blockstructured"):
-        include_file("dune/perftool/blockstructured/blockstructuredqkfem.hh", filetag="driver")
+        include_file("dune/codegen/blockstructured/blockstructuredqkfem.hh", filetag="driver")
         degree = element.degree() * get_form_option("number_of_blocks")
         return "using {} = Dune::PDELab::BlockstructuredQkLocalFiniteElementMap<{}, {}, {}, {}>;" \
             .format(name, gv, df, r, degree)
@@ -161,7 +161,7 @@ def typedef_fem(element, name):
             # TODO allow switching the basis here!
             return "using {} = Dune::PDELab::QkDGLocalFiniteElementMap<{}, {}, {}, {}>;" \
                 .format(name, df, r, degrees[0], dim)
-        raise NotImplementedError("FEM not implemented in dune-perftool")
+        raise NotImplementedError("FEM not implemented in dune-codegen")
     elif isQk(element):
         include_file("dune/pdelab/finiteelementmap/qkfem.hh", filetag="driver")
         return "using {} = Dune::PDELab::QkLocalFiniteElementMap<{}, {}, {}, {}>;" \
@@ -182,7 +182,7 @@ def typedef_fem(element, name):
                 .format(name, df, r, element.degree(), dim)
         raise NotImplementedError("Geometry type not known in code generation")
 
-    raise NotImplementedError("FEM not implemented in dune-perftool")
+    raise NotImplementedError("FEM not implemented in dune-codegen")
 
 
 def type_fem(element):
@@ -194,7 +194,7 @@ def type_fem(element):
 @preamble(section="fem")
 def define_fem(element, name):
     femtype = type_fem(element)
-    from dune.perftool.pdelab.driver import isDG
+    from dune.codegen.pdelab.driver import isDG
     if isinstance(element, TensorProductElement):
         # Only allow TensorProductElements where all subelements are
         # of the same type ('CG' or 'DG')
@@ -330,7 +330,7 @@ def typedef_gfs(element, is_dirichlet, name, root):
     vb = type_vectorbackend(element, root)
     gv = type_leafview()
     fem = type_fem(element)
-    from dune.perftool.pdelab.driver.constraints import has_dirichlet_constraints
+    from dune.codegen.pdelab.driver.constraints import has_dirichlet_constraints
     cass = type_constraintsassembler(has_dirichlet_constraints(is_dirichlet))
     return "using {} = Dune::PDELab::GridFunctionSpace<{}, {}, {}, {}>;".format(name, gv, fem, cass, vb)
 
diff --git a/python/dune/perftool/pdelab/driver/gridoperator.py b/python/dune/codegen/pdelab/driver/gridoperator.py
similarity index 72%
rename from python/dune/perftool/pdelab/driver/gridoperator.py
rename to python/dune/codegen/pdelab/driver/gridoperator.py
index 8b5c8c0223b61f3d8a5464170cb5c2e496151e15..abc878f0715dbcb4a0501d56247c4f03c98f20df 100644
--- a/python/dune/perftool/pdelab/driver/gridoperator.py
+++ b/python/dune/codegen/pdelab/driver/gridoperator.py
@@ -1,27 +1,27 @@
-from dune.perftool.generation import (get_global_context_value,
-                                      include_file,
-                                      preamble,
-                                      )
-from dune.perftool.pdelab.driver import (get_cell,
-                                         get_dimension,
-                                         get_test_element,
-                                         get_trial_element,
-                                         isQuadrilateral,
-                                         name_initree,
-                                         )
-from dune.perftool.pdelab.driver.constraints import (name_assembled_constraints,
-                                                     type_constraintscontainer,
-                                                     )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_test_gfs,
-                                                           name_trial_gfs,
-                                                           preprocess_leaf_data,
-                                                           type_domainfield,
-                                                           type_range,
-                                                           type_test_gfs,
-                                                           type_trial_gfs,
-                                                           )
-from dune.perftool.pdelab.localoperator import localoperator_basename
-from dune.perftool.options import get_form_option
+from dune.codegen.generation import (get_global_context_value,
+                                     include_file,
+                                     preamble,
+                                     )
+from dune.codegen.pdelab.driver import (get_cell,
+                                        get_dimension,
+                                        get_test_element,
+                                        get_trial_element,
+                                        isQuadrilateral,
+                                        name_initree,
+                                        )
+from dune.codegen.pdelab.driver.constraints import (name_assembled_constraints,
+                                                    type_constraintscontainer,
+                                                    )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_test_gfs,
+                                                          name_trial_gfs,
+                                                          preprocess_leaf_data,
+                                                          type_domainfield,
+                                                          type_range,
+                                                          type_test_gfs,
+                                                          type_trial_gfs,
+                                                          )
+from dune.codegen.pdelab.localoperator import localoperator_basename
+from dune.codegen.options import get_form_option
 
 
 @preamble(section="gridoperator")
@@ -35,7 +35,7 @@ def typedef_gridoperator(name, form_ident):
     r = type_range()
     if get_form_option("fastdg"):
         if not get_form_option("sumfact"):
-            raise PerftoolCodegenError("FastDGGridOperator is only implemented for sumfactorization.")
+            raise CodegenCodegenError("FastDGGridOperator is only implemented for sumfactorization.")
         include_file("dune/pdelab/gridoperator/fastdg.hh", filetag="driver")
         return "using {} = Dune::PDELab::FastDGGridOperator<{}, {}, {}, {}, {}, {}, {}, {}, {}>;".format(name, ugfs, vgfs, lop, mb, df, r, r, cc, cc)
     else:
diff --git a/python/dune/perftool/pdelab/driver/instationary.py b/python/dune/codegen/pdelab/driver/instationary.py
similarity index 75%
rename from python/dune/perftool/pdelab/driver/instationary.py
rename to python/dune/codegen/pdelab/driver/instationary.py
index c37792896a23837131ca71f83dcc9f7e497476a3..5cf7170f1dca6f4274db4bf77b4b1627466e20cb 100644
--- a/python/dune/perftool/pdelab/driver/instationary.py
+++ b/python/dune/codegen/pdelab/driver/instationary.py
@@ -1,41 +1,41 @@
-from dune.perftool.generation import (include_file,
-                                      preamble,
-                                      )
-from dune.perftool.pdelab.driver import (get_form_ident,
-                                         get_trial_element,
-                                         is_linear,
-                                         name_initree,
-                                         preprocess_leaf_data,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_trial_gfs,
-                                                           type_range,
-                                                           )
-from dune.perftool.pdelab.driver.gridoperator import (name_gridoperator,
-                                                      type_gridoperator,
-                                                      name_localoperator,
-                                                      )
-from dune.perftool.pdelab.driver.constraints import (has_dirichlet_constraints,
-                                                     name_bctype_function,
-                                                     name_constraintscontainer,
+from dune.codegen.generation import (include_file,
+                                     preamble,
+                                     )
+from dune.codegen.pdelab.driver import (get_form_ident,
+                                        get_trial_element,
+                                        is_linear,
+                                        name_initree,
+                                        preprocess_leaf_data,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_trial_gfs,
+                                                          type_range,
+                                                          )
+from dune.codegen.pdelab.driver.gridoperator import (name_gridoperator,
+                                                     type_gridoperator,
+                                                     name_localoperator,
                                                      )
-from dune.perftool.pdelab.driver.interpolate import (interpolate_dirichlet_data,
-                                                     name_boundary_function,
-                                                     )
-from dune.perftool.pdelab.driver.solve import (print_matrix,
-                                               print_residual,
-                                               name_linearsolver,
-                                               name_stationarynonlinearproblemsolver,
-                                               name_vector,
-                                               type_linearsolver,
-                                               type_stationarynonlinearproblemssolver,
-                                               type_vector,
-                                               )
-from dune.perftool.pdelab.driver.vtk import (name_vtk_sequence_writer,
-                                             visualize_initial_condition,
-                                             name_predicate)
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   )
+from dune.codegen.pdelab.driver.constraints import (has_dirichlet_constraints,
+                                                    name_bctype_function,
+                                                    name_constraintscontainer,
+                                                    )
+from dune.codegen.pdelab.driver.interpolate import (interpolate_dirichlet_data,
+                                                    name_boundary_function,
+                                                    )
+from dune.codegen.pdelab.driver.solve import (print_matrix,
+                                              print_residual,
+                                              name_linearsolver,
+                                              name_stationarynonlinearproblemsolver,
+                                              name_vector,
+                                              type_linearsolver,
+                                              type_stationarynonlinearproblemssolver,
+                                              type_vector,
+                                              )
+from dune.codegen.pdelab.driver.vtk import (name_vtk_sequence_writer,
+                                            visualize_initial_condition,
+                                            name_predicate)
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  )
 
 
 def solve_instationary():
diff --git a/python/dune/perftool/pdelab/driver/interpolate.py b/python/dune/codegen/pdelab/driver/interpolate.py
similarity index 78%
rename from python/dune/perftool/pdelab/driver/interpolate.py
rename to python/dune/codegen/pdelab/driver/interpolate.py
index 36ff21d9c7c47440569fc55cc76eb39b8fbb05a3..7877497e3f69119f558ddf9b3e37659ec84043ac 100644
--- a/python/dune/perftool/pdelab/driver/interpolate.py
+++ b/python/dune/codegen/pdelab/driver/interpolate.py
@@ -1,18 +1,18 @@
-from dune.perftool.generation import (cached,
-                                      get_counted_variable,
-                                      global_context,
-                                      include_file,
-                                      preamble,
-                                      )
-from dune.perftool.pdelab.driver import (FEM_name_mangling,
-                                         get_form_ident,
-                                         get_trial_element,
-                                         is_stationary,
-                                         preprocess_leaf_data,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_trial_gfs,
-                                                           name_leafview,
-                                                           )
+from dune.codegen.generation import (cached,
+                                     get_counted_variable,
+                                     global_context,
+                                     include_file,
+                                     preamble,
+                                     )
+from dune.codegen.pdelab.driver import (FEM_name_mangling,
+                                        get_form_ident,
+                                        get_trial_element,
+                                        is_stationary,
+                                        preprocess_leaf_data,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_trial_gfs,
+                                                          name_leafview,
+                                                          )
 from ufl import FiniteElement, MixedElement, TensorElement, VectorElement, TensorProductElement
 
 
@@ -71,7 +71,7 @@ def define_boundary_function(name, dirichlet):
                                                                                       lambdaname,
                                                                                       )
     else:
-        from dune.perftool.pdelab.driver.gridoperator import name_localoperator
+        from dune.codegen.pdelab.driver.gridoperator import name_localoperator
         lop = name_localoperator(get_form_ident())
         return "auto {} = Dune::PDELab::makeInstationaryGridFunctionFromCallable({}, {}, {});".format(name,
                                                                                                       gv,
@@ -95,7 +95,7 @@ def define_boundary_lambda(name, boundary):
     if isinstance(boundary, (int, float)):
         return "auto {} = [&](const auto& x){{ return {}; }};".format(name, float(boundary))
     elif isinstance(boundary, Expr):
-        from dune.perftool.pdelab.driver.visitor import ufl_to_code
+        from dune.codegen.pdelab.driver.visitor import ufl_to_code
         return "auto {} = [&](const auto& is, const auto& xl){{ {}; }};".format(name, ufl_to_code(boundary))
     else:
         raise NotImplementedError("What is this?")
diff --git a/python/dune/perftool/pdelab/driver/solve.py b/python/dune/codegen/pdelab/driver/solve.py
similarity index 82%
rename from python/dune/perftool/pdelab/driver/solve.py
rename to python/dune/codegen/pdelab/driver/solve.py
index 25747850ba9188f6141b6f848584daed3dd09921..79dfac051c66c2faa50c4e262eb419ed30b5fde1 100644
--- a/python/dune/perftool/pdelab/driver/solve.py
+++ b/python/dune/codegen/pdelab/driver/solve.py
@@ -1,26 +1,26 @@
-from dune.perftool.generation import (include_file,
-                                      preamble,
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   )
-from dune.perftool.pdelab.driver import (get_form_ident,
-                                         is_linear,
-                                         name_initree,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_trial_gfs,
-                                                           name_leafview,
-                                                           type_domainfield,
-                                                           type_trial_gfs,
-                                                           )
-from dune.perftool.pdelab.driver.constraints import (type_constraintscontainer,
-                                                     name_assembled_constraints,
+from dune.codegen.generation import (include_file,
+                                     preamble,
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  )
+from dune.codegen.pdelab.driver import (get_form_ident,
+                                        is_linear,
+                                        name_initree,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_trial_gfs,
+                                                          name_leafview,
+                                                          type_domainfield,
+                                                          type_trial_gfs,
+                                                          )
+from dune.codegen.pdelab.driver.constraints import (type_constraintscontainer,
+                                                    name_assembled_constraints,
+                                                    )
+from dune.codegen.pdelab.driver.gridoperator import (name_gridoperator,
+                                                     type_gridoperator,
                                                      )
-from dune.perftool.pdelab.driver.gridoperator import (name_gridoperator,
-                                                      type_gridoperator,
-                                                      )
-from dune.perftool.pdelab.driver.interpolate import interpolate_dirichlet_data
-from dune.perftool.pdelab.geometry import world_dimension
+from dune.codegen.pdelab.driver.interpolate import interpolate_dirichlet_data
+from dune.codegen.pdelab.geometry import world_dimension
 
 
 @preamble(section="solver")
@@ -35,7 +35,7 @@ def dune_solve():
     if linear and matrix_free:
         go = name_gridoperator(form_ident)
         x = name_vector(form_ident)
-        include_file("dune/perftool/matrixfree.hh", filetag="driver")
+        include_file("dune/codegen/matrixfree.hh", filetag="driver")
         solve = "solveMatrixFree({},{});".format(go, x)
     elif linear and not matrix_free:
         slp = name_stationarylinearproblemsolver()
@@ -44,7 +44,7 @@ def dune_solve():
         # TODO copy of linear case and obviously broken, used to generate something ;)
         go = name_gridoperator(form_ident)
         x = name_vector(form_ident)
-        include_file("dune/perftool/matrixfree.hh", filetag="driver")
+        include_file("dune/codegen/matrixfree.hh", filetag="driver")
         solve = "solveNonlinearMatrixFree({},{});".format(go, x)
     elif not linear and not matrix_free:
         go_type = type_gridoperator(form_ident)
@@ -58,10 +58,10 @@ def dune_solve():
         print_matrix()
 
     if get_option('instrumentation_level') >= 2:
-        from dune.perftool.pdelab.driver.timings import setup_timer, name_timing_stream, name_timing_identifier
+        from dune.codegen.pdelab.driver.timings import setup_timer, name_timing_stream, name_timing_identifier
         timestream = name_timing_stream()
         setup_timer()
-        from dune.perftool.generation import post_include
+        from dune.codegen.generation import post_include
         post_include("HP_DECLARE_TIMER(solve);", filetag="driver")
 
         solve = ["HP_TIMER_START(solve);",
@@ -71,7 +71,7 @@ def dune_solve():
                  ]
 
         if get_option('instrumentation_level') >= 3:
-            from dune.perftool.pdelab.driver.gridoperator import name_localoperator
+            from dune.codegen.pdelab.driver.gridoperator import name_localoperator
             lop_name = name_localoperator(form_ident)
             solve.append("{}.dump_timers({}, {}, true);".format(lop_name, timestream, name_timing_identifier()))
 
diff --git a/python/dune/perftool/pdelab/driver/timings.py b/python/dune/codegen/pdelab/driver/timings.py
similarity index 80%
rename from python/dune/perftool/pdelab/driver/timings.py
rename to python/dune/codegen/pdelab/driver/timings.py
index b8ebd5f32dd368dc23119388f352b25cff9575a0..714f263a353c5a8a3a6b3b83dbc651ffd3401961 100644
--- a/python/dune/perftool/pdelab/driver/timings.py
+++ b/python/dune/codegen/pdelab/driver/timings.py
@@ -1,28 +1,28 @@
 """ Timing related generator functions """
 
-from dune.perftool.options import get_option
-from dune.perftool.generation import (cached,
-                                      include_file,
-                                      pre_include,
-                                      post_include,
-                                      preamble,
-                                      )
-from dune.perftool.pdelab.driver import (get_form_ident,
-                                         is_linear,
-                                         name_initree,
-                                         name_mpihelper,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_leafview,
-                                                           name_trial_gfs,
-                                                           type_leafview,
-                                                           )
-from dune.perftool.pdelab.driver.gridoperator import (name_gridoperator,
-                                                      name_localoperator,
-                                                      type_gridoperator,
-                                                      )
-from dune.perftool.pdelab.driver.solve import (name_vector,
-                                               type_vector,
-                                               )
+from dune.codegen.options import get_option
+from dune.codegen.generation import (cached,
+                                     include_file,
+                                     pre_include,
+                                     post_include,
+                                     preamble,
+                                     )
+from dune.codegen.pdelab.driver import (get_form_ident,
+                                        is_linear,
+                                        name_initree,
+                                        name_mpihelper,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_leafview,
+                                                          name_trial_gfs,
+                                                          type_leafview,
+                                                          )
+from dune.codegen.pdelab.driver.gridoperator import (name_gridoperator,
+                                                     name_localoperator,
+                                                     type_gridoperator,
+                                                     )
+from dune.codegen.pdelab.driver.solve import (name_vector,
+                                              type_vector,
+                                              )
 
 
 @preamble(section="timings")
@@ -45,7 +45,7 @@ def dump_dof_numbers(stream):
     gvt = type_leafview()
     gv = name_leafview()
 
-    from dune.perftool.pdelab.driver import get_trial_element, isDG, _flatten_list
+    from dune.codegen.pdelab.driver import get_trial_element, isDG, _flatten_list
     from ufl import MixedElement, TensorProductElement
     element = get_trial_element()
 
@@ -96,7 +96,7 @@ def setup_timer():
     if get_option('opcounter'):
         pre_include("#define ENABLE_COUNTER", filetag="driver")
     pre_include("#define ENABLE_HP_TIMERS", filetag="driver")
-    include_file("dune/perftool/common/timer.hh", filetag="driver")
+    include_file("dune/codegen/common/timer.hh", filetag="driver")
 
 
 @preamble(section="timings")
@@ -108,7 +108,7 @@ def evaluate_residual_timer():
 
     if get_option('instrumentation_level') >= 2:
         # Write back times
-        from dune.perftool.generation import post_include
+        from dune.codegen.generation import post_include
         post_include("HP_DECLARE_TIMER(residual_evaluation);", filetag="driver")
         timestream = name_timing_stream()
         print_times = []
@@ -140,7 +140,7 @@ def apply_jacobian_timer():
 
     if get_option('instrumentation_level') >= 2:
         # Write back times
-        from dune.perftool.generation import post_include
+        from dune.codegen.generation import post_include
         post_include("HP_DECLARE_TIMER(apply_jacobian);", filetag="driver")
         timestream = name_timing_stream()
         print_times = []
@@ -174,7 +174,7 @@ def assemble_matrix_timer():
 
     if get_option('instrumentation_level') >= 2:
         # Write back times
-        from dune.perftool.generation import post_include
+        from dune.codegen.generation import post_include
         post_include("HP_DECLARE_TIMER(matrix_assembly);", filetag="driver")
         timestream = name_timing_stream()
         print_times = []
diff --git a/python/dune/perftool/pdelab/driver/visitor.py b/python/dune/codegen/pdelab/driver/visitor.py
similarity index 77%
rename from python/dune/perftool/pdelab/driver/visitor.py
rename to python/dune/codegen/pdelab/driver/visitor.py
index c126e40d79a02b32501390ecf76f6c3bded07f72..0c45871f5d940a62f85386e7aaccd41d210d1abb 100644
--- a/python/dune/perftool/pdelab/driver/visitor.py
+++ b/python/dune/codegen/pdelab/driver/visitor.py
@@ -1,20 +1,20 @@
-from dune.perftool.generation import global_context, preamble
-from dune.perftool.ufl.visitor import UFL2LoopyVisitor
+from dune.codegen.generation import global_context, preamble
+from dune.codegen.ufl.visitor import UFL2LoopyVisitor
 
 import pymbolic.primitives as prim
 
 
 @preamble(section="gridoperator")
 def set_lop_to_starting_time():
-    from dune.perftool.pdelab.driver import get_form_ident
-    from dune.perftool.pdelab.driver.gridoperator import name_localoperator
+    from dune.codegen.pdelab.driver import get_form_ident
+    from dune.codegen.pdelab.driver.gridoperator import name_localoperator
     lop = name_localoperator(get_form_ident())
     return "{}.setTime(0.0);".format(lop)
 
 
 class DriverUFL2PymbolicVisitor(UFL2LoopyVisitor):
     def __init__(self):
-        from dune.perftool.pdelab import PDELabInterface
+        from dune.codegen.pdelab import PDELabInterface
         UFL2LoopyVisitor.__init__(self, PDELabInterface(), "exterior_facet", {})
 
     def __call__(self, expr):
@@ -40,8 +40,8 @@ class DriverUFL2PymbolicVisitor(UFL2LoopyVisitor):
 
     def coefficient(self, o):
         if o.count() == 2:
-            from dune.perftool.pdelab.driver import get_form_ident
-            from dune.perftool.pdelab.driver.gridoperator import name_localoperator
+            from dune.codegen.pdelab.driver import get_form_ident
+            from dune.codegen.pdelab.driver.gridoperator import name_localoperator
             lop = name_localoperator(get_form_ident())
             set_lop_to_starting_time()
             return prim.Call(prim.Variable("{}.getTime".format(lop)), ())
@@ -52,7 +52,7 @@ class DriverUFL2PymbolicVisitor(UFL2LoopyVisitor):
 def ufl_to_code(expr, boundary=True):
     # So far, we only considered this code branch on boundaries!
     assert boundary
-    from dune.perftool.pdelab.driver import get_form_ident
+    from dune.codegen.pdelab.driver import get_form_ident
     with global_context(integral_type="exterior_facet", form_identifier=get_form_ident()):
         visitor = DriverUFL2PymbolicVisitor()
         from pymbolic.mapper.c_code import CCodeMapper
diff --git a/python/dune/perftool/pdelab/driver/vtk.py b/python/dune/codegen/pdelab/driver/vtk.py
similarity index 77%
rename from python/dune/perftool/pdelab/driver/vtk.py
rename to python/dune/codegen/pdelab/driver/vtk.py
index 3004c4892870d078e5611c5f1ac3eabd4da704ee..dd66bea4973838be7ced00e7910fa0617456e540 100644
--- a/python/dune/perftool/pdelab/driver/vtk.py
+++ b/python/dune/codegen/pdelab/driver/vtk.py
@@ -1,18 +1,18 @@
-from dune.perftool.generation import (include_file,
-                                      preamble,
-                                      )
-from dune.perftool.options import get_form_option
-from dune.perftool.pdelab.driver import (get_form_ident,
-                                         get_trial_element,
-                                         name_initree,
-                                         preprocess_leaf_data,
-                                         )
-from dune.perftool.pdelab.driver.gridfunctionspace import (name_leafview,
-                                                           name_gfs,
-                                                           name_trial_gfs,
-                                                           type_leafview,
-                                                           )
-from dune.perftool.pdelab.driver.solve import name_vector
+from dune.codegen.generation import (include_file,
+                                     preamble,
+                                     )
+from dune.codegen.options import get_form_option
+from dune.codegen.pdelab.driver import (get_form_ident,
+                                        get_trial_element,
+                                        name_initree,
+                                        preprocess_leaf_data,
+                                        )
+from dune.codegen.pdelab.driver.gridfunctionspace import (name_leafview,
+                                                          name_gfs,
+                                                          name_trial_gfs,
+                                                          type_leafview,
+                                                          )
+from dune.codegen.pdelab.driver.solve import name_vector
 
 
 @preamble(section="vtk")
@@ -82,7 +82,7 @@ def vtkoutput():
 
 
 def type_predicate():
-    include_file("dune/perftool/vtkpredicate.hh", filetag="driver")
+    include_file("dune/codegen/vtkpredicate.hh", filetag="driver")
     return "CuttingPredicate"
 
 
@@ -131,7 +131,7 @@ def visualize_initial_condition():
     gfs = name_trial_gfs()
     vector = name_vector(get_form_ident())
     predicate = name_predicate()
-    from dune.perftool.pdelab.driver.instationary import name_time
+    from dune.codegen.pdelab.driver.instationary import name_time
     time = name_time()
     return ["Dune::PDELab::addSolutionToVTKWriter({}, {}, {}, Dune::PDELab::vtk::defaultNameScheme(), {});".format(vtkwriter, gfs, vector, predicate),
             "{}.write({}, Dune::VTK::appendedraw);".format(vtkwriter, time)]
diff --git a/python/dune/perftool/pdelab/function.py b/python/dune/codegen/pdelab/function.py
similarity index 72%
rename from python/dune/perftool/pdelab/function.py
rename to python/dune/codegen/pdelab/function.py
index c1dadef18fdcb8a60a88d06aff5fac186a80432d..74e6b6b6ad08cdf8b6b9c1f0a1c5aeeae5f3f3c9 100644
--- a/python/dune/perftool/pdelab/function.py
+++ b/python/dune/codegen/pdelab/function.py
@@ -1,13 +1,13 @@
-from dune.perftool.generation import (get_backend,
-                                      instruction,
-                                      kernel_cached,
-                                      preamble,
-                                      temporary_variable,
-                                      )
-from dune.perftool.pdelab.geometry import (name_cell,
-                                           world_dimension,
-                                           )
-from dune.perftool.pdelab.localoperator import name_gridfunction_member
+from dune.codegen.generation import (get_backend,
+                                     instruction,
+                                     kernel_cached,
+                                     preamble,
+                                     temporary_variable,
+                                     )
+from dune.codegen.pdelab.geometry import (name_cell,
+                                          world_dimension,
+                                          )
+from dune.codegen.pdelab.localoperator import name_gridfunction_member
 
 import pymbolic.primitives as prim
 
diff --git a/python/dune/perftool/pdelab/geometry.py b/python/dune/codegen/pdelab/geometry.py
similarity index 89%
rename from python/dune/perftool/pdelab/geometry.py
rename to python/dune/codegen/pdelab/geometry.py
index 1eebaae31f620bd89cc59f2906edb52a8b44d1af..7d1e722ad8d92143d44747cbc2622b7eec0431b2 100644
--- a/python/dune/perftool/pdelab/geometry.py
+++ b/python/dune/codegen/pdelab/geometry.py
@@ -1,24 +1,24 @@
-from dune.perftool.ufl.modified_terminals import Restriction
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.generation import (backend,
-                                      class_member,
-                                      domain,
-                                      get_backend,
-                                      get_global_context_value,
-                                      globalarg,
-                                      iname,
-                                      include_file,
-                                      kernel_cached,
-                                      preamble,
-                                      temporary_variable,
-                                      valuearg,
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   option_switch,
-                                   )
-from dune.perftool.loopy.target import dtype_floatingpoint, type_floatingpoint
-from dune.perftool.pdelab.quadrature import quadrature_preamble
-from dune.perftool.tools import get_pymbolic_basename
+from dune.codegen.ufl.modified_terminals import Restriction
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.generation import (backend,
+                                     class_member,
+                                     domain,
+                                     get_backend,
+                                     get_global_context_value,
+                                     globalarg,
+                                     iname,
+                                     include_file,
+                                     kernel_cached,
+                                     preamble,
+                                     temporary_variable,
+                                     valuearg,
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  option_switch,
+                                  )
+from dune.codegen.loopy.target import dtype_floatingpoint, type_floatingpoint
+from dune.codegen.pdelab.quadrature import quadrature_preamble
+from dune.codegen.tools import get_pymbolic_basename
 from ufl.algorithms import MultiFunction
 from pymbolic.primitives import Variable
 from pymbolic.primitives import Expression as PymbolicExpression
@@ -87,7 +87,7 @@ def type_intersection_geometry_wrapper():
 
 def name_geometry_wrapper():
     """ Selects the 'native' geometry wrapper of the kernel """
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     it = get_global_context_value("integral_type")
 
     if it == 'cell':
@@ -99,7 +99,7 @@ def name_geometry_wrapper():
 
 def type_geometry_wrapper():
     """ Selects the 'native' geometry wrapper of the kernel """
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     it = get_global_context_value("integral_type")
 
     if it == 'cell':
@@ -173,7 +173,7 @@ def name_intersection():
 
 def name_geometry():
     """ Selects the 'native' geometry of the kernel """
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     it = get_global_context_value("integral_type")
 
     if it == 'cell':
@@ -233,7 +233,7 @@ def to_cell_coordinates(local, restriction):
 def world_dimension():
     data = get_global_context_value("data")
     form = data.object_by_name[get_form_option("form")]
-    from dune.perftool.ufl.preprocess import preprocess_form
+    from dune.codegen.ufl.preprocess import preprocess_form
     form = preprocess_form(form).preprocessed_form
     return form.ufl_cell().geometric_dimension()
 
@@ -310,7 +310,7 @@ def define_jacobian_inverse_transposed_temporary(restriction):
 
 @preamble(kernel="operator")
 def define_constant_jacobian_inverse_transposed_eval(name):
-    from dune.perftool.pdelab.localoperator import name_ansatz_gfs_constructor_param, lop_template_range_field
+    from dune.codegen.pdelab.localoperator import name_ansatz_gfs_constructor_param, lop_template_range_field
     gfs = name_ansatz_gfs_constructor_param()
     rft = lop_template_range_field()
 
@@ -320,7 +320,7 @@ def define_constant_jacobian_inverse_transposed_eval(name):
 @class_member(classtag="operator")
 def define_constant_jacobian_inverse_transposed(name):
     define_constant_jacobian_inverse_transposed_eval(name)
-    from dune.perftool.pdelab.localoperator import lop_template_ansatz_gfs
+    from dune.codegen.pdelab.localoperator import lop_template_ansatz_gfs
     gfst = lop_template_ansatz_gfs()
     return "typename {}::Traits::GridView::template Codim<0>::Geometry::JacobianInverseTransposed {};".format(gfst, name)
 
@@ -367,7 +367,7 @@ def pymbolic_jacobian_inverse(i, j, restriction):
 
 @preamble(kernel="operator")
 def define_constant_jacobian_determinant_eval(name):
-    from dune.perftool.pdelab.localoperator import name_ansatz_gfs_constructor_param, lop_template_range_field
+    from dune.codegen.pdelab.localoperator import name_ansatz_gfs_constructor_param, lop_template_range_field
     gfs = name_ansatz_gfs_constructor_param()
     rft = lop_template_range_field()
 
@@ -377,7 +377,7 @@ def define_constant_jacobian_determinant_eval(name):
 @class_member(classtag="operator")
 def _define_constant_jacobian_determinant(name):
     define_constant_jacobian_determinant_eval(name)
-    from dune.perftool.pdelab.localoperator import lop_template_ansatz_gfs
+    from dune.codegen.pdelab.localoperator import lop_template_ansatz_gfs
     gfst = lop_template_ansatz_gfs()
     return "typename {}::Traits::GridView::template Codim<0>::Geometry::ctype {};".format(gfst, name)
 
@@ -500,13 +500,13 @@ def pymbolic_facet_area():
 
 
 def define_element_corners(name):
-    from dune.perftool.pdelab.driver import get_form
+    from dune.codegen.pdelab.driver import get_form
     n_corners = get_form().ufl_cell().num_vertices()
     temporary_variable(name, shape_impl=('fv', 'fv'), shape=(n_corners, local_dimension()))
 
     iname = "i_corner"
     domain(iname, n_corners)
-    from dune.perftool.generation import instruction
+    from dune.codegen.generation import instruction
     instruction(code="{0}[{1}] = {2}.corner({3});".format(name, iname, name_geometry(), iname),
                 assignees=frozenset({name}),
                 within_inames=frozenset({iname}), within_inames_is_final=True)
diff --git a/python/dune/perftool/pdelab/index.py b/python/dune/codegen/pdelab/index.py
similarity index 91%
rename from python/dune/perftool/pdelab/index.py
rename to python/dune/codegen/pdelab/index.py
index 73bf17eb655f95dbe59db620cca367b736009ea8..a456255f66a3605a81f6be5b5a36a62f73a63a44 100644
--- a/python/dune/perftool/pdelab/index.py
+++ b/python/dune/codegen/pdelab/index.py
@@ -1,4 +1,4 @@
-from dune.perftool.generation import kernel_cached
+from dune.codegen.generation import kernel_cached
 
 from ufl.classes import MultiIndex, Index
 
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/codegen/pdelab/localoperator.py
similarity index 87%
rename from python/dune/perftool/pdelab/localoperator.py
rename to python/dune/codegen/pdelab/localoperator.py
index 9c7aab0ff537ac0641a9f4cb5807dcf608bf960c..c598232f2ac4a9f1069740551c699365de62a5a9 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/codegen/pdelab/localoperator.py
@@ -5,40 +5,40 @@ import logging
 
 import numpy as np
 
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   option_switch,
-                                   set_form_option)
-from dune.perftool.generation import (backend,
-                                      base_class,
-                                      class_basename,
-                                      class_member,
-                                      constructor_parameter,
-                                      domain,
-                                      dump_accumulate_timer,
-                                      end_of_file,
-                                      function_mangler,
-                                      generator_factory,
-                                      get_backend,
-                                      get_global_context_value,
-                                      global_context,
-                                      iname,
-                                      include_file,
-                                      initializer_list,
-                                      post_include,
-                                      retrieve_cache_functions,
-                                      retrieve_cache_items,
-                                      ReturnArg,
-                                      run_hook,
-                                      template_parameter,
-                                      )
-from dune.perftool.cgen.clazz import (AccessModifier,
-                                      BaseClass,
-                                      ClassMember,
-                                      )
-from dune.perftool.ufl.modified_terminals import Restriction
-
-import dune.perftool.loopy.mangler
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  option_switch,
+                                  set_form_option)
+from dune.codegen.generation import (backend,
+                                     base_class,
+                                     class_basename,
+                                     class_member,
+                                     constructor_parameter,
+                                     domain,
+                                     dump_accumulate_timer,
+                                     end_of_file,
+                                     function_mangler,
+                                     generator_factory,
+                                     get_backend,
+                                     get_global_context_value,
+                                     global_context,
+                                     iname,
+                                     include_file,
+                                     initializer_list,
+                                     post_include,
+                                     retrieve_cache_functions,
+                                     retrieve_cache_items,
+                                     ReturnArg,
+                                     run_hook,
+                                     template_parameter,
+                                     )
+from dune.codegen.cgen.clazz import (AccessModifier,
+                                     BaseClass,
+                                     ClassMember,
+                                     )
+from dune.codegen.ufl.modified_terminals import Restriction
+
+import dune.codegen.loopy.mangler
 
 from pymbolic.primitives import Variable
 import pymbolic.primitives as prim
@@ -123,9 +123,9 @@ def _enum_pattern(which):
 
 
 def enum_pattern():
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
-    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
+    from dune.codegen.pdelab.signatures import ufl_measure_to_pdelab_measure
     return _enum_pattern(ufl_measure_to_pdelab_measure(integral_type))
 
 
@@ -134,9 +134,9 @@ def _pattern_baseclass(measure):
 
 
 def pattern_baseclass():
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
-    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
+    from dune.codegen.pdelab.signatures import ufl_measure_to_pdelab_measure
     return _pattern_baseclass(ufl_measure_to_pdelab_measure(integral_type))
 
 
@@ -146,9 +146,9 @@ def _enum_alpha(which):
 
 
 def enum_alpha():
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
-    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
+    from dune.codegen.pdelab.signatures import ufl_measure_to_pdelab_measure
     return _enum_alpha(ufl_measure_to_pdelab_measure(integral_type))
 
 
@@ -200,7 +200,7 @@ def type_gridfunction_template_parameter(coeff):
 
 
 def class_type_from_cache(classtag):
-    from dune.perftool.generation import retrieve_cache_items
+    from dune.codegen.generation import retrieve_cache_items
 
     # get the basename
     basename = [i for i in retrieve_cache_items(condition="{} and basename".format(classtag))]
@@ -256,18 +256,18 @@ def determine_accumulation_space(info, number):
         subel = element.extract_component(info.element_index)[1]
 
     # And generate a local function space for it!
-    from dune.perftool.pdelab.spaces import name_lfs, name_lfs_bound, lfs_iname
+    from dune.codegen.pdelab.spaces import name_lfs, name_lfs_bound, lfs_iname
     lfs = name_lfs(element, info.restriction, info.element_index)
-    from dune.perftool.generation import valuearg
+    from dune.codegen.generation import valuearg
     from loopy.types import NumpyType
     valuearg(lfs, dtype=NumpyType("str"))
 
     if get_form_option("blockstructured"):
-        from dune.perftool.blockstructured.tools import micro_index_to_macro_index
-        from dune.perftool.blockstructured.spaces import lfs_inames
+        from dune.codegen.blockstructured.tools import micro_index_to_macro_index
+        from dune.codegen.blockstructured.spaces import lfs_inames
         lfsi = micro_index_to_macro_index(subel, lfs_inames(subel, info.restriction, count=number))
     else:
-        from dune.perftool.pdelab.spaces import lfs_inames
+        from dune.codegen.pdelab.spaces import lfs_inames
         lfsi = Variable(lfs_iname(subel, info.restriction, count=number))
 
     # If the LFS is not yet a pymbolic expression, make it one
@@ -287,7 +287,7 @@ def boundary_predicates(measure, subdomain_id):
 
     if subdomain_id not in ['everywhere', 'otherwise']:
         # Get the original form and inspect the present measures
-        from dune.perftool.generation import get_global_context_value
+        from dune.codegen.generation import get_global_context_value
         data = get_global_context_value("data")
         original_form = data.object_by_name[get_form_option("form")]
 
@@ -350,7 +350,7 @@ class PDELabAccumulationInfo(ImmutableRecord):
 
 
 def _list_infos(expr, number, visitor):
-    from dune.perftool.ufl.modified_terminals import extract_modified_arguments
+    from dune.codegen.ufl.modified_terminals import extract_modified_arguments
     ma = extract_modified_arguments(expr, argnumber=number)
     if len(ma) == 0:
         if number == 1:
@@ -410,20 +410,20 @@ def generate_accumulation_instruction(expr, visitor):
     ansatz_lfs = determine_accumulation_space(visitor.trial_info, 1)
 
     # Collect the lfs and lfs indices for the accumulate call
-    from dune.perftool.pdelab.argument import name_accumulation_variable
+    from dune.codegen.pdelab.argument import name_accumulation_variable
     accumvar = name_accumulation_variable(test_lfs.get_restriction() + ansatz_lfs.get_restriction())
 
     predicates = boundary_predicates(visitor.measure, visitor.subdomain_id)
     rank = 1 if ansatz_lfs.lfs is None else 2
 
-    from dune.perftool.pdelab.argument import PDELabAccumulationFunction
+    from dune.codegen.pdelab.argument import PDELabAccumulationFunction
     from pymbolic.primitives import Call
     accexpr = Call(PDELabAccumulationFunction(accumvar, rank),
                    (test_lfs.get_args() + ansatz_lfs.get_args() + (expr,))
                    )
 
-    from dune.perftool.generation import instruction
-    from dune.perftool.options import option_switch
+    from dune.codegen.generation import instruction
+    from dune.codegen.options import option_switch
     quad_inames = visitor.interface.quadrature_inames()
     lfs_inames = frozenset(visitor.test_info.inames)
     if visitor.trial_info:
@@ -440,16 +440,16 @@ def generate_accumulation_instruction(expr, visitor):
 def get_visitor(measure, subdomain_id):
     # Get a transformer instance for this kernel
     if get_form_option('sumfact'):
-        from dune.perftool.sumfact import SumFactInterface
+        from dune.codegen.sumfact import SumFactInterface
         interface = SumFactInterface()
     elif get_form_option('blockstructured'):
-        from dune.perftool.blockstructured import BlockStructuredInterface
+        from dune.codegen.blockstructured import BlockStructuredInterface
         interface = BlockStructuredInterface()
     else:
-        from dune.perftool.pdelab import PDELabInterface
+        from dune.codegen.pdelab import PDELabInterface
         interface = PDELabInterface()
 
-    from dune.perftool.ufl.visitor import UFL2LoopyVisitor
+    from dune.codegen.ufl.visitor import UFL2LoopyVisitor
     return UFL2LoopyVisitor(interface, measure, subdomain_id)
 
 
@@ -482,25 +482,25 @@ def generate_kernel(integrals):
             visit_integral(integral)
 
     # Now perform some checks on what should be done
-    from dune.perftool.sumfact.vectorization import decide_vectorization_strategy
+    from dune.codegen.sumfact.vectorization import decide_vectorization_strategy
     logger.debug('generate_kernel: decide_vectorization_strategy')
     decide_vectorization_strategy()
 
     # Delete the cache contents and do the real thing!
     logger.debug('generate_kernel: visit_integrals (no dry run)')
-    from dune.perftool.generation import delete_cache_items
+    from dune.codegen.generation import delete_cache_items
     delete_cache_items("kernel_default")
     for integral in integrals:
         visit_integral(integral)
 
-    from dune.perftool.pdelab.signatures import kernel_name, assembly_routine_signature
+    from dune.codegen.pdelab.signatures import kernel_name, assembly_routine_signature
     name = kernel_name()
     signature = assembly_routine_signature()
     knl = extract_kernel_from_cache("kernel_default", name, signature)
     delete_cache_items("kernel_default")
 
     # Reset the quadrature degree
-    from dune.perftool.sumfact.tabulation import set_quadrature_points
+    from dune.codegen.sumfact.tabulation import set_quadrature_points
     set_quadrature_points(None)
 
     # Clean the cache from any data collected after the dry run
@@ -521,7 +521,7 @@ def generate_kernels_per_integral(integrals):
 
 def extract_kernel_from_cache(tag, name, signature, wrap_in_cgen=True, add_timings=True):
     # Now extract regular loopy kernel components
-    from dune.perftool.loopy.target import DuneTarget
+    from dune.codegen.loopy.target import DuneTarget
     domains = [i for i in retrieve_cache_items("{} and domain".format(tag))]
 
     if not domains:
@@ -560,18 +560,18 @@ def extract_kernel_from_cache(tag, name, signature, wrap_in_cgen=True, add_timin
     for trafo in transformations:
         kernel = trafo[0](kernel, *trafo[1], **trafo[2])
 
-    from dune.perftool.loopy import heuristic_duplication
+    from dune.codegen.loopy import heuristic_duplication
     kernel = heuristic_duplication(kernel)
 
     # Maybe apply vectorization strategies
     if get_form_option("vectorization_quadloop"):
         if get_form_option("sumfact"):
-            from dune.perftool.loopy.transformations.vectorize_quad import vectorize_quadrature_loop
+            from dune.codegen.loopy.transformations.vectorize_quad import vectorize_quadrature_loop
             kernel = vectorize_quadrature_loop(kernel)
         else:
             raise NotImplementedError("Only vectorizing sumfactorized code right now!")
     if get_form_option("vectorization_blockstructured"):
-        from dune.perftool.blockstructured.vectorization import vectorize_micro_elements
+        from dune.codegen.blockstructured.vectorization import vectorize_micro_elements
         kernel = vectorize_micro_elements(kernel)
 
     # Now add the preambles to the kernel
@@ -587,13 +587,13 @@ def extract_kernel_from_cache(tag, name, signature, wrap_in_cgen=True, add_timin
     # *REALLY* ignore boostability. This is - so far - necessary due to a mystery bug.
     kernel = kernel.copy(instructions=[i.copy(boostable=False, boostable_into=frozenset()) for i in kernel.instructions])
 
-    from dune.perftool.loopy.transformations.matchfma import match_fused_multiply_add
+    from dune.codegen.loopy.transformations.matchfma import match_fused_multiply_add
     kernel = match_fused_multiply_add(kernel)
 
     # Add instrumentation to the kernel
-    from dune.perftool.loopy.transformations.instrumentation import add_instrumentation
+    from dune.codegen.loopy.transformations.instrumentation import add_instrumentation
     if add_timings and get_form_option("sumfact"):
-        from dune.perftool.pdelab.signatures import assembler_routine_name
+        from dune.codegen.pdelab.signatures import assembler_routine_name
         kernel = add_instrumentation(kernel, lp.match.Tagged("sumfact_stage1"), "{}_kernel_stage1".format(assembler_routine_name()), 4)
         kernel = add_instrumentation(kernel, lp.match.Tagged("sumfact_stage2"), "{}_kernel_quadratureloop".format(assembler_routine_name()), 4, depends_on=frozenset({lp.match.Tagged("sumfact_stage1")}))
         kernel = add_instrumentation(kernel, lp.match.Tagged("sumfact_stage3"), "{}_kernel_stage3".format(assembler_routine_name()), 4, depends_on=frozenset({lp.match.Tagged("sumfact_stage2")}))
@@ -601,7 +601,7 @@ def extract_kernel_from_cache(tag, name, signature, wrap_in_cgen=True, add_timin
     if wrap_in_cgen:
         # Wrap the kernel in something which can generate code
         if signature is None:
-            from dune.perftool.pdelab.signatures import assembly_routine_signature
+            from dune.codegen.pdelab.signatures import assembly_routine_signature
             signature = assembly_routine_signature()
         kernel = LoopyKernelMethod(signature, kernel, add_timings=add_timings)
 
@@ -659,7 +659,7 @@ class LoopyKernelMethod(ClassMember):
         if kernel is not None:
             # Start timer
             if add_timings and get_option('instrumentation_level') >= 3:
-                from dune.perftool.pdelab.signatures import assembler_routine_name
+                from dune.codegen.pdelab.signatures import assembler_routine_name
                 timer_name = assembler_routine_name() + '_kernel'
                 name_example_kernel(name=timer_name)
                 post_include('HP_DECLARE_TIMER({});'.format(timer_name), filetag='operatorfile')
@@ -688,7 +688,7 @@ class LoopyKernelMethod(ClassMember):
 
 
 def cgen_class_from_cache(tag, members=[]):
-    from dune.perftool.generation import retrieve_cache_items
+    from dune.codegen.generation import retrieve_cache_items
 
     # Sort the given member functions by their name to help debugging by fixing
     # the order
@@ -705,7 +705,7 @@ def cgen_class_from_cache(tag, members=[]):
 
     # Construct the constructor
     constructor_knl = extract_kernel_from_cache(tag, "constructor_kernel", None, wrap_in_cgen=False, add_timings=False)
-    from dune.perftool.loopy.target import DuneTarget
+    from dune.codegen.loopy.target import DuneTarget
     constructor_knl = constructor_knl.copy(target=DuneTarget(declare_temporaries=False))
     signature = "{}({})".format(basename, ", ".join(next(iter(p.generate(with_semicolon=False))) for p in constructor_params))
     constructor = LoopyKernelMethod([signature], constructor_knl, add_timings=False, initializer_list=il)
@@ -729,7 +729,7 @@ def cgen_class_from_cache(tag, members=[]):
                                         )
     decls = [cgen.Line("\n  " + next(iter(d.generate()))) for d in target.get_device_ast_builder().get_temporary_decls(codegen_state, 0)]
 
-    from dune.perftool.cgen import Class
+    from dune.codegen.cgen import Class
     return Class(basename, base_classes=base_classes, members=[constructor] + members + pm + decls, tparam_decls=tparams)
 
 
@@ -762,16 +762,16 @@ def local_operator_default_settings(operator, form):
         name_gridfunction_constructor_argument(c)
 
     # Set some options!
-    from dune.perftool.pdelab.driver import isQuadrilateral
+    from dune.codegen.pdelab.driver import isQuadrilateral
     if isQuadrilateral(form.arguments()[0].ufl_element().cell()) and not get_option("grid_unstructured"):
-        from dune.perftool.options import set_form_option
+        from dune.codegen.options import set_form_option
         # For Yasp Grids the jacobian of the transformation is diagonal and constant on each cell
         set_form_option('diagonal_transformation_matrix', True)
         set_form_option('constant_transformation_matrix', True)
 
     # Add right base classes for stationary/instationary operators
     base_class('Dune::PDELab::LocalOperatorDefaultFlags', classtag="operator")
-    from dune.perftool.pdelab.driver import is_stationary
+    from dune.codegen.pdelab.driver import is_stationary
     if not is_stationary():
         rf = lop_template_range_field()
         base_class('Dune::PDELab::InstationaryLocalOperatorDefaultMethods<{}>'
@@ -790,7 +790,7 @@ def generate_residual_kernels(form, original_form):
         for measure in set(i.integral_type() for i in form.integrals()):
             logger.info("generate_residual_kernels: measure {}".format(measure))
             with global_context(integral_type=measure):
-                from dune.perftool.pdelab.signatures import assembler_routine_name
+                from dune.codegen.pdelab.signatures import assembler_routine_name
                 with global_context(kernel=assembler_routine_name()):
                     kernel = [k for k in get_backend(interface="generate_kernels_per_integral")(form.integrals_by_type(measure))]
 
@@ -808,7 +808,7 @@ def generate_residual_kernels(form, original_form):
 
                     # Numerical jacobian base class
                     _, loptype = class_type_from_cache("operator")
-                    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
+                    from dune.codegen.pdelab.signatures import ufl_measure_to_pdelab_measure
                     which = ufl_measure_to_pdelab_measure(measure)
                     base_class("Dune::PDELab::NumericalJacobian{}<{}>".format(which, loptype), classtag="operator")
 
@@ -822,7 +822,7 @@ def generate_residual_kernels(form, original_form):
 
                     # In the case of matrix free operator evaluation we need jacobian apply methods
                     if get_form_option("generate_jacobian_apply"):
-                        from dune.perftool.pdelab.driver import is_linear
+                        from dune.codegen.pdelab.driver import is_linear
                         if is_linear(original_form):
                             # Numeical jacobian apply base class
                             base_class("Dune::PDELab::NumericalJacobianApply{}<{}>".format(which, loptype), classtag="operator")
@@ -853,14 +853,14 @@ def generate_jacobian_kernels(form, original_form):
     from ufl import derivative
     jacform = derivative(original_form, original_form.coefficients()[0])
 
-    from dune.perftool.ufl.preprocess import preprocess_form
+    from dune.codegen.ufl.preprocess import preprocess_form
     jacform = preprocess_form(jacform).preprocessed_form
 
     if get_form_option("block_preconditioner_diagonal"):
-        from dune.perftool.ufl.transformations.blockpreconditioner import diagonal_block_jacobian
+        from dune.codegen.ufl.transformations.blockpreconditioner import diagonal_block_jacobian
         jacform = diagonal_block_jacobian(jacform)
     if get_form_option("block_preconditioner_offdiagonal"):
-        from dune.perftool.ufl.transformations.blockpreconditioner import offdiagonal_block_jacobian
+        from dune.codegen.ufl.transformations.blockpreconditioner import offdiagonal_block_jacobian
         jacform = offdiagonal_block_jacobian(jacform)
 
     operator_kernels = {}
@@ -877,7 +877,7 @@ def generate_jacobian_kernels(form, original_form):
         with global_context(form_type="jacobian_apply"):
             for measure in set(i.integral_type() for i in jac_apply_form.integrals()):
                 with global_context(integral_type=measure):
-                    from dune.perftool.pdelab.signatures import assembler_routine_name
+                    from dune.codegen.pdelab.signatures import assembler_routine_name
                     with global_context(kernel=assembler_routine_name()):
                         kernel = [k for k in get_backend(interface="generate_kernels_per_integral")(jac_apply_form.integrals_by_type(measure))]
                 operator_kernels[(measure, 'jacobian_apply')] = kernel
@@ -889,7 +889,7 @@ def generate_jacobian_kernels(form, original_form):
                 jacobian_apply_measures = set(i.integral_type() for i in jac_apply_form.integrals())
                 for it in alpha_measures - jacobian_apply_measures:
                     with global_context(integral_type=it):
-                        from dune.perftool.pdelab.signatures import assembly_routine_signature
+                        from dune.codegen.pdelab.signatures import assembly_routine_signature
                         operator_kernels[(it, 'jacobian_apply')] = [LoopyKernelMethod(assembly_routine_signature(), kernel=None)]
     if get_form_option("generate_jacobians"):
         with global_context(form_type="jacobian"):
@@ -901,7 +901,7 @@ def generate_jacobian_kernels(form, original_form):
                 for measure in set(i.integral_type() for i in jacform.integrals()):
                     logger.info("generate_jacobian_kernels: measure {}".format(measure))
                     with global_context(integral_type=measure):
-                        from dune.perftool.pdelab.signatures import assembler_routine_name
+                        from dune.codegen.pdelab.signatures import assembler_routine_name
                         with global_context(kernel=assembler_routine_name()):
                             kernel = [k for k in get_backend(interface="generate_kernels_per_integral")(jacform.integrals_by_type(measure))]
                     operator_kernels[(measure, 'jacobian')] = kernel
@@ -913,7 +913,7 @@ def generate_jacobian_kernels(form, original_form):
                 jacobian_measures = set(i.integral_type() for i in jacform.integrals())
                 for it in alpha_measures - jacobian_measures:
                     with global_context(integral_type=it):
-                        from dune.perftool.pdelab.signatures import assembly_routine_signature
+                        from dune.codegen.pdelab.signatures import assembly_routine_signature
                         operator_kernels[(it, 'jacobian')] = [LoopyKernelMethod(assembly_routine_signature(), kernel=None)]
                 if get_form_option("sumfact_regular_jacobians"):
                     if was_sumfact:
@@ -934,12 +934,12 @@ def generate_control_kernels(forms):
         for measure in set(i.integral_type() for form in forms for i in form.integrals()):
             logger.info("generate_control_kernels: measure {}".format(measure))
             with global_context(integral_type=measure):
-                from dune.perftool.pdelab.signatures import assembler_routine_name
+                from dune.codegen.pdelab.signatures import assembler_routine_name
                 with global_context(kernel=assembler_routine_name()):
                     # TODO: Sumfactorization not yet implemented
                     assert not get_form_option('sumfact')
 
-                    from dune.perftool.pdelab.adjoint import control_generate_kernels_per_integral
+                    from dune.codegen.pdelab.adjoint import control_generate_kernels_per_integral
                     forms_measure = [form.integrals_by_type(measure) for form in forms]
                     kernel = [k for k in control_generate_kernels_per_integral(forms_measure)]
 
@@ -960,7 +960,7 @@ def generate_localoperator_kernels(operator):
 
     data = get_global_context_value("data")
     original_form = data.object_by_name[get_form_option("form")]
-    from dune.perftool.ufl.preprocess import preprocess_form
+    from dune.codegen.ufl.preprocess import preprocess_form
 
     if get_form_option("adjoint"):
         # Generate adjoint operator
@@ -1051,7 +1051,7 @@ def generate_localoperator_kernels(operator):
         form = preprocess_form(original_form).preprocessed_form
 
     # Reset the generation cache
-    from dune.perftool.generation import delete_cache_items
+    from dune.codegen.generation import delete_cache_items
     delete_cache_items()
 
     # Have a data structure collect the generated kernels
@@ -1088,20 +1088,20 @@ def generate_localoperator_file(kernels, filename):
     if sfkernels:
         logger.info("generate_localoperator_kernels: Create {} sumfact kernel realizations".format(len(sfkernels)))
 
-    from dune.perftool.sumfact.realization import realize_sumfact_kernel_function
+    from dune.codegen.sumfact.realization import realize_sumfact_kernel_function
     for sf, qp in sfkernels:
-        from dune.perftool.sumfact.tabulation import set_quadrature_points
+        from dune.codegen.sumfact.tabulation import set_quadrature_points
         set_quadrature_points(qp)
         operator_methods.append(realize_sumfact_kernel_function(sf))
 
     if get_option('instrumentation_level') >= 3:
-        include_file('dune/perftool/common/timer.hh', filetag='operatorfile')
+        include_file('dune/codegen/common/timer.hh', filetag='operatorfile')
         operator_methods.append(TimerMethod())
     elif get_option('opcounter'):
-        include_file('dune/perftool/common/timer.hh', filetag='operatorfile')
+        include_file('dune/codegen/common/timer.hh', filetag='operatorfile')
 
     # Write the file!
-    from dune.perftool.file import generate_file
+    from dune.codegen.file import generate_file
     # TODO take the name of this thing from the UFL file
     lop = cgen_class_from_cache("operator", members=operator_methods)
     generate_file(filename, "operatorfile", [lop])
diff --git a/python/dune/perftool/pdelab/quadrature.py b/python/dune/codegen/pdelab/quadrature.py
similarity index 81%
rename from python/dune/perftool/pdelab/quadrature.py
rename to python/dune/codegen/pdelab/quadrature.py
index 031d97b019df0cab8355d4295b5229584e077b9b..8c3e2b36df63b3120883fd51737fc5ded051b157 100644
--- a/python/dune/perftool/pdelab/quadrature.py
+++ b/python/dune/codegen/pdelab/quadrature.py
@@ -1,20 +1,20 @@
 import numpy
 
-from dune.perftool.generation import (backend,
-                                      class_member,
-                                      domain,
-                                      get_backend,
-                                      get_global_context_value,
-                                      globalarg,
-                                      iname,
-                                      include_file,
-                                      instruction,
-                                      preamble,
-                                      temporary_variable,
-                                      valuearg,
-                                      )
-from dune.perftool.pdelab.localoperator import lop_template_range_field
-from dune.perftool.options import get_form_option
+from dune.codegen.generation import (backend,
+                                     class_member,
+                                     domain,
+                                     get_backend,
+                                     get_global_context_value,
+                                     globalarg,
+                                     iname,
+                                     include_file,
+                                     instruction,
+                                     preamble,
+                                     temporary_variable,
+                                     valuearg,
+                                     )
+from dune.codegen.pdelab.localoperator import lop_template_range_field
+from dune.codegen.options import get_form_option
 
 from pymbolic.primitives import Variable, Subscript
 
@@ -22,7 +22,7 @@ from pymbolic.primitives import Variable, Subscript
 @preamble
 def define_quadrature_rule(name):
     include_file('dune/pdelab/common/quadraturerules.hh', filetag='operatorfile')
-    from dune.perftool.pdelab.geometry import name_geometry
+    from dune.codegen.pdelab.geometry import name_geometry
     geo = name_geometry()
     order = name_quadrature_order()
     return "const auto {} = quadratureRule({}, {});".format(name, geo, order)
@@ -73,17 +73,17 @@ def name_quadrature_point():
 
 @preamble
 def fill_quadrature_points_cache(name):
-    from dune.perftool.pdelab.geometry import name_geometry
+    from dune.codegen.pdelab.geometry import name_geometry
     geo = name_geometry()
     quad_order = quadrature_order()
-    include_file("dune/perftool/localbasiscache.hh", filetag='operatorfile')
+    include_file("dune/codegen/localbasiscache.hh", filetag='operatorfile')
     return "fillQuadraturePointsCache({}, {}, {});".format(geo, quad_order, name)
 
 
 @class_member(classtag="operator")
 def typedef_quadrature_points(name):
     range_field = lop_template_range_field()
-    from dune.perftool.pdelab.geometry import local_dimension
+    from dune.codegen.pdelab.geometry import local_dimension
     dim = local_dimension()
     return "using {} = typename Dune::QuadraturePoint<{}, {}>::Vector;".format(name, range_field, dim)
 
@@ -102,7 +102,7 @@ def define_quadrature_points(name):
 
 def name_quadrature_points():
     """Name of vector storing quadrature points as class member"""
-    from dune.perftool.pdelab.geometry import local_dimension
+    from dune.codegen.pdelab.geometry import local_dimension
     dim = local_dimension()
     order = quadrature_order()
     name = "qp_dim{}_order{}".format(dim, order)
@@ -123,24 +123,24 @@ def pymbolic_quadrature_position():
 
 @backend(interface="qp_in_cell")
 def pymbolic_quadrature_position_in_cell(restriction):
-    from dune.perftool.pdelab.geometry import to_cell_coordinates
+    from dune.codegen.pdelab.geometry import to_cell_coordinates
     quad_pos = get_backend("quad_pos")()
     return to_cell_coordinates(quad_pos, restriction)
 
 
 @preamble
 def fill_quadrature_weights_cache(name):
-    from dune.perftool.pdelab.geometry import name_geometry
+    from dune.codegen.pdelab.geometry import name_geometry
     geo = name_geometry()
     quad_order = quadrature_order()
-    include_file("dune/perftool/localbasiscache.hh", filetag='operatorfile')
+    include_file("dune/codegen/localbasiscache.hh", filetag='operatorfile')
     return "fillQuadratureWeightsCache({}, {}, {});".format(geo, quad_order, name)
 
 
 @class_member(classtag="operator")
 def typedef_quadrature_weights(name):
     range_field = lop_template_range_field()
-    from dune.perftool.pdelab.geometry import local_dimension
+    from dune.codegen.pdelab.geometry import local_dimension
     dim = local_dimension()
     return "using {} = typename Dune::QuadraturePoint<{}, {}>::Field;".format(name, range_field, dim)
 
@@ -165,7 +165,7 @@ def define_quadrature_weights(name):
 
 def name_quadrature_weights():
     """"Name of vector storing quadrature weights as class member"""
-    from dune.perftool.pdelab.geometry import local_dimension
+    from dune.codegen.pdelab.geometry import local_dimension
     dim = local_dimension()
     order = quadrature_order()
     name = "qw_dim{}_order{}".format(dim, order)
@@ -185,7 +185,7 @@ def _estimate_quadrature_order():
     # should only be called on preprocessed forms.
     data = get_global_context_value("data")
     form = data.object_by_name[get_form_option("form")]
-    from dune.perftool.ufl.preprocess import preprocess_form
+    from dune.codegen.ufl.preprocess import preprocess_form
     form = preprocess_form(form).preprocessed_form
 
     # Estimate polynomial degree of integrals of current type (eg 'Cell')
@@ -239,7 +239,7 @@ def quadrature_order():
     if isinstance(quadrature_order, tuple):
         if not get_form_option('sumfact'):
             raise NotImplementedError("Different quadrature order per direction is only implemented for kernels using sum factorization.")
-        from dune.perftool.pdelab.geometry import world_dimension
+        from dune.codegen.pdelab.geometry import world_dimension
         assert(len(quadrature_order) == world_dimension())
 
     return quadrature_order
diff --git a/python/dune/perftool/pdelab/restriction.py b/python/dune/codegen/pdelab/restriction.py
similarity index 92%
rename from python/dune/perftool/pdelab/restriction.py
rename to python/dune/codegen/pdelab/restriction.py
index 03c55eaec4874c2611d892d74d8a14476cf8435d..d393fbe55b1d7da5e643d98386bbde5bbde6bcac 100644
--- a/python/dune/perftool/pdelab/restriction.py
+++ b/python/dune/codegen/pdelab/restriction.py
@@ -1,4 +1,4 @@
-from dune.perftool.ufl.modified_terminals import Restriction
+from dune.codegen.ufl.modified_terminals import Restriction
 
 
 def restricted_name(name, restriction):
diff --git a/python/dune/perftool/pdelab/signatures.py b/python/dune/codegen/pdelab/signatures.py
similarity index 92%
rename from python/dune/perftool/pdelab/signatures.py
rename to python/dune/codegen/pdelab/signatures.py
index 2990c8b24b9c89bcca243dce78c9144914c26b44..09b832ac252138181d8be19c9fd4c098b5bb9b68 100644
--- a/python/dune/perftool/pdelab/signatures.py
+++ b/python/dune/codegen/pdelab/signatures.py
@@ -1,20 +1,20 @@
 """ Signatures for PDELab local opreator assembly functions """
-from dune.perftool.generation import get_global_context_value
-from dune.perftool.ufl.modified_terminals import Restriction
-from dune.perftool.pdelab.geometry import (name_geometry_wrapper,
-                                           type_geometry_wrapper,
-                                           )
-from dune.perftool.pdelab.argument import (name_accumulation_variable,
-                                           type_accumulation_variable,
-                                           name_coefficientcontainer,
-                                           type_coefficientcontainer,
-                                           name_applycontainer,
-                                           )
-from dune.perftool.pdelab.spaces import (name_testfunctionspace,
-                                         type_testfunctionspace,
-                                         name_trialfunctionspace,
-                                         type_trialfunctionspace,
-                                         )
+from dune.codegen.generation import get_global_context_value
+from dune.codegen.ufl.modified_terminals import Restriction
+from dune.codegen.pdelab.geometry import (name_geometry_wrapper,
+                                          type_geometry_wrapper,
+                                          )
+from dune.codegen.pdelab.argument import (name_accumulation_variable,
+                                          type_accumulation_variable,
+                                          name_coefficientcontainer,
+                                          type_coefficientcontainer,
+                                          name_applycontainer,
+                                          )
+from dune.codegen.pdelab.spaces import (name_testfunctionspace,
+                                        type_testfunctionspace,
+                                        name_trialfunctionspace,
+                                        type_trialfunctionspace,
+                                        )
 
 
 def ufl_measure_to_pdelab_measure(which):
@@ -25,7 +25,7 @@ def ufl_measure_to_pdelab_measure(which):
 
 
 def assembler_routine_name():
-    from dune.perftool.generation import get_global_context_value
+    from dune.codegen.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
     form_type = get_global_context_value("form_type")
 
@@ -64,7 +64,7 @@ def assembly_routine_signature():
 
     if templates is None:
         # Check if form is linear
-        from dune.perftool.pdelab.driver import is_linear
+        from dune.codegen.pdelab.driver import is_linear
         linear = is_linear()
 
         templates, args = {('jacobian_apply', 'cell', True): (jacobian_apply_volume_templates, jacobian_apply_volume_args),
@@ -92,7 +92,7 @@ def assembly_routine_args():
 
     if args is None:
         # Check if form is linear
-        from dune.perftool.pdelab.driver import is_linear
+        from dune.codegen.pdelab.driver import is_linear
         linear = is_linear()
 
         args = {('jacobian_apply', 'cell', True): jacobian_apply_volume_args,
diff --git a/python/dune/perftool/pdelab/spaces.py b/python/dune/codegen/pdelab/spaces.py
similarity index 90%
rename from python/dune/perftool/pdelab/spaces.py
rename to python/dune/codegen/pdelab/spaces.py
index d5f62735ea0b1d98c3496f49f0d062fc62bd1e5a..d8c3c5684ce95e5a80baca6b8da11753f997607c 100644
--- a/python/dune/perftool/pdelab/spaces.py
+++ b/python/dune/codegen/pdelab/spaces.py
@@ -1,15 +1,15 @@
 """ Generator functions for PDELab local/grid function spaces etc. """
 
-from dune.perftool.generation import (class_member,
-                                      domain,
-                                      function_mangler,
-                                      generator_factory,
-                                      include_file,
-                                      preamble,
-                                      valuearg,
-                                      )
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.ufl.modified_terminals import Restriction
+from dune.codegen.generation import (class_member,
+                                     domain,
+                                     function_mangler,
+                                     generator_factory,
+                                     include_file,
+                                     preamble,
+                                     valuearg,
+                                     )
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.ufl.modified_terminals import Restriction
 
 from loopy import CallMangleInfo
 from loopy.symbolic import FunctionIdentifier
@@ -138,7 +138,7 @@ def initialize_function_spaces(expr, visitor):
                             restriction,
                             name=name_testfunctionspace(restriction))
         name_lfs(expr.ufl_element(), restriction, index)
-        from dune.perftool.pdelab.localoperator import lop_template_test_gfs
+        from dune.codegen.pdelab.localoperator import lop_template_test_gfs
         available_gfs_names(expr.ufl_element(), 0,
                             name=lop_template_test_gfs())
         type_gfs(expr.ufl_element(), restriction, index)
@@ -147,7 +147,7 @@ def initialize_function_spaces(expr, visitor):
                             restriction,
                             name=name_trialfunctionspace(restriction))
         name_lfs(expr.ufl_element(), restriction, index)
-        from dune.perftool.pdelab.localoperator import lop_template_ansatz_gfs
+        from dune.codegen.pdelab.localoperator import lop_template_ansatz_gfs
         available_gfs_names(expr.ufl_element(), 0,
                             name=lop_template_ansatz_gfs())
         type_gfs(expr.ufl_element(), restriction, index)
diff --git a/python/dune/perftool/pdelab/tensors.py b/python/dune/codegen/pdelab/tensors.py
similarity index 91%
rename from python/dune/perftool/pdelab/tensors.py
rename to python/dune/codegen/pdelab/tensors.py
index 3d89dd70995ffa12cde249ca77cac57b3d2149e9..754e7b24a8f639a3a73a3532ef56c888368dd2af 100644
--- a/python/dune/perftool/pdelab/tensors.py
+++ b/python/dune/codegen/pdelab/tensors.py
@@ -1,12 +1,12 @@
 """ Code generation for explicitly specified tensors """
 
-from dune.perftool.generation import (get_counted_variable,
-                                      domain,
-                                      kernel_cached,
-                                      iname,
-                                      instruction,
-                                      temporary_variable,
-                                      )
+from dune.codegen.generation import (get_counted_variable,
+                                     domain,
+                                     kernel_cached,
+                                     iname,
+                                     instruction,
+                                     temporary_variable,
+                                     )
 
 import pymbolic.primitives as prim
 import numpy as np
diff --git a/python/dune/perftool/sumfact/__init__.py b/python/dune/codegen/sumfact/__init__.py
similarity index 62%
rename from python/dune/perftool/sumfact/__init__.py
rename to python/dune/codegen/sumfact/__init__.py
index d3192b6f278bc7e0d050a500da86a09d905a4a7e..22a6049614784ced07c1e2a68739a094ec328516 100644
--- a/python/dune/perftool/sumfact/__init__.py
+++ b/python/dune/codegen/sumfact/__init__.py
@@ -1,36 +1,36 @@
-from dune.perftool.generation import get_backend
-from dune.perftool.options import option_switch
-from dune.perftool.pdelab.argument import (name_applycontainer,
-                                           name_coefficientcontainer,
-                                           )
-from dune.perftool.sumfact.quadrature import (quadrature_inames,
-                                              quadrature_weight,
-                                              )
+from dune.codegen.generation import get_backend
+from dune.codegen.options import option_switch
+from dune.codegen.pdelab.argument import (name_applycontainer,
+                                          name_coefficientcontainer,
+                                          )
+from dune.codegen.sumfact.quadrature import (quadrature_inames,
+                                             quadrature_weight,
+                                             )
 
-from dune.perftool.sumfact.basis import (lfs_inames,
-                                         pymbolic_basis,
-                                         pymbolic_reference_gradient,
-                                         pymbolic_coefficient,
-                                         pymbolic_coefficient_gradient,
-                                         )
+from dune.codegen.sumfact.basis import (lfs_inames,
+                                        pymbolic_basis,
+                                        pymbolic_reference_gradient,
+                                        pymbolic_coefficient,
+                                        pymbolic_coefficient_gradient,
+                                        )
 
-import dune.perftool.sumfact.accumulation
-import dune.perftool.sumfact.switch
+import dune.codegen.sumfact.accumulation
+import dune.codegen.sumfact.switch
 
-from dune.perftool.pdelab import PDELabInterface
+from dune.codegen.pdelab import PDELabInterface
 
 
 class SumFactInterface(PDELabInterface):
     def get_accumulation_info(self, expr, visitor):
-        from dune.perftool.sumfact.accumulation import get_accumulation_info
+        from dune.codegen.sumfact.accumulation import get_accumulation_info
         return get_accumulation_info(expr, visitor)
 
     def list_accumulation_infos(self, expr, visitor):
-        from dune.perftool.sumfact.accumulation import list_accumulation_infos
+        from dune.codegen.sumfact.accumulation import list_accumulation_infos
         return list_accumulation_infos(expr, visitor)
 
     def generate_accumulation_instruction(self, expr, visitor):
-        from dune.perftool.sumfact.accumulation import generate_accumulation_instruction
+        from dune.codegen.sumfact.accumulation import generate_accumulation_instruction
         return generate_accumulation_instruction(expr, visitor)
 
     def lfs_inames(self, element, restriction, number=None, context=''):
@@ -73,30 +73,30 @@ class SumFactInterface(PDELabInterface):
     #
 
     def pymbolic_spatial_coordinate(self):
-        import dune.perftool.sumfact.geometry
+        import dune.codegen.sumfact.geometry
         ret = get_backend(interface="spatial_coordinate", selector=option_switch("diagonal_transformation_matrix"))(self.visitor.do_predicates, self.visitor)
         return ret
 
     def pymbolic_unit_outer_normal(self):
-        from dune.perftool.sumfact.geometry import pymbolic_unit_outer_normal
+        from dune.codegen.sumfact.geometry import pymbolic_unit_outer_normal
         return pymbolic_unit_outer_normal(self.visitor)
 
     def pymbolic_unit_inner_normal(self):
-        from dune.perftool.sumfact.geometry import pymbolic_unit_inner_normal
+        from dune.codegen.sumfact.geometry import pymbolic_unit_inner_normal
         return pymbolic_unit_inner_normal(self.visitor)
 
     def pymbolic_facet_jacobian_determinant(self):
-        from dune.perftool.sumfact.geometry import pymbolic_facet_jacobian_determinant
+        from dune.codegen.sumfact.geometry import pymbolic_facet_jacobian_determinant
         return pymbolic_facet_jacobian_determinant(self.visitor)
 
     def pymbolic_facet_area(self):
-        from dune.perftool.sumfact.geometry import pymbolic_facet_area
+        from dune.codegen.sumfact.geometry import pymbolic_facet_area
         return pymbolic_facet_area(self.visitor)
 
     def pymbolic_jacobian_inverse(self, i, j, restriction):
-        from dune.perftool.sumfact.geometry import pymbolic_jacobian_inverse
+        from dune.codegen.sumfact.geometry import pymbolic_jacobian_inverse
         return pymbolic_jacobian_inverse(i, j, restriction, self.visitor)
 
     def pymbolic_jacobian_determinant(self):
-        from dune.perftool.sumfact.geometry import pymbolic_jacobian_determinant
+        from dune.codegen.sumfact.geometry import pymbolic_jacobian_determinant
         return pymbolic_jacobian_determinant(self.visitor)
diff --git a/python/dune/perftool/sumfact/accumulation.py b/python/dune/codegen/sumfact/accumulation.py
similarity index 83%
rename from python/dune/perftool/sumfact/accumulation.py
rename to python/dune/codegen/sumfact/accumulation.py
index 3bf16b24dd2e3fd5bd330319be2418770b6d3f93..5bf6703f3133bc4cdae6716480228c651e927976 100644
--- a/python/dune/perftool/sumfact/accumulation.py
+++ b/python/dune/codegen/sumfact/accumulation.py
@@ -1,46 +1,46 @@
 import itertools
 
-from dune.perftool.pdelab.argument import (name_accumulation_variable,
-                                           PDELabAccumulationFunction,
-                                           )
-from dune.perftool.generation import (backend,
-                                      domain,
-                                      dump_accumulate_timer,
-                                      generator_factory,
-                                      get_counted_variable,
-                                      get_counter,
-                                      get_global_context_value,
-                                      globalarg,
-                                      iname,
-                                      instruction,
-                                      post_include,
-                                      kernel_cached,
-                                      temporary_variable,
-                                      transform,
-                                      valuearg
-                                      )
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   )
-from dune.perftool.loopy.flatten import flatten_index
-from dune.perftool.loopy.target import type_floatingpoint
-from dune.perftool.pdelab.driver import FEM_name_mangling
-from dune.perftool.pdelab.localoperator import determine_accumulation_space
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.pdelab.signatures import assembler_routine_name
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.pdelab.spaces import name_lfs
-from dune.perftool.sumfact.tabulation import (basis_functions_per_direction,
-                                              construct_basis_matrix_sequence,
-                                              )
-from dune.perftool.sumfact.switch import (get_facedir,
-                                          get_facemod,
+from dune.codegen.pdelab.argument import (name_accumulation_variable,
+                                          PDELabAccumulationFunction,
                                           )
-from dune.perftool.sumfact.symbolic import SumfactKernel, SumfactKernelInterfaceBase
-from dune.perftool.ufl.modified_terminals import extract_modified_arguments
-from dune.perftool.tools import get_pymbolic_basename, get_leaf
-from dune.perftool.error import PerftoolError
-from dune.perftool.sumfact.quadrature import quadrature_inames
+from dune.codegen.generation import (backend,
+                                     domain,
+                                     dump_accumulate_timer,
+                                     generator_factory,
+                                     get_counted_variable,
+                                     get_counter,
+                                     get_global_context_value,
+                                     globalarg,
+                                     iname,
+                                     instruction,
+                                     post_include,
+                                     kernel_cached,
+                                     temporary_variable,
+                                     transform,
+                                     valuearg
+                                     )
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  )
+from dune.codegen.loopy.flatten import flatten_index
+from dune.codegen.loopy.target import type_floatingpoint
+from dune.codegen.pdelab.driver import FEM_name_mangling
+from dune.codegen.pdelab.localoperator import determine_accumulation_space
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.pdelab.signatures import assembler_routine_name
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.pdelab.spaces import name_lfs
+from dune.codegen.sumfact.tabulation import (basis_functions_per_direction,
+                                             construct_basis_matrix_sequence,
+                                             )
+from dune.codegen.sumfact.switch import (get_facedir,
+                                         get_facemod,
+                                         )
+from dune.codegen.sumfact.symbolic import SumfactKernel, SumfactKernelInterfaceBase
+from dune.codegen.ufl.modified_terminals import extract_modified_arguments
+from dune.codegen.tools import get_pymbolic_basename, get_leaf
+from dune.codegen.error import CodegenError
+from dune.codegen.sumfact.quadrature import quadrature_inames
 
 from pytools import ImmutableRecord, product
 
@@ -80,7 +80,7 @@ def accum_iname(element, bound, i):
     if element is None:
         suffix = ""
     else:
-        from dune.perftool.pdelab.driver import FEM_name_mangling
+        from dune.codegen.pdelab.driver import FEM_name_mangling
         suffix = "_{}".format(FEM_name_mangling(element))
     return sumfact_iname(bound, "accum{}".format(suffix))
 
@@ -120,7 +120,7 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord):
         if self.trial_element is None:
             return ()
         else:
-            from dune.perftool.sumfact.basis import lfs_inames
+            from dune.codegen.sumfact.basis import lfs_inames
             return lfs_inames(get_leaf(self.trial_element, self.trial_element_index), self.restriction)
 
     def realize(self, sf, result, insn_dep, inames=None, additional_inames=()):
@@ -133,7 +133,7 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord):
                            for i, mat in enumerate(sf.permuted_matrix_sequence))
 
             # Determine the expression to accumulate with. This depends on the vectorization strategy!
-            from dune.perftool.tools import maybe_wrap_subscript
+            from dune.codegen.tools import maybe_wrap_subscript
             result = maybe_wrap_subscript(result, tuple(prim.Variable(i) for i in inames))
 
         # Collect the lfs and lfs indices for the accumulate call
@@ -153,7 +153,7 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord):
             # elsewhere. This is *NOT* robust (but works right now)
             ansatz_lfs = name_lfs(self.trial_element, restriction[1], self.trial_element_index)
             valuearg(ansatz_lfs, dtype=lp.types.NumpyType("str"))
-            from dune.perftool.sumfact.basis import _basis_functions_per_direction
+            from dune.codegen.sumfact.basis import _basis_functions_per_direction
             ansatz_lfs_index = flatten_index(tuple(prim.Variable(sf.within_inames[i])
                                                    for i in range(world_dimension())),
                                              _basis_functions_per_direction(trial_leaf_element),
@@ -302,7 +302,7 @@ def get_accumulation_info(expr, visitor):
 
     restriction = visitor.restriction
     if visitor.measure == 'exterior_facet':
-        from dune.perftool.pdelab.restriction import Restriction
+        from dune.codegen.pdelab.restriction import Restriction
         restriction = Restriction.POSITIVE
 
     inames = visitor.interface.lfs_inames(leaf_element,
@@ -334,14 +334,14 @@ def _get_childs(element):
 
 
 def _test_generator(expr, visitor):
-    from dune.perftool.ufl.modified_terminals import extract_modified_arguments
+    from dune.codegen.ufl.modified_terminals import extract_modified_arguments
     ma = extract_modified_arguments(expr, argnumber=0)
     if len(ma) == 0:
         return
     element = ma[0].argexpr.ufl_element()
     dim = world_dimension()
 
-    from dune.perftool.ufl.modified_terminals import Restriction
+    from dune.codegen.ufl.modified_terminals import Restriction
     if visitor.measure == "cell":
         restrictions = (Restriction.NONE,)
     elif visitor.measure == "exterior_facet":
@@ -357,14 +357,14 @@ def _test_generator(expr, visitor):
 
 
 def _trial_generator(expr, visitor):
-    from dune.perftool.ufl.modified_terminals import extract_modified_arguments
+    from dune.codegen.ufl.modified_terminals import extract_modified_arguments
     ma = extract_modified_arguments(expr, argnumber=1)
     if len(ma) == 0:
         yield None
         return
     element = ma[0].argexpr.ufl_element()
 
-    from dune.perftool.ufl.modified_terminals import Restriction
+    from dune.codegen.ufl.modified_terminals import Restriction
     if visitor.measure == "cell":
         restrictions = (Restriction.NONE,)
     elif visitor.measure == "exterior_facet":
@@ -387,7 +387,7 @@ def generate_accumulation_instruction(expr, visitor):
     trial_info = visitor.trial_info
 
     # Count flops on the expression for the vectorization decision making algorithm
-    from dune.perftool.sumfact.vectorization import count_quadrature_point_operations
+    from dune.codegen.sumfact.vectorization import count_quadrature_point_operations
     count_quadrature_point_operations(expr)
 
     # Number of basis functions per direction
@@ -403,7 +403,7 @@ def generate_accumulation_instruction(expr, visitor):
     # Anisotropic finite elements are not (yet) supported by Dune
     assert(size == basis_size[0] for size in basis_size)
 
-    from dune.perftool.pdelab.localoperator import boundary_predicates
+    from dune.codegen.pdelab.localoperator import boundary_predicates
     predicates = boundary_predicates(visitor.measure,
                                      visitor.subdomain_id,
                                      )
@@ -415,7 +415,7 @@ def generate_accumulation_instruction(expr, visitor):
 
     insn_dep = None
 
-    from dune.perftool.pdelab.localoperator import determine_accumulation_space
+    from dune.codegen.pdelab.localoperator import determine_accumulation_space
     test_lfs = determine_accumulation_space(test_info, 0)
     ansatz_lfs = determine_accumulation_space(trial_info, 1)
 
@@ -426,7 +426,7 @@ def generate_accumulation_instruction(expr, visitor):
     if isinstance(trial_leaf_element, MixedElement):
         trial_leaf_element = trial_leaf_element.extract_component(trial_info.element_index)[1]
 
-    from dune.perftool.pdelab.argument import name_accumulation_variable
+    from dune.codegen.pdelab.argument import name_accumulation_variable
     accumvar = name_accumulation_variable(test_lfs.get_restriction() + ansatz_lfs.get_restriction())
 
     matrix_sequence = construct_basis_matrix_sequence(
@@ -455,7 +455,7 @@ def generate_accumulation_instruction(expr, visitor):
                        predicates=predicates,
                        )
 
-    from dune.perftool.sumfact.vectorization import attach_vectorization_info
+    from dune.codegen.sumfact.vectorization import attach_vectorization_info
     vsf = attach_vectorization_info(sf)
 
     # Make sure we have a buffer that we can set up the input with
@@ -465,7 +465,7 @@ def generate_accumulation_instruction(expr, visitor):
 
     vectag = frozenset({"gradvec"}) if vsf.vectorized else frozenset()
 
-    from dune.perftool.sumfact.realization import name_buffer_storage
+    from dune.codegen.sumfact.realization import name_buffer_storage
     temp = "input_{}".format(buffer)
     temporary_variable(temp,
                        shape=vsf.quadrature_shape,
@@ -488,7 +488,7 @@ def generate_accumulation_instruction(expr, visitor):
     # Determine dependencies
     from loopy.match import Or, Writes
     from loopy.symbolic import DependencyMapper
-    from dune.perftool.tools import get_pymbolic_basename
+    from dune.codegen.tools import get_pymbolic_basename
     deps = Or(tuple(Writes(get_pymbolic_basename(e)) for e in DependencyMapper()(expr)))
 
     # Issue an instruction in the quadrature loop that fills the buffer
@@ -508,7 +508,7 @@ def generate_accumulation_instruction(expr, visitor):
 
     # Add a sum factorization kernel that implements the multiplication
     # with the test function (stage 3)
-    from dune.perftool.sumfact.realization import realize_sum_factorization_kernel
+    from dune.codegen.sumfact.realization import realize_sum_factorization_kernel
     result, insn_dep = realize_sum_factorization_kernel(vsf.copy(insn_dep=vsf.insn_dep.union(insn_dep)))
 
     if not get_form_option("fastdg"):
diff --git a/python/dune/perftool/sumfact/autotune.py b/python/dune/codegen/sumfact/autotune.py
similarity index 83%
rename from python/dune/perftool/sumfact/autotune.py
rename to python/dune/codegen/sumfact/autotune.py
index 244873c24b0b64cd61f8b04a6c66500599b15670..48b281d1689f2eaff0866438d41a96999170fa2d 100644
--- a/python/dune/perftool/sumfact/autotune.py
+++ b/python/dune/codegen/sumfact/autotune.py
@@ -1,10 +1,10 @@
 """ Autotuning for sum factorization kernels """
 
-from dune.perftool.generation import cache_restoring, delete_cache_items
-from dune.perftool.loopy.target import DuneTarget
-from dune.perftool.sumfact.realization import realize_sumfact_kernel_function
-from dune.perftool.options import get_option, set_option
-from dune.perftool.error import PerftoolAutotuneError
+from dune.codegen.generation import cache_restoring, delete_cache_items
+from dune.codegen.loopy.target import DuneTarget
+from dune.codegen.sumfact.realization import realize_sumfact_kernel_function
+from dune.codegen.options import get_option, set_option
+from dune.codegen.error import CodegenAutotuneError
 
 import loopy as lp
 from pytools import product
@@ -22,11 +22,11 @@ def get_cmake_cache_entry(entry):
             return match.groups()[0]
 
 
-def get_perftool_dir():
-    if get_cmake_cache_entry("CMAKE_PROJECT_NAME") == "dune-perftool":
+def get_dune_codegen_dir():
+    if get_cmake_cache_entry("CMAKE_PROJECT_NAME") == "dune-codegen":
         return get_option("project_basedir")
     else:
-        return get_cmake_cache_entry("dune-perftool_DIR")
+        return get_cmake_cache_entry("dune-codegen_DIR")
 
 
 def compiler_invocation(name, filename):
@@ -39,7 +39,7 @@ def compiler_invocation(name, filename):
     compile_flags = [compiler]
 
     # Parse compiler flags
-    for line in open(os.path.join(get_perftool_dir(), "python", "CMakeFiles", "_autotune_target.dir", "flags.make"), "r"):
+    for line in open(os.path.join(get_dune_codegen_dir(), "python", "CMakeFiles", "_autotune_target.dir", "flags.make"), "r"):
         match = re.match("([^=]*)=(.*)", line)
         if match:
             compile_flags.extend(match.groups()[1].split())
@@ -48,14 +48,14 @@ def compiler_invocation(name, filename):
     compile_flags.append(filename)
 
     # Parse linker flags
-    for line in open(os.path.join(get_perftool_dir(), "python", "CMakeFiles", "_autotune_target.dir", "link.txt"), "r"):
+    for line in open(os.path.join(get_dune_codegen_dir(), "python", "CMakeFiles", "_autotune_target.dir", "link.txt"), "r"):
         match = re.match(".*_autotune_target (.*)", line)
         if match:
             for flag in match.groups()[0].split():
                 if flag.startswith("-") or os.path.isabs(flag):
                     compile_flags.append(flag)
                 else:
-                    compile_flags.append(os.path.join(get_perftool_dir(), "python", flag))
+                    compile_flags.append(os.path.join(get_dune_codegen_dir(), "python", flag))
 
     # Set an output name
     compile_flags.append("-o")
@@ -70,10 +70,10 @@ def generate_standalone_code(sf, filename):
     with open(filename, "w") as f:
         f.writelines(["#include \"config.h\"\n",
                       "#include<dune/pdelab/finiteelementmap/qkdg.hh>\n",
-                      "#include<dune/perftool/common/tsc.hh>\n",
-                      "#include<dune/perftool/common/vectorclass.hh>\n",
-                      "#include<dune/perftool/sumfact/onedquadrature.hh>\n",
-                      "#include<dune/perftool/sumfact/horizontaladd.hh>\n",
+                      "#include<dune/codegen/common/tsc.hh>\n",
+                      "#include<dune/codegen/common/vectorclass.hh>\n",
+                      "#include<dune/codegen/sumfact/onedquadrature.hh>\n",
+                      "#include<dune/codegen/sumfact/horizontaladd.hh>\n",
                       "#include<random>\n",
                       "#include<fstream>\n",
                       "#include<iostream>\n",
@@ -87,18 +87,18 @@ def generate_standalone_code(sf, filename):
         # Setup a polynomial object (normally done in the LocalOperator members)
         opcounting = get_option("opcounter")
         set_option("opcounter", False)
-        from dune.perftool.loopy.target import type_floatingpoint
+        from dune.codegen.loopy.target import type_floatingpoint
         real = type_floatingpoint()
         f.write("  using RF = {};\n".format(real))
         f.write("  using DF = {};\n".format(real))
 
-        from dune.perftool.sumfact.tabulation import name_polynomials
+        from dune.codegen.sumfact.tabulation import name_polynomials
         degs = tuple(m.basis_size - 1 for m in sf.matrix_sequence)
         for deg in set(degs):
             f.write("  Dune::QkStuff::EquidistantLagrangePolynomials<DF, RF, {}> {};\n".format(deg, name_polynomials(deg)))
 
         # Get kernels
-        from dune.perftool.pdelab.localoperator import extract_kernel_from_cache
+        from dune.codegen.pdelab.localoperator import extract_kernel_from_cache
         knl = realize_sumfact_kernel_function(sf)
         constructor_knl = extract_kernel_from_cache("operator", "constructor_kernel", None, wrap_in_cgen=False, add_timings=False)
         constructor_knl = constructor_knl.copy(target=DuneTarget(declare_temporaries=False))
@@ -205,7 +205,7 @@ def autotune_realization(sf):
 
                 ret = subprocess.call(compiler_invocation(name, filename))
                 if ret != 0:
-                    raise PerftoolAutotuneError("Compilation of autotune executable failed. Invocation: {}".format(" ".join(compiler_invocation(name, filename))))
+                    raise CodegenAutotuneError("Compilation of autotune executable failed. Invocation: {}".format(" ".join(compiler_invocation(name, filename))))
 
                 # Check whether the user specified an execution wrapper
                 call = []
@@ -219,7 +219,7 @@ def autotune_realization(sf):
                 devnull = open(os.devnull, 'w')
                 ret = subprocess.call(call, stdout=devnull, stderr=subprocess.STDOUT)
                 if ret != 0:
-                    raise PerftoolAutotuneError("Execution of autotune benchmark failed. Invocation: {}".format(" ".join(call)))
+                    raise CodegenAutotuneError("Execution of autotune benchmark failed. Invocation: {}".format(" ".join(call)))
 
             # Extract the result form the log file
             return float(next(iter(open(logname, "r")))) / 1000000
diff --git a/python/dune/perftool/sumfact/basis.py b/python/dune/codegen/sumfact/basis.py
similarity index 81%
rename from python/dune/perftool/sumfact/basis.py
rename to python/dune/codegen/sumfact/basis.py
index d846024d54e9f6b62785862803ab4e03498ac6ac..ce29589a1e3a8d7739519341578813fd0946603e 100644
--- a/python/dune/perftool/sumfact/basis.py
+++ b/python/dune/codegen/sumfact/basis.py
@@ -5,41 +5,41 @@ multiplication with the test function is part of the sum factorization kernel.
 """
 import itertools
 
-from dune.perftool.generation import (backend,
-                                      domain,
-                                      get_counted_variable,
-                                      get_counter,
-                                      get_global_context_value,
-                                      globalarg,
-                                      iname,
-                                      instruction,
-                                      kernel_cached,
-                                      temporary_variable,
-                                      )
-from dune.perftool.loopy.target import type_floatingpoint
-from dune.perftool.sumfact.tabulation import (basis_functions_per_direction,
-                                              construct_basis_matrix_sequence,
-                                              BasisTabulationMatrix,
-                                              PolynomialLookup,
-                                              name_polynomials,
-                                              polynomial_degree,
-                                              )
-from dune.perftool.sumfact.quadrature import quadrature_inames
-from dune.perftool.sumfact.switch import (get_facedir,
-                                          get_facemod,
+from dune.codegen.generation import (backend,
+                                     domain,
+                                     get_counted_variable,
+                                     get_counter,
+                                     get_global_context_value,
+                                     globalarg,
+                                     iname,
+                                     instruction,
+                                     kernel_cached,
+                                     temporary_variable,
+                                     )
+from dune.codegen.loopy.target import type_floatingpoint
+from dune.codegen.sumfact.tabulation import (basis_functions_per_direction,
+                                             construct_basis_matrix_sequence,
+                                             BasisTabulationMatrix,
+                                             PolynomialLookup,
+                                             name_polynomials,
+                                             polynomial_degree,
+                                             )
+from dune.codegen.sumfact.quadrature import quadrature_inames
+from dune.codegen.sumfact.switch import (get_facedir,
+                                         get_facemod,
+                                         )
+from dune.codegen.pdelab.argument import name_coefficientcontainer
+from dune.codegen.pdelab.geometry import (local_dimension,
+                                          world_dimension,
                                           )
-from dune.perftool.pdelab.argument import name_coefficientcontainer
-from dune.perftool.pdelab.geometry import (local_dimension,
-                                           world_dimension,
-                                           )
-from dune.perftool.sumfact.symbolic import SumfactKernel, SumfactKernelInterfaceBase
-from dune.perftool.options import get_form_option
-from dune.perftool.pdelab.driver import FEM_name_mangling
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.pdelab.spaces import name_lfs, name_lfs_bound, name_leaf_lfs
-from dune.perftool.tools import maybe_wrap_subscript
-from dune.perftool.pdelab.basis import shape_as_pymbolic
-from dune.perftool.sumfact.accumulation import sumfact_iname
+from dune.codegen.sumfact.symbolic import SumfactKernel, SumfactKernelInterfaceBase
+from dune.codegen.options import get_form_option
+from dune.codegen.pdelab.driver import FEM_name_mangling
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.pdelab.spaces import name_lfs, name_lfs_bound, name_leaf_lfs
+from dune.codegen.tools import maybe_wrap_subscript
+from dune.codegen.pdelab.basis import shape_as_pymbolic
+from dune.codegen.sumfact.accumulation import sumfact_iname
 
 from ufl import MixedElement, VectorElement, TensorElement, TensorProductElement
 
@@ -82,11 +82,11 @@ class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord):
         lfs = name_lfs(self.element, self.restriction, self.element_index)
         basisiname = sumfact_iname(name_lfs_bound(lfs), "basis")
         container = self.coeff_func(self.restriction)
-        from dune.perftool.pdelab.argument import pymbolic_coefficient as pc
+        from dune.codegen.pdelab.argument import pymbolic_coefficient as pc
         coeff = pc(container, lfs, basisiname)
 
         # Get the input temporary!
-        from dune.perftool.sumfact.realization import name_buffer_storage
+        from dune.codegen.sumfact.realization import name_buffer_storage
         name = "input_{}".format(sf.buffer)
         temporary_variable(name,
                            shape=(product(mat.basis_size for mat in sf.permuted_matrix_sequence), sf.vector_width),
@@ -107,7 +107,7 @@ class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord):
     def realize_direct(self, shape, inames, which=0):
         arg = "fastdg{}".format(which)
 
-        from dune.perftool.sumfact.accumulation import _dof_offset
+        from dune.codegen.sumfact.accumulation import _dof_offset
         globalarg(arg,
                   shape=shape,
                   dim_tags=",".join("f" * len(shape)),
@@ -140,7 +140,7 @@ class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord):
 
     @property
     def fastdg_interface_object_size(self):
-        from dune.perftool.sumfact.accumulation import _local_sizes
+        from dune.codegen.sumfact.accumulation import _local_sizes
         return sum(_local_sizes(self.element))
 
 
@@ -192,7 +192,7 @@ def pymbolic_coefficient_gradient(element, restriction, index, coeff_func, visit
                        interface=inp,
                        )
 
-    from dune.perftool.sumfact.vectorization import attach_vectorization_info
+    from dune.codegen.sumfact.vectorization import attach_vectorization_info
     vsf = attach_vectorization_info(sf)
 
     # If this sum factorization kernel was not used in the dry run we
@@ -201,7 +201,7 @@ def pymbolic_coefficient_gradient(element, restriction, index, coeff_func, visit
         visitor.indices = None
         return 0
 
-    from dune.perftool.sumfact.realization import realize_sum_factorization_kernel
+    from dune.codegen.sumfact.realization import realize_sum_factorization_kernel
     var, insn_dep = realize_sum_factorization_kernel(vsf)
 
     visitor.indices = None
@@ -234,7 +234,7 @@ def pymbolic_coefficient(element, restriction, index, coeff_func, visitor):
                        position_priority=3,
                        )
 
-    from dune.perftool.sumfact.vectorization import attach_vectorization_info
+    from dune.codegen.sumfact.vectorization import attach_vectorization_info
     vsf = attach_vectorization_info(sf)
 
     # If this sum factorization kernel was not used in the dry run we
@@ -245,7 +245,7 @@ def pymbolic_coefficient(element, restriction, index, coeff_func, visitor):
 
     # Add a sum factorization kernel that implements the evaluation of
     # the basis functions at quadrature points (stage 1)
-    from dune.perftool.sumfact.realization import realize_sum_factorization_kernel
+    from dune.codegen.sumfact.realization import realize_sum_factorization_kernel
     var, _ = realize_sum_factorization_kernel(vsf)
 
     visitor.indices = None
@@ -255,7 +255,7 @@ def pymbolic_coefficient(element, restriction, index, coeff_func, visitor):
 @iname
 def sumfact_lfs_iname(element, bound, dim):
     assert(isinstance(bound, int))
-    from dune.perftool.pdelab.driver import FEM_name_mangling
+    from dune.codegen.pdelab.driver import FEM_name_mangling
     name = "sumfac_lfs_{}_{}".format(FEM_name_mangling(element), dim)
     domain(name, bound)
     return name
diff --git a/python/dune/perftool/sumfact/geometry.py b/python/dune/codegen/sumfact/geometry.py
similarity index 88%
rename from python/dune/perftool/sumfact/geometry.py
rename to python/dune/codegen/sumfact/geometry.py
index 8455f78bda074359c7668e2c4674f7886741aea9..3d7df5502709f064fbda325ead9212cf5e24bbb3 100644
--- a/python/dune/perftool/sumfact/geometry.py
+++ b/python/dune/codegen/sumfact/geometry.py
@@ -1,44 +1,44 @@
 """ Sum factorized geometry evaluations """
 
-from dune.perftool.generation import (backend,
-                                      class_member,
-                                      domain,
-                                      get_counted_variable,
-                                      iname,
-                                      include_file,
-                                      instruction,
-                                      kernel_cached,
-                                      preamble,
-                                      silenced_warning,
-                                      temporary_variable,
-                                      get_global_context_value,
-                                      globalarg,
-                                      valuearg,
-                                      )
-from dune.perftool.options import get_option
-from dune.perftool.pdelab.geometry import (local_dimension,
-                                           world_dimension,
-                                           name_cell_geometry,
-                                           name_geometry,
-                                           )
-from dune.perftool.pdelab.localoperator import (name_ansatz_gfs_constructor_param,
-                                                lop_template_ansatz_gfs,
-                                                lop_template_range_field,
-                                                )
-from dune.perftool.pdelab.restriction import restricted_name
-from dune.perftool.sumfact.accumulation import basis_sf_kernels
-from dune.perftool.sumfact.basis import construct_basis_matrix_sequence
-from dune.perftool.sumfact.quadrature import (additional_inames,
-                                              default_quadrature_inames)
-from dune.perftool.sumfact.realization import (name_buffer_storage,
-                                               realize_sum_factorization_kernel,
+from dune.codegen.generation import (backend,
+                                     class_member,
+                                     domain,
+                                     get_counted_variable,
+                                     iname,
+                                     include_file,
+                                     instruction,
+                                     kernel_cached,
+                                     preamble,
+                                     silenced_warning,
+                                     temporary_variable,
+                                     get_global_context_value,
+                                     globalarg,
+                                     valuearg,
+                                     )
+from dune.codegen.options import get_option
+from dune.codegen.pdelab.geometry import (local_dimension,
+                                          world_dimension,
+                                          name_cell_geometry,
+                                          name_geometry,
+                                          )
+from dune.codegen.pdelab.localoperator import (name_ansatz_gfs_constructor_param,
+                                               lop_template_ansatz_gfs,
+                                               lop_template_range_field,
                                                )
-from dune.perftool.sumfact.switch import get_facedir, get_facemod
-from dune.perftool.sumfact.symbolic import SumfactKernelInterfaceBase, SumfactKernel
-from dune.perftool.sumfact.vectorization import attach_vectorization_info
-from dune.perftool.tools import get_pymbolic_basename
-from dune.perftool.options import get_form_option, option_switch
-from dune.perftool.ufl.modified_terminals import Restriction
+from dune.codegen.pdelab.restriction import restricted_name
+from dune.codegen.sumfact.accumulation import basis_sf_kernels
+from dune.codegen.sumfact.basis import construct_basis_matrix_sequence
+from dune.codegen.sumfact.quadrature import (additional_inames,
+                                             default_quadrature_inames)
+from dune.codegen.sumfact.realization import (name_buffer_storage,
+                                              realize_sum_factorization_kernel,
+                                              )
+from dune.codegen.sumfact.switch import get_facedir, get_facemod
+from dune.codegen.sumfact.symbolic import SumfactKernelInterfaceBase, SumfactKernel
+from dune.codegen.sumfact.vectorization import attach_vectorization_info
+from dune.codegen.tools import get_pymbolic_basename
+from dune.codegen.options import get_form_option, option_switch
+from dune.codegen.ufl.modified_terminals import Restriction
 
 from pytools import ImmutableRecord
 
@@ -178,14 +178,14 @@ def define_corner(name, low):
 
 @class_member(classtag="operator")
 def define_mesh_width(name):
-    from dune.perftool.pdelab.localoperator import lop_template_range_field
+    from dune.codegen.pdelab.localoperator import lop_template_range_field
     rft = lop_template_range_field()
     define_mesh_width_eval(name)
     return "Dune::FieldVector<{}, {}> {};".format(rft, world_dimension(), name)
 
 
 def define_mesh_width_eval(name):
-    from dune.perftool.pdelab.localoperator import name_ansatz_gfs_constructor_param
+    from dune.codegen.pdelab.localoperator import name_ansatz_gfs_constructor_param
     gfs = name_ansatz_gfs_constructor_param()
     code = ["{",
             "  auto e = *({}.gridView().template begin<0>());".format(gfs),
@@ -217,11 +217,11 @@ def pymbolic_spatial_coordinate_axiparallel(do_predicates, visitor):
     index, = visitor.indices
 
     # Urgh: *SOMEHOW* construct a face direction
-    from dune.perftool.pdelab.restriction import Restriction
+    from dune.codegen.pdelab.restriction import Restriction
     restriction = Restriction.NONE
     if get_global_context_value("integral_type") == "interior_facet":
         restriction = Restriction.POSITIVE
-    from dune.perftool.sumfact.switch import get_facedir
+    from dune.codegen.sumfact.switch import get_facedir
     face = get_facedir(restriction)
 
     lowcorner = name_lowerleft_corner()
@@ -239,7 +239,7 @@ def pymbolic_spatial_coordinate_axiparallel(do_predicates, visitor):
         iindex = index
         if face is not None and index > face:
             iindex = iindex - 1
-        from dune.perftool.sumfact.quadrature import pymbolic_indexed_quadrature_position
+        from dune.codegen.sumfact.quadrature import pymbolic_indexed_quadrature_position
         x = pymbolic_indexed_quadrature_position(iindex, visitor)
 
     visitor.indices = None
@@ -332,7 +332,7 @@ def pymbolic_unit_outer_normal(visitor):
         visitor.indices = None
 
         # Use facemod_s and facedir_s
-        from dune.perftool.sumfact.switch import get_facedir, get_facemod
+        from dune.codegen.sumfact.switch import get_facedir, get_facemod
         if index == get_facedir(Restriction.POSITIVE):
             if get_facemod(Restriction.POSITIVE):
                 return 1
@@ -500,7 +500,7 @@ def pymbolic_facet_area(visitor):
     if get_form_option("constant_transformation_matrix"):
         return pymbolic_facet_jacobian_determinant(visitor)
     else:
-        from dune.perftool.pdelab.geometry import pymbolic_facet_area as nonconstant_facet_area
+        from dune.codegen.pdelab.geometry import pymbolic_facet_area as nonconstant_facet_area
         return nonconstant_facet_area()
 
 
@@ -581,7 +581,7 @@ def define_jacobian_inverse(name, restriction, visitor):
     temporary_variable(name_detjac, shape=())
     ftags = ",".join(["f"] * 2)
     temporary_variable(name, shape=(dim, dim), dim_tags=ftags, managed=True)
-    include_file('dune/perftool/sumfact/invertgeometry.hh', filetag='operatorfile')
+    include_file('dune/codegen/sumfact/invertgeometry.hh', filetag='operatorfile')
     code = "{} = invert_and_return_determinant({}, {});".format(name_detjac,
                                                                 ", ".join(names_jacobian),
                                                                 name)
@@ -606,7 +606,7 @@ def pymbolic_jacobian_inverse(i, j, restriction, visitor):
     # branch, otherwise we want to go into the sumfact implementation instead
     # of pdelab.
     if get_form_option("constant_transformation_matrix"):
-        from dune.perftool.pdelab.geometry import name_constant_jacobian_inverse_transposed
+        from dune.codegen.pdelab.geometry import name_constant_jacobian_inverse_transposed
         name = name_constant_jacobian_inverse_transposed(restriction)
         # Return jacobian inverse -> (j, i) instead of (i, j)
         return prim.Subscript(prim.Variable(name), (j, i))
@@ -622,7 +622,7 @@ def name_jacobian_determinant(visitor):
 
 def pymbolic_jacobian_determinant(visitor):
     if get_form_option("constant_transformation_matrix"):
-        from dune.perftool.pdelab.geometry import pymbolic_jacobian_determinant
+        from dune.codegen.pdelab.geometry import pymbolic_jacobian_determinant
         return pymbolic_jacobian_determinant()
     else:
         # The calculation of the jacobian determinant happens in this function
diff --git a/python/dune/perftool/sumfact/permutation.py b/python/dune/codegen/sumfact/permutation.py
similarity index 97%
rename from python/dune/perftool/sumfact/permutation.py
rename to python/dune/codegen/sumfact/permutation.py
index 211bf22a3d3d586991381a3862af149e61a1de56..79b758fcae2252d879cb28e2ca3c87de10019a1d 100644
--- a/python/dune/perftool/sumfact/permutation.py
+++ b/python/dune/codegen/sumfact/permutation.py
@@ -2,8 +2,8 @@
 
 import itertools
 
-from dune.perftool.options import get_option
-from dune.perftool.sumfact.switch import get_facedir, get_facemod
+from dune.codegen.options import get_option
+from dune.codegen.sumfact.switch import get_facedir, get_facemod
 
 
 def sumfact_permutation_heuristic(permutations, stage):
diff --git a/python/dune/perftool/sumfact/quadrature.py b/python/dune/codegen/sumfact/quadrature.py
similarity index 84%
rename from python/dune/perftool/sumfact/quadrature.py
rename to python/dune/codegen/sumfact/quadrature.py
index 398e793d49d5beb98d35e14a859936e15f03332c..3453d94cdeb1b52be343bad736b8a139cffe9183 100644
--- a/python/dune/perftool/sumfact/quadrature.py
+++ b/python/dune/codegen/sumfact/quadrature.py
@@ -1,28 +1,28 @@
-from dune.perftool.generation import (backend,
-                                      domain,
-                                      function_mangler,
-                                      get_global_context_value,
-                                      globalarg,
-                                      iname,
-                                      instruction,
-                                      kernel_cached,
-                                      loopy_class_member,
-                                      preamble,
-                                      temporary_variable,
-                                      )
-from dune.perftool.sumfact.switch import get_facedir
-from dune.perftool.sumfact.tabulation import (quadrature_points_per_direction,
-                                              local_quadrature_points_per_direction,
-                                              name_oned_quadrature_points,
-                                              name_oned_quadrature_weights,
-                                              )
-from dune.perftool.pdelab.argument import name_accumulation_variable
-from dune.perftool.pdelab.geometry import (local_dimension,
-                                           world_dimension,
-                                           )
-from dune.perftool.options import get_form_option
-from dune.perftool.sumfact.switch import get_facedir
-from dune.perftool.loopy.target import dtype_floatingpoint
+from dune.codegen.generation import (backend,
+                                     domain,
+                                     function_mangler,
+                                     get_global_context_value,
+                                     globalarg,
+                                     iname,
+                                     instruction,
+                                     kernel_cached,
+                                     loopy_class_member,
+                                     preamble,
+                                     temporary_variable,
+                                     )
+from dune.codegen.sumfact.switch import get_facedir
+from dune.codegen.sumfact.tabulation import (quadrature_points_per_direction,
+                                             local_quadrature_points_per_direction,
+                                             name_oned_quadrature_points,
+                                             name_oned_quadrature_weights,
+                                             )
+from dune.codegen.pdelab.argument import name_accumulation_variable
+from dune.codegen.pdelab.geometry import (local_dimension,
+                                          world_dimension,
+                                          )
+from dune.codegen.options import get_form_option
+from dune.codegen.sumfact.switch import get_facedir
+from dune.codegen.loopy.target import dtype_floatingpoint
 
 from loopy import CallMangleInfo
 from loopy.symbolic import FunctionIdentifier
@@ -82,7 +82,7 @@ def quadrature_inames(element):
     else:
         from ufl import FiniteElement, TensorProductElement
         assert isinstance(element, (FiniteElement, TensorProductElement))
-        from dune.perftool.pdelab.driver import FEM_name_mangling
+        from dune.codegen.pdelab.driver import FEM_name_mangling
         names = tuple("quad_{}_{}".format(FEM_name_mangling(element), d) for d in range(local_dimension()))
 
     local_qps_per_dir = local_quadrature_points_per_direction()
@@ -262,11 +262,11 @@ def additional_inames(visitor):
         element = info.element
 
     if element is not None:
-        from dune.perftool.pdelab.restriction import Restriction
+        from dune.codegen.pdelab.restriction import Restriction
         restriction = Restriction.NONE
         if get_global_context_value("integral_type") == "interior_facet":
             restriction = Restriction.POSITIVE
-        from dune.perftool.sumfact.basis import lfs_inames
+        from dune.codegen.sumfact.basis import lfs_inames
         lfs_inames = lfs_inames(element, restriction)
         return lfs_inames
     else:
diff --git a/python/dune/perftool/sumfact/realization.py b/python/dune/codegen/sumfact/realization.py
similarity index 85%
rename from python/dune/perftool/sumfact/realization.py
rename to python/dune/codegen/sumfact/realization.py
index 12f7115662533b6f279e6e340130de95b64992d9..d00f2a01681ecfe14f171ef74bca08e667c67112 100644
--- a/python/dune/perftool/sumfact/realization.py
+++ b/python/dune/codegen/sumfact/realization.py
@@ -2,41 +2,41 @@
 The code that triggers the creation of the necessary code constructs
 to realize a sum factorization kernel
 """
-from dune.perftool.generation import (barrier,
-                                      delete_cache_items,
-                                      dump_accumulate_timer,
-                                      generator_factory,
-                                      get_global_context_value,
-                                      globalarg,
-                                      instruction,
-                                      kernel_cached,
-                                      post_include,
-                                      preamble,
-                                      silenced_warning,
-                                      temporary_variable,
-                                      transform,
-                                      )
-from dune.perftool.loopy.flatten import flatten_index
-from dune.perftool.pdelab.argument import pymbolic_coefficient
-from dune.perftool.pdelab.basis import shape_as_pymbolic
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.options import (get_form_option,
-                                   get_option,
-                                   )
-from dune.perftool.pdelab.signatures import assembler_routine_name
-from dune.perftool.sumfact.permutation import (sumfact_permutation_strategy,
-                                               permute_backward,
-                                               permute_forward,
-                                               )
-from dune.perftool.sumfact.quadrature import quadrature_points_per_direction
-from dune.perftool.sumfact.symbolic import (SumfactKernel,
-                                            VectorizedSumfactKernel,
-                                            )
-from dune.perftool.sumfact.vectorization import attach_vectorization_info
-from dune.perftool.sumfact.accumulation import sumfact_iname
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.loopy.vcl import ExplicitVCLCast
-from dune.perftool.tools import get_leaf, remove_duplicates
+from dune.codegen.generation import (barrier,
+                                     delete_cache_items,
+                                     dump_accumulate_timer,
+                                     generator_factory,
+                                     get_global_context_value,
+                                     globalarg,
+                                     instruction,
+                                     kernel_cached,
+                                     post_include,
+                                     preamble,
+                                     silenced_warning,
+                                     temporary_variable,
+                                     transform,
+                                     )
+from dune.codegen.loopy.flatten import flatten_index
+from dune.codegen.pdelab.argument import pymbolic_coefficient
+from dune.codegen.pdelab.basis import shape_as_pymbolic
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.options import (get_form_option,
+                                  get_option,
+                                  )
+from dune.codegen.pdelab.signatures import assembler_routine_name
+from dune.codegen.sumfact.permutation import (sumfact_permutation_strategy,
+                                              permute_backward,
+                                              permute_forward,
+                                              )
+from dune.codegen.sumfact.quadrature import quadrature_points_per_direction
+from dune.codegen.sumfact.symbolic import (SumfactKernel,
+                                           VectorizedSumfactKernel,
+                                           )
+from dune.codegen.sumfact.vectorization import attach_vectorization_info
+from dune.codegen.sumfact.accumulation import sumfact_iname
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.loopy.vcl import ExplicitVCLCast
+from dune.codegen.tools import get_leaf, remove_duplicates
 
 from pytools import product
 from ufl import MixedElement
@@ -294,7 +294,7 @@ def realize_sumfact_kernel_function(sf):
                                   })
 
     # Construct a loopy kernel object
-    from dune.perftool.pdelab.localoperator import extract_kernel_from_cache
+    from dune.codegen.pdelab.localoperator import extract_kernel_from_cache
     args = ("const char* buffer0", "const char* buffer1") + sf.interface.signature_args
     signature = "void {}({}) const __attribute__((always_inline))".format(sf.function_name, ", ".join(args))
     kernel = extract_kernel_from_cache("kernel_default", sf.function_name, [signature], add_timings=False)
diff --git a/python/dune/perftool/sumfact/switch.py b/python/dune/codegen/sumfact/switch.py
similarity index 89%
rename from python/dune/perftool/sumfact/switch.py
rename to python/dune/codegen/sumfact/switch.py
index 8a44d50923226b7971c46389d245760e587fde89..09c85af539b27c1e9eead6d95dc886f3a2824082 100644
--- a/python/dune/perftool/sumfact/switch.py
+++ b/python/dune/codegen/sumfact/switch.py
@@ -2,18 +2,18 @@
 
 import csv
 
-from dune.perftool.generation import (backend,
-                                      get_global_context_value,
-                                      global_context,
-                                      )
-from dune.perftool.pdelab.geometry import world_dimension
-from dune.perftool.pdelab.localoperator import generate_kernel
-from dune.perftool.pdelab.signatures import (assembly_routine_args,
-                                             assembly_routine_signature,
-                                             kernel_name,
-                                             )
-from dune.perftool.options import get_form_option, get_option
-from dune.perftool.cgen.clazz import ClassMember
+from dune.codegen.generation import (backend,
+                                     get_global_context_value,
+                                     global_context,
+                                     )
+from dune.codegen.pdelab.geometry import world_dimension
+from dune.codegen.pdelab.localoperator import generate_kernel
+from dune.codegen.pdelab.signatures import (assembly_routine_args,
+                                            assembly_routine_signature,
+                                            kernel_name,
+                                            )
+from dune.codegen.options import get_form_option, get_option
+from dune.codegen.cgen.clazz import ClassMember
 
 
 @backend(interface="generate_kernels_per_integral", name="sumfact")
@@ -155,7 +155,7 @@ def generate_interior_facet_switch():
 
 
 def get_facedir(restriction):
-    from dune.perftool.pdelab.restriction import Restriction
+    from dune.codegen.pdelab.restriction import Restriction
     if restriction == Restriction.POSITIVE or get_global_context_value("integral_type") == "exterior_facet":
         return get_global_context_value("facedir_s")
     if restriction == Restriction.NEGATIVE:
@@ -166,7 +166,7 @@ def get_facedir(restriction):
 
 
 def get_facemod(restriction):
-    from dune.perftool.pdelab.restriction import Restriction
+    from dune.codegen.pdelab.restriction import Restriction
     if restriction == Restriction.POSITIVE or get_global_context_value("integral_type") == "exterior_facet":
         return get_global_context_value("facemod_s")
     if restriction == Restriction.NEGATIVE:
diff --git a/python/dune/perftool/sumfact/symbolic.py b/python/dune/codegen/sumfact/symbolic.py
similarity index 96%
rename from python/dune/perftool/sumfact/symbolic.py
rename to python/dune/codegen/sumfact/symbolic.py
index f1ef75074baa956e7a8fd3cb354b233495899501..24f924555b0573d895ed7f574aa6d744de44f6f3 100644
--- a/python/dune/perftool/sumfact/symbolic.py
+++ b/python/dune/codegen/sumfact/symbolic.py
@@ -1,17 +1,17 @@
 """ A pymbolic node representing a sum factorization kernel """
 
-from dune.perftool.options import get_form_option, get_option
-from dune.perftool.generation import (get_counted_variable,
-                                      subst_rule,
-                                      transform,
-                                      )
-from dune.perftool.pdelab.geometry import local_dimension, world_dimension
-from dune.perftool.sumfact.permutation import permute_forward, sumfact_quadrature_permutation_strategy
-from dune.perftool.sumfact.quadrature import quadrature_inames
-from dune.perftool.sumfact.tabulation import BasisTabulationMatrixBase, BasisTabulationMatrixArray
-from dune.perftool.loopy.target import dtype_floatingpoint, type_floatingpoint
-from dune.perftool.loopy.vcl import ExplicitVCLCast, VCLLowerUpperLoad
-from dune.perftool.tools import get_leaf, maybe_wrap_subscript, remove_duplicates
+from dune.codegen.options import get_form_option, get_option
+from dune.codegen.generation import (get_counted_variable,
+                                     subst_rule,
+                                     transform,
+                                     )
+from dune.codegen.pdelab.geometry import local_dimension, world_dimension
+from dune.codegen.sumfact.permutation import permute_forward, sumfact_quadrature_permutation_strategy
+from dune.codegen.sumfact.quadrature import quadrature_inames
+from dune.codegen.sumfact.tabulation import BasisTabulationMatrixBase, BasisTabulationMatrixArray
+from dune.codegen.loopy.target import dtype_floatingpoint, type_floatingpoint
+from dune.codegen.loopy.vcl import ExplicitVCLCast, VCLLowerUpperLoad
+from dune.codegen.tools import get_leaf, maybe_wrap_subscript, remove_duplicates
 
 from pytools import ImmutableRecord, product
 
@@ -160,7 +160,7 @@ class VectorSumfactKernelOutput(SumfactKernelInterfaceBase):
 
         trial_element, = set(o.trial_element for o in self.interfaces)
         trial_element_index = set(o.trial_element_index for o in self.interfaces).pop()
-        from dune.perftool.sumfact.accumulation import accum_iname
+        from dune.codegen.sumfact.accumulation import accum_iname
         element = get_leaf(trial_element, trial_element_index) if trial_element is not None else None
         inames = tuple(accum_iname(element, mat.rows, i)
                        for i, mat in enumerate(sf.permuted_matrix_sequence))
@@ -576,7 +576,7 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable):
     def operations(self):
         """ The total number of floating point operations for the kernel
         to be carried out """
-        from dune.perftool.sumfact.permutation import flop_cost
+        from dune.codegen.sumfact.permutation import flop_cost
         return flop_cost(self.permuted_matrix_sequence)
 
 
@@ -881,5 +881,5 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable)
     def operations(self):
         """ The total number of floating point operations for the kernel
         to be carried out """
-        from dune.perftool.sumfact.permutation import flop_cost
+        from dune.codegen.sumfact.permutation import flop_cost
         return flop_cost(self.matrix_sequence)
diff --git a/python/dune/perftool/sumfact/tabulation.py b/python/dune/codegen/sumfact/tabulation.py
similarity index 89%
rename from python/dune/perftool/sumfact/tabulation.py
rename to python/dune/codegen/sumfact/tabulation.py
index ef1c23da8c93d8db09fce419242892de68151d4f..d5a44a8989de68f62770a7ff18165afe21d42dcd 100644
--- a/python/dune/perftool/sumfact/tabulation.py
+++ b/python/dune/codegen/sumfact/tabulation.py
@@ -1,31 +1,31 @@
-from dune.perftool.ufl.modified_terminals import Restriction
-
-from dune.perftool.pdelab.argument import name_coefficientcontainer
-from dune.perftool.pdelab.geometry import world_dimension, local_dimension
-from dune.perftool.generation import (class_member,
-                                      domain,
-                                      function_mangler,
-                                      generator_factory,
-                                      get_global_context_value,
-                                      iname,
-                                      include_file,
-                                      initializer_list,
-                                      instruction,
-                                      loopy_class_member,
-                                      preamble,
-                                      silenced_warning,
-                                      temporary_variable,
-                                      transform,
-                                      valuearg
-                                      )
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.loopy.vcl import ExplicitVCLCast, get_vcl_type_size
-from dune.perftool.options import get_option
-from dune.perftool.pdelab.localoperator import (name_domain_field,
-                                                lop_template_range_field,
-                                                )
-from dune.perftool.pdelab.quadrature import quadrature_order
-from dune.perftool.tools import maybe_wrap_subscript, ceildiv
+from dune.codegen.ufl.modified_terminals import Restriction
+
+from dune.codegen.pdelab.argument import name_coefficientcontainer
+from dune.codegen.pdelab.geometry import world_dimension, local_dimension
+from dune.codegen.generation import (class_member,
+                                     domain,
+                                     function_mangler,
+                                     generator_factory,
+                                     get_global_context_value,
+                                     iname,
+                                     include_file,
+                                     initializer_list,
+                                     instruction,
+                                     loopy_class_member,
+                                     preamble,
+                                     silenced_warning,
+                                     temporary_variable,
+                                     transform,
+                                     valuearg
+                                     )
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.loopy.vcl import ExplicitVCLCast, get_vcl_type_size
+from dune.codegen.options import get_option
+from dune.codegen.pdelab.localoperator import (name_domain_field,
+                                               lop_template_range_field,
+                                               )
+from dune.codegen.pdelab.quadrature import quadrature_order
+from dune.codegen.tools import maybe_wrap_subscript, ceildiv
 from loopy import CallMangleInfo
 from loopy.symbolic import FunctionIdentifier
 from loopy.types import NumpyType
@@ -299,7 +299,7 @@ def local_quadrature_points_per_direction():
 def polynomial_degree():
     data = get_global_context_value("data")
     form = data.object_by_name[get_form_option("form")]
-    from dune.perftool.ufl.preprocess import preprocess_form
+    from dune.codegen.ufl.preprocess import preprocess_form
     form = preprocess_form(form).preprocessed_form
     degree = form.coefficients()[0].ufl_element().degree()
     if isinstance(degree, int):
@@ -376,7 +376,7 @@ def name_polynomials(degree):
 def sort_quadrature_points_weights(qp, qw, bound):
     range_field = lop_template_range_field()
     domain_field = name_domain_field()
-    include_file("dune/perftool/sumfact/onedquadrature.hh", filetag="operatorfile")
+    include_file("dune/codegen/sumfact/onedquadrature.hh", filetag="operatorfile")
     return frozenset({instruction(code="onedQuadraturePointsWeights<{}, {}, {}>({}, {});"
                                   .format(range_field, domain_field, bound, qp, qw),
                                   assignees=frozenset({qp, qw}),
diff --git a/python/dune/perftool/sumfact/vectorization.py b/python/dune/codegen/sumfact/vectorization.py
similarity index 92%
rename from python/dune/perftool/sumfact/vectorization.py
rename to python/dune/codegen/sumfact/vectorization.py
index 7d779eff11d82c4acf2fcd810223790537c8e7d6..2ac0ffb5a41eac1503a3a50b1809c971de330008 100644
--- a/python/dune/perftool/sumfact/vectorization.py
+++ b/python/dune/codegen/sumfact/vectorization.py
@@ -4,25 +4,25 @@ from __future__ import division
 
 import logging
 
-from dune.perftool.loopy.target import dtype_floatingpoint
-from dune.perftool.loopy.vcl import get_vcl_type_size
-from dune.perftool.loopy.symbolic import SumfactKernel, VectorizedSumfactKernel
-from dune.perftool.generation import (backend,
-                                      generator_factory,
-                                      get_backend,
-                                      get_counted_variable,
-                                      get_global_context_value,
-                                      kernel_cached,
-                                      )
-from dune.perftool.pdelab.restriction import (Restriction,
-                                              restricted_name,
-                                              )
-from dune.perftool.sumfact.tabulation import (quadrature_points_per_direction,
-                                              set_quadrature_points,
-                                              )
-from dune.perftool.error import PerftoolVectorizationError
-from dune.perftool.options import get_form_option, get_option, set_form_option
-from dune.perftool.tools import add_to_frozendict, round_to_multiple, list_diff
+from dune.codegen.loopy.target import dtype_floatingpoint
+from dune.codegen.loopy.vcl import get_vcl_type_size
+from dune.codegen.loopy.symbolic import SumfactKernel, VectorizedSumfactKernel
+from dune.codegen.generation import (backend,
+                                     generator_factory,
+                                     get_backend,
+                                     get_counted_variable,
+                                     get_global_context_value,
+                                     kernel_cached,
+                                     )
+from dune.codegen.pdelab.restriction import (Restriction,
+                                             restricted_name,
+                                             )
+from dune.codegen.sumfact.tabulation import (quadrature_points_per_direction,
+                                             set_quadrature_points,
+                                             )
+from dune.codegen.error import CodegenVectorizationError
+from dune.codegen.options import get_form_option, get_option, set_form_option
+from dune.codegen.tools import add_to_frozendict, round_to_multiple, list_diff
 
 from pymbolic.mapper.flop_counter import FlopCounter
 from pytools import product
@@ -37,9 +37,9 @@ import math
 def _cache_vectorization_info(old, new):
     if get_form_option("vectorization_not_fully_vectorized_error"):
         if not isinstance(new, VectorizedSumfactKernel):
-            raise PerftoolVectorizationError("Did not fully vectorize!")
+            raise CodegenVectorizationError("Did not fully vectorize!")
     if new is None:
-        raise PerftoolVectorizationError("Vectorization info for sum factorization kernel was not gathered correctly!")
+        raise CodegenVectorizationError("Vectorization info for sum factorization kernel was not gathered correctly!")
     return new
 
 
@@ -126,7 +126,7 @@ def strategy_cost(strat_tuple):
     elif s == "target":
         func = target_costfunction
     elif s == "autotune":
-        from dune.perftool.sumfact.autotune import autotune_realization
+        from dune.codegen.sumfact.autotune import autotune_realization
         func = autotune_realization
     else:
         raise NotImplementedError("Vectorization strategy '{}' unknown!".format(s))
@@ -242,7 +242,7 @@ def short_stringify_vectorization_strategy(strategy):
 
 def filter_active_inactive_sumfacts():
     # Retrieve all sum factorization kernels for stage 1 and 3
-    from dune.perftool.generation import retrieve_cache_items
+    from dune.codegen.generation import retrieve_cache_items
     all_sumfacts = [i for i in retrieve_cache_items("kernel_default and sumfactnodes")]
 
     # Stage 1 sum factorizations that were actually used
diff --git a/python/dune/perftool/sympy.py b/python/dune/codegen/sympy.py
similarity index 98%
rename from python/dune/perftool/sympy.py
rename to python/dune/codegen/sympy.py
index 4999ad8aa90f6e69c4f122db9c4772b7c7cb85f0..8165d749fb9bf191cd01f7edcc495f7c06076249 100644
--- a/python/dune/perftool/sympy.py
+++ b/python/dune/codegen/sympy.py
@@ -1,5 +1,5 @@
 from __future__ import absolute_import
-from dune.perftool.generation import get_global_context_value
+from dune.codegen.generation import get_global_context_value
 from pymbolic.interop.sympy import SympyToPymbolicMapper, PymbolicToSympyMapper
 from functools import partial
 
diff --git a/python/dune/perftool/tools.py b/python/dune/codegen/tools.py
similarity index 100%
rename from python/dune/perftool/tools.py
rename to python/dune/codegen/tools.py
diff --git a/python/dune/perftool/ufl/__init__.py b/python/dune/codegen/ufl/__init__.py
similarity index 100%
rename from python/dune/perftool/ufl/__init__.py
rename to python/dune/codegen/ufl/__init__.py
diff --git a/python/dune/perftool/ufl/execution.py b/python/dune/codegen/ufl/execution.py
similarity index 68%
rename from python/dune/perftool/ufl/execution.py
rename to python/dune/codegen/ufl/execution.py
index 30a5b915721d81147ded0fba9946dc0e2f23ae05..8b2fd632ad8f79ba91500a60e8424675530f9835 100644
--- a/python/dune/perftool/ufl/execution.py
+++ b/python/dune/codegen/ufl/execution.py
@@ -2,7 +2,7 @@
 So, this module contains all our extensions and monkey patches to
 UFL.
 """
-from dune.perftool.error import PerftoolUFLError
+from dune.codegen.error import CodegenUFLError
 
 import ufl
 
@@ -13,7 +13,7 @@ class TrialFunction(ufl.Coefficient):
     """ A coefficient that always takes the reserved index 0 """
     def __init__(self, element, count=None):
         if count is not None and count != 0:
-            raise PerftoolUFLError("The trial function must be the coefficient of index 0 in uflpdelab")
+            raise CodegenUFLError("The trial function must be the coefficient of index 0 in uflpdelab")
         ufl.Coefficient.__init__(self, element, count=0)
 
 
@@ -21,11 +21,11 @@ class Coefficient(ufl.Coefficient):
     """ A coefficient that honors the reserved index 0. """
     def __init__(self, element, count=None):
         if count == 0:
-            raise PerftoolUFLError("The coefficient of index 0 is reserved for the trial function in uflpdelab")
+            raise CodegenUFLError("The coefficient of index 0 is reserved for the trial function in uflpdelab")
         if count == 1:
-            raise PerftoolUFLError("The coefficient of index 1 is reserved for the jacobian apply vector in uflpdelab")
+            raise CodegenUFLError("The coefficient of index 1 is reserved for the jacobian apply vector in uflpdelab")
         if count == 2:
-            raise PerftoolUFLError("The coefficient of index 2 is reserved for the time variable in uflpdelab")
+            raise CodegenUFLError("The coefficient of index 2 is reserved for the time variable in uflpdelab")
         if count is None and ufl.Coefficient._globalcount < 3:
             count = 3
         ufl.Coefficient.__init__(self, element, count)
diff --git a/python/dune/perftool/ufl/flatoperators.py b/python/dune/codegen/ufl/flatoperators.py
similarity index 100%
rename from python/dune/perftool/ufl/flatoperators.py
rename to python/dune/codegen/ufl/flatoperators.py
diff --git a/python/dune/perftool/ufl/modified_terminals.py b/python/dune/codegen/ufl/modified_terminals.py
similarity index 100%
rename from python/dune/perftool/ufl/modified_terminals.py
rename to python/dune/codegen/ufl/modified_terminals.py
diff --git a/python/dune/perftool/ufl/preprocess.py b/python/dune/codegen/ufl/preprocess.py
similarity index 91%
rename from python/dune/perftool/ufl/preprocess.py
rename to python/dune/codegen/ufl/preprocess.py
index 175d0c00ddb57db3bfcf5a84aba62e7d2a997030..d81ee85cfda09e5c1957463dac0959ca9d747dbf 100644
--- a/python/dune/perftool/ufl/preprocess.py
+++ b/python/dune/codegen/ufl/preprocess.py
@@ -1,12 +1,12 @@
 """ Preprocessing algorithms for UFL forms """
 
-from dune.perftool.generation import run_hook, ReturnArg
+from dune.codegen.generation import run_hook, ReturnArg
 import ufl.classes as uc
 import ufl.algorithms.apply_function_pullbacks as afp
 import ufl.algorithms.apply_algebra_lowering as aal
 import ufl.algorithms.apply_derivatives as ad
 
-from dune.perftool.options import get_form_option
+from dune.codegen.options import get_form_option
 
 from pytools import memoize
 
@@ -57,8 +57,8 @@ def apply_default_transformations(form):
     # This is the list of transformations we unconditionally apply to
     # all forms we want to generate code for.
     #
-    from dune.perftool.ufl.transformations import transform_form
-    from dune.perftool.ufl.transformations.indexpushdown import pushdown_indexed
+    from dune.codegen.ufl.transformations import transform_form
+    from dune.codegen.ufl.transformations.indexpushdown import pushdown_indexed
 
     form = transform_form(form, pushdown_indexed)
 
diff --git a/python/dune/perftool/ufl/transformations/__init__.py b/python/dune/codegen/ufl/transformations/__init__.py
similarity index 98%
rename from python/dune/perftool/ufl/transformations/__init__.py
rename to python/dune/codegen/ufl/transformations/__init__.py
index de66173a2a04bf3d5f5b7873d8444d230e665ca0..1d4979997bff1d370abe69b266f827ea649cc548 100644
--- a/python/dune/perftool/ufl/transformations/__init__.py
+++ b/python/dune/codegen/ufl/transformations/__init__.py
@@ -19,7 +19,7 @@ class UFLTransformationWrapper(object):
             return
 
         # Write out a dot file
-        from dune.perftool.options import get_form_option
+        from dune.codegen.options import get_form_option
         if get_form_option("print_transformations"):
             import os
             dir = get_form_option("print_transformations_dir")
diff --git a/python/dune/perftool/ufl/transformations/blockpreconditioner.py b/python/dune/codegen/ufl/transformations/blockpreconditioner.py
similarity index 97%
rename from python/dune/perftool/ufl/transformations/blockpreconditioner.py
rename to python/dune/codegen/ufl/transformations/blockpreconditioner.py
index c16c11520ccef27a5cf23d22ba387846b434b4a0..c992af12e0cae3499f6f6694027610dfd53c535e 100644
--- a/python/dune/perftool/ufl/transformations/blockpreconditioner.py
+++ b/python/dune/codegen/ufl/transformations/blockpreconditioner.py
@@ -1,6 +1,6 @@
 """ Derive block preconditioners from residual forms """
 
-from dune.perftool.ufl.modified_terminals import Restriction
+from dune.codegen.ufl.modified_terminals import Restriction
 
 from ufl.algorithms import MultiFunction
 from ufl.algorithms.map_integrands import map_integrands
diff --git a/python/dune/perftool/ufl/transformations/indexpushdown.py b/python/dune/codegen/ufl/transformations/indexpushdown.py
similarity index 89%
rename from python/dune/perftool/ufl/transformations/indexpushdown.py
rename to python/dune/codegen/ufl/transformations/indexpushdown.py
index 73b8d73a670f66517060ac61338a683da275d90e..d33deb192e55d94a488d437394639fc9ec1ae85b 100644
--- a/python/dune/perftool/ufl/transformations/indexpushdown.py
+++ b/python/dune/codegen/ufl/transformations/indexpushdown.py
@@ -1,7 +1,7 @@
 from __future__ import absolute_import
 from ufl.algorithms import MultiFunction
-from dune.perftool.ufl.flatoperators import get_operands, construct_binary_operator
-from dune.perftool.ufl.transformations import ufl_transformation
+from dune.codegen.ufl.flatoperators import get_operands, construct_binary_operator
+from dune.codegen.ufl.transformations import ufl_transformation
 
 import ufl.classes as uc
 
diff --git a/python/dune/perftool/ufl/visitor.py b/python/dune/codegen/ufl/visitor.py
similarity index 94%
rename from python/dune/perftool/ufl/visitor.py
rename to python/dune/codegen/ufl/visitor.py
index 987d29d034caf1ce191960c8a1429bbf3c8e5ba4..996024cea6ec966cbb8f5463949c7bb84b2560b2 100644
--- a/python/dune/perftool/ufl/visitor.py
+++ b/python/dune/codegen/ufl/visitor.py
@@ -2,18 +2,18 @@
 This module defines the main visitor algorithm transforming ufl expressions
 to pymbolic and loopy.
 """
-from dune.perftool.error import PerftoolUFLError
-from dune.perftool.generation import (get_global_context_value,
-                                      domain,
-                                      globalarg,
-                                      valuearg,
-                                      )
-from dune.perftool.ufl.flatoperators import get_operands
-from dune.perftool.ufl.modified_terminals import (ModifiedTerminalTracker,
-                                                  Restriction,
-                                                  )
-from dune.perftool.tools import maybe_wrap_subscript
-from dune.perftool.options import get_form_option
+from dune.codegen.error import CodegenUFLError
+from dune.codegen.generation import (get_global_context_value,
+                                     domain,
+                                     globalarg,
+                                     valuearg,
+                                     )
+from dune.codegen.ufl.flatoperators import get_operands
+from dune.codegen.ufl.modified_terminals import (ModifiedTerminalTracker,
+                                                 Restriction,
+                                                 )
+from dune.codegen.tools import maybe_wrap_subscript
+from dune.codegen.options import get_form_option
 from loopy import Reduction
 
 from pymbolic.primitives import (Call,
@@ -61,7 +61,7 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker):
             expr = self._call(o, False)
             if expr != 0:
                 if get_form_option("simplify"):
-                    from dune.perftool.sympy import simplify_pymbolic_expression
+                    from dune.codegen.sympy import simplify_pymbolic_expression
                     expr = simplify_pymbolic_expression(expr)
                 self.interface.generate_accumulation_instruction(expr, self)
 
@@ -128,7 +128,7 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker):
             leaf_element = leaf_element.extract_component(index)[1]
 
         if self.grad:
-            raise PerftoolUFLError("Gradients should have been transformed to reference gradients!!!")
+            raise CodegenUFLError("Gradients should have been transformed to reference gradients!!!")
 
         if self.reference_grad:
             return self.interface.pymbolic_reference_gradient(leaf_element, restriction, o.number())
@@ -154,7 +154,7 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker):
                     self.indices = None
 
             if self.grad:
-                raise PerftoolUFLError("Gradients should have been transformed to reference gradients!!!")
+                raise CodegenUFLError("Gradients should have been transformed to reference gradients!!!")
 
             if self.reference_grad:
                 if o.count() == 0:
@@ -174,7 +174,7 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker):
             return prim.Call(prim.Variable("getTime"), ())
         else:
             if self.reference_grad:
-                raise PerftoolUFLError("Coefficient gradients should not be transformed to reference element")
+                raise CodegenUFLError("Coefficient gradients should not be transformed to reference element")
 
             return self.interface.pymbolic_gridfunction(o, restriction, self.grad)
 
diff --git a/python/dune/perftool/error.py b/python/dune/perftool/error.py
deleted file mode 100644
index fb77655aef3689b27b2764d76a3e20c158cbf982..0000000000000000000000000000000000000000
--- a/python/dune/perftool/error.py
+++ /dev/null
@@ -1,25 +0,0 @@
-""" Some error classes for dune-perftool """
-
-
-class PerftoolError(Exception):
-    pass
-
-
-class PerftoolUFLError(PerftoolError):
-    pass
-
-
-class PerftoolCodegenError(PerftoolError):
-    pass
-
-
-class PerftoolLoopyError(PerftoolError):
-    pass
-
-
-class PerftoolVectorizationError(PerftoolCodegenError):
-    pass
-
-
-class PerftoolAutotuneError(PerftoolVectorizationError):
-    pass
diff --git a/python/dune/perftool/generation/__init__.py b/python/dune/perftool/generation/__init__.py
deleted file mode 100644
index 607b4055850d33f2fb78f2d03ee4be771caec904..0000000000000000000000000000000000000000
--- a/python/dune/perftool/generation/__init__.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from __future__ import absolute_import
-
-from dune.perftool.generation.backend import (backend,
-                                              get_backend,
-                                              )
-
-from dune.perftool.generation.counter import (get_counter,
-                                              get_counted_variable,
-                                              )
-
-from dune.perftool.generation.cache import (cached,
-                                            generator_factory,
-                                            no_caching,
-                                            retrieve_cache_functions,
-                                            retrieve_cache_items,
-                                            delete_cache_items,
-                                            inspect_generator,
-                                            )
-
-from dune.perftool.generation.cpp import (base_class,
-                                          class_basename,
-                                          class_member,
-                                          constructor_parameter,
-                                          dump_accumulate_timer,
-                                          end_of_file,
-                                          include_file,
-                                          initializer_list,
-                                          pre_include,
-                                          preamble,
-                                          post_include,
-                                          template_parameter,
-                                          )
-
-from dune.perftool.generation.hooks import (hook,
-                                            ReturnArg,
-                                            run_hook,
-                                            )
-
-from dune.perftool.generation.loopy import (barrier,
-                                            constantarg,
-                                            domain,
-                                            function_mangler,
-                                            get_temporary_name,
-                                            globalarg,
-                                            iname,
-                                            instruction,
-                                            loopy_class_member,
-                                            kernel_cached,
-                                            noop_instruction,
-                                            silenced_warning,
-                                            subst_rule,
-                                            temporary_variable,
-                                            transform,
-                                            valuearg,
-                                            )
-
-from dune.perftool.generation.context import (cache_restoring,
-                                              global_context,
-                                              get_global_context_value,
-                                              )
diff --git a/python/dune/perftool/loopy/__init__.py b/python/dune/perftool/loopy/__init__.py
deleted file mode 100644
index c948e9e18af3ab9d5ac8686476088d43a39712d7..0000000000000000000000000000000000000000
--- a/python/dune/perftool/loopy/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-""" Export the interface interesting to the rest of the project """
-
-from dune.perftool.loopy.transformations.duplicate import heuristic_duplication
diff --git a/python/dune/perftool/options.py b/python/dune/perftool/options.py
deleted file mode 100644
index a62de9950cf6d3dff0a84b3bc52b2e1e33ed5299..0000000000000000000000000000000000000000
--- a/python/dune/perftool/options.py
+++ /dev/null
@@ -1,263 +0,0 @@
-""" Manage the command line options to the form compiler executable """
-
-from argparse import ArgumentParser
-from os.path import abspath
-from pytools import ImmutableRecord, memoize
-
-from dune.testtools.parametertree.parser import parse_ini_file
-
-
-class PerftoolOption(ImmutableRecord):
-    """ Data structure representing a single formcompiler option """
-    def __init__(self,
-                 default=None,
-                 helpstr="Undocumented feature!",
-                 process=lambda x: x,
-                 _type=type(None),
-                 ):
-        _type = type(default)
-        if issubclass(_type, type(None)):
-            _type = str
-        ImmutableRecord.__init__(self,
-                                 helpstr=helpstr,
-                                 default=default,
-                                 type=_type,
-                                 )
-
-
-class PerftoolGlobalOptionsArray(ImmutableRecord):
-    """ A collection of form compiler arguments """
-    def __init__(self, **kwargs):
-        opts = {k: v.default for k, v in PerftoolGlobalOptionsArray.__dict__.items() if isinstance(v, PerftoolOption)}
-        opts.update(**kwargs)
-        ImmutableRecord.__init__(self, **opts)
-
-    # Arguments that are to be set from the outside
-    uflfile = PerftoolOption(helpstr="the UFL file to compile")
-    debug_cache_with_stack = PerftoolOption(default=False, helpstr="Store stack along with cache objects. Makes debugging caching issues easier.")
-    driver_file = PerftoolOption(helpstr="The filename for the generated driver header")
-    explicit_time_stepping = PerftoolOption(default=False, helpstr="use explicit time stepping")
-    exact_solution_expression = PerftoolOption(helpstr="name of the exact solution expression in the ufl file")
-    compare_l2errorsquared = PerftoolOption(helpstr="maximal allowed l2 error squared of difference between numerical solution and interpolation of exact solution (NOTE: requires --exact-solution-expression)")
-    grid_info = PerftoolOption(default=None, helpstr="Path to file with information about facedir and facemod variations. This can be used to limit the generation of skeleton kernels.")
-    l2error_tree_path = PerftoolOption(default=None, helpstr="Tree pathes that should be considered for l2 error calculation. Default None means we take all of them into account.")
-    ini_file = PerftoolOption(helpstr="An inifile to use. A generated driver will be hard-coded to it, a [formcompiler] section will be used as default values to form compiler arguments (use snake case)")
-    opcounter = PerftoolOption(default=False, helpstr="Count operations. Note: In this case only operator applications are generated since solving and operator counting does not work. You probably want to set instrumentation level>0.")
-    performance_measuring = PerftoolOption(default=False, helpstr="Generate opcounter codepath, but only measure times!")
-    instrumentation_level = PerftoolOption(default=0, helpstr="Control time/opcounter measurements. 0-do nothing, 1-measure program as a whole, 2-operator applications, 3-measure kernel (eg. alpha-volume, ...), 4-parts of kernel (eg. stage 1-3 of SF)")
-    project_basedir = PerftoolOption(helpstr="The base (build) directory of the dune-perftool project")
-    architecture = PerftoolOption(default="haswell", helpstr="The architecture to optimize for. Possible values: haswell|knl|skylake")
-    yaspgrid_offset = PerftoolOption(default=False, helpstr="Set to true if you want a yasp grid where the lower left corner is not in the origin.")
-    grid_unstructured = PerftoolOption(default=False, helpstr="Set to true if you want to use an unstructured grid.")
-    precision_bits = PerftoolOption(default=64, helpstr="The number of bits for the floating point type")
-    overlapping = PerftoolOption(default=False, helpstr="Use an overlapping solver and constraints. You still need to make sure to construct a grid with overlap! The parallel option will be set automatically.")
-    operators = PerftoolOption(default="r", helpstr="A comma separated list of operators, each name will be interpreted as a subsection name within the formcompiler section")
-    target_name = PerftoolOption(default=None, helpstr="The target name from CMake")
-    operator_to_build = PerftoolOption(default=None, helpstr="The operators from the list that is about to be build now. CMake sets this one!!!")
-    debug_interpolate_input = PerftoolOption(default=False, helpstr="Should the input for printresidual and printmatix be interpolated (instead of random input).")
-
-    # Arguments that are mainly to be set by logic depending on other options
-    max_vector_width = PerftoolOption(default=256, helpstr=None)
-    parallel = PerftoolOption(default=False, helpstr="Mark that this program should be run in parallel. If set to true the c++ code will check that there are more than 1 MPI-ranks involved and the error computation will use communication.")
-
-
-class PerftoolFormOptionsArray(ImmutableRecord):
-    """ A collection of form-specific form compiler arguments """
-    def __init__(self, **kwargs):
-        opts = {k: v.default for k, v in PerftoolFormOptionsArray.__dict__.items() if isinstance(v, PerftoolOption)}
-        opts.update(**kwargs)
-        ImmutableRecord.__init__(self, **opts)
-
-    # Form specific options
-    form = PerftoolOption(default=None, helpstr="The name of the UFL object representing the form in the UFL file")
-    filename = PerftoolOption(default=None, helpstr="The filename to use for this LocalOperator")
-    classname = PerftoolOption(default=None, helpstr="The name of the C++ class to generate")
-    numerical_jacobian = PerftoolOption(default=False, helpstr="use numerical jacobians (only makes sense, if uflpdelab for some reason fails to generate analytic jacobians)")
-    matrix_free = PerftoolOption(default=False, helpstr="Generate jacobian_apply_* methods for matrix free solvers")
-    print_transformations = PerftoolOption(default=False, helpstr="print out dot files after ufl tree transformations")
-    print_transformations_dir = PerftoolOption(default=".", helpstr="place where to put dot files (can be omitted)")
-    quadrature_order = PerftoolOption(_type=int, helpstr="Quadrature order used for all integrals.")
-    diagonal_transformation_matrix = PerftoolOption(default=False, helpstr="set option if the jacobian of the transformation is diagonal (axiparallel grids)")
-    constant_transformation_matrix = PerftoolOption(default=False, helpstr="set option if the jacobian of the transformation is constant on a cell")
-    fastdg = PerftoolOption(default=False, helpstr="Use FastDGGridOperator from PDELab.")
-    sumfact = PerftoolOption(default=False, helpstr="Use sumfactorization")
-    sumfact_regular_jacobians = PerftoolOption(default=False, helpstr="Generate non sum-factorized jacobians (only useful if sumfact is set)")
-    vectorization_quadloop = PerftoolOption(default=False, helpstr="whether to generate code with explicit vectorization")
-    vectorization_strategy = PerftoolOption(default="none", helpstr="The identifier of the vectorization cost model. Possible values: none|explicit|model|target|autotune")
-    vectorization_not_fully_vectorized_error = PerftoolOption(default=False, helpstr="throw an error if nonquadloop vectorization did not fully vectorize")
-    vectorization_horizontal = PerftoolOption(default=None, helpstr="an explicit value for horizontal vectorization read by the 'explicit' strategy")
-    vectorization_vertical = PerftoolOption(default=None, helpstr="an explicit value for vertical vectorization read by the 'explicit' strategy")
-    vectorization_padding = PerftoolOption(default=None, helpstr="an explicit value for the allowed padding in vectorization")
-    vectorization_allow_quadrature_changes = PerftoolOption(default=False, helpstr="whether the vectorization strategy is allowed to alter quadrature point numbers")
-    vectorization_list_index = PerftoolOption(default=None, helpstr="Which vectorization to pick from a list (only valid with vectorization_strategy=fromlist).")
-    vectorization_jacobians = PerftoolOption(default=True, helpstr="Whether to attempt to vectorize jacobians (takes time, often not needed)")
-    vectorization_target = PerftoolOption(_type=float, helpstr="The cost function target for the 'target' cost model. Only needed to verify the cost model itself, do not use light-heartedly!!!")
-    simplify = PerftoolOption(default=False, helpstr="Whether to simplify expressions using sympy")
-    generate_jacobians = PerftoolOption(default=True, helpstr="Whether jacobian_* methods should be generated. This is set to false automatically, when numerical_jacobian is set to true.")
-    generate_jacobian_apply = PerftoolOption(default=False, helpstr="Wether jacobian_allpy_* methods should be generated.")
-    generate_residuals = PerftoolOption(default=True, helpstr="Whether alpha_* methods should be generated.")
-    unroll_dimension_loops = PerftoolOption(default=False, helpstr="whether loops over the geometric dimension should be unrolled")
-    precompute_quadrature_info = PerftoolOption(default=True, helpstr="compute quadrature points and weights in the constructor of the local operator")
-    blockstructured = PerftoolOption(default=False, helpstr="Use block structure")
-    number_of_blocks = PerftoolOption(default=1, helpstr="Number of sub blocks in one direction")
-    vectorization_blockstructured = PerftoolOption(default=False, helpstr="Vectorize block structuring")
-    adjoint = PerftoolOption(default=False, helpstr="Generate adjoint operator")
-    control = PerftoolOption(default=False, helpstr="Generate operator of derivative w.r.t. the control variable")
-    objective_function = PerftoolOption(default=None, helpstr="Name of form representing the objective function in UFL file")
-    control_variable = PerftoolOption(default=None, helpstr="Name of control variable in UFL file")
-    block_preconditioner_diagonal = PerftoolOption(default=False, helpstr="Whether this operator should implement the diagonal part of a block preconditioner")
-    block_preconditioner_offdiagonal = PerftoolOption(default=False, helpstr="Whether this operator should implement the off-diagonal part of a block preconditioner")
-
-# Until more sophisticated logic is needed, we keep the actual option data in this module
-_global_options = PerftoolGlobalOptionsArray()
-_form_options = {}
-
-
-def initialize_options():
-    """ Initialize the options from the command line """
-    global _global_options
-    _global_options = update_options_from_commandline(_global_options)
-    _global_options = update_options_from_inifile(_global_options)
-
-
-def update_options_from_commandline(opt):
-    """ Return an options array object with updated values from the commandline """
-    assert isinstance(opt, PerftoolGlobalOptionsArray)
-    parser = ArgumentParser(description="Compile UFL files to PDELab C++ code",
-                            epilog="Please report bugs to dominic.kempf@iwr.uni-heidelberg.de",
-                            )
-    parser.add_argument('--version', action='version', version='%(prog)s 0.1')
-    for k, v in type(opt).__dict__.items():
-        if isinstance(v, PerftoolOption) and v.helpstr is not None:
-            cmdopt = "--{}".format(k.replace('_', '-'))
-            parser.add_argument(cmdopt, help=v.helpstr, type=v.type)
-    parsedargs = {k: v for k, v in vars(parser.parse_args()).items() if v is not None}
-    return opt.copy(**parsedargs)
-
-
-def update_options_from_inifile(opt):
-    """ Return an options array object with updated values from an inifile """
-    if opt.ini_file:
-        def parse_ini(section, opttype):
-            def _fix_types(k, v):
-                if hasattr(opttype, k) and getattr(opttype, k).type is bool:
-                    return bool(eval(v))
-                if hasattr(opttype, k):
-                    return getattr(opttype, k).type(v)
-                return v
-            ini = parse_ini_file(opt.ini_file).get(section, {})
-            return {k: _fix_types(k, v) for k, v in ini.items()}
-
-        opt = opt.copy(**parse_ini("formcompiler", PerftoolGlobalOptionsArray))
-        # Also parse form-specific options
-        for form in [i.strip() for i in opt.operators.split(",")]:
-            _form_options[form] = PerftoolFormOptionsArray(**parse_ini("formcompiler.{}".format(form), PerftoolFormOptionsArray))
-
-    return opt
-
-
-@memoize
-def process_global_options(opt):
-    """ Make sure that the options have been fully processed """
-    opt = expand_architecture_options(opt)
-
-    if opt.overlapping:
-        opt = opt.copy(parallel=True)
-
-    return opt
-
-
-@memoize
-def process_form_options(opt, form):
-    if opt.sumfact:
-        opt = opt.copy(unroll_dimension_loops=True)
-
-    if opt.numerical_jacobian:
-        opt = opt.copy(generate_jacobians=False, generate_jacobian_apply=False)
-
-    if opt.form is None:
-        opt = opt.copy(form=form)
-
-    if opt.classname is None:
-        opt = opt.copy(classname="{}Operator".format(form))
-
-    if opt.filename is None:
-        opt = opt.copy(filename="{}_{}_file.hh".format(get_option("target_name"), opt.classname))
-
-    if opt.block_preconditioner_diagonal or opt.block_preconditioner_offdiagonal:
-        assert opt.numerical_jacobian is False
-        opt = opt.copy(generate_residuals=False,
-                       generate_jacobians=False,
-                       matrix_free=True,
-                       )
-
-    if opt.matrix_free:
-        opt = opt.copy(generate_jacobian_apply=True)
-
-    return opt
-
-
-def expand_architecture_options(opt):
-    if opt.architecture == "haswell":
-        return opt.copy(max_vector_width=256)
-    elif opt.architecture == "knl":
-        return opt.copy(max_vector_width=512)
-    elif opt.architecture == "skylake":
-        return opt.copy(max_vector_width=512)
-    else:
-        raise NotImplementedError("Architecture {} not known!".format(opt.architecture))
-
-
-def set_option(key, value):
-    """Add the key value pair to the options.
-
-    If the key is already in the options dictionary its value will be
-    overwritten.  Form compiler arguments will always be set before
-    any other options.
-    """
-    global _global_options
-    _global_options = process_global_options(_global_options).copy(**{key: value})
-
-
-def set_form_option(key, value, form=None):
-    if form is None:
-        from dune.perftool.generation import get_global_context_value
-        form = get_global_context_value("form_identifier", 0)
-    if isinstance(form, int):
-        form = get_option("operators").split(",")[form].strip()
-    _form_options[form] = _form_options[form].copy(**{key: value})
-
-
-def get_option(key):
-    processed_global_opts = process_global_options(_global_options)
-    return getattr(processed_global_opts, key)
-
-
-def get_form_option(key, form=None):
-    if form is None:
-        from dune.perftool.generation import get_global_context_value
-        form = get_global_context_value("form_identifier", 0)
-    if isinstance(form, int):
-        form = get_option("operators").split(",")[form].strip()
-    processed_form_opts = process_form_options(_form_options[form], form)
-    return getattr(processed_form_opts, key)
-
-
-def option_switch(opt):
-    def _switch():
-        if isinstance(opt, tuple):
-            opts = opt
-        else:
-            assert isinstance(opt, str)
-            opts = (opt,)
-        try:
-            for o in opts:
-                if get_option(o):
-                    return o
-            return "default"
-        except AttributeError:
-            for o in opts:
-                if get_form_option(o):
-                    return o
-            return "default"
-    return _switch
diff --git a/python/setup.py b/python/setup.py
index e4517d2f7f6c1b57b7f57f69c90b20a5f4a05f3f..88431ad1b496afc1c41d13fae5608956274f3018 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -23,29 +23,29 @@ class PyTest(TestCommand):
         sys.exit(errno)
 
 
-setup(name='dune.perftool',
+setup(name='dune.codegen',
       version='0.1',
       namespace_packages=['dune'],
-      description='Performance optimizing form compiler for dune-pdelab',
+      description='Performance optimizing form compiler for the Dune project',
       author='Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>',
-      url='http://conan2.iwr.uni-heidelberg.de/git/dominic/dune-perftool',
-      packages=['dune.perftool',
-                'dune.perftool.blockstructured',
-                'dune.perftool.cgen',
-                'dune.perftool.generation',
-                'dune.perftool.loopy',
-                'dune.perftool.loopy.transformations',
-                'dune.perftool.pdelab',
-                'dune.perftool.pdelab.driver',
-                'dune.perftool.sumfact',
-                'dune.perftool.ufl',
-                'dune.perftool.ufl.transformations',
+      url='https://gitlab.dune-project.org/dominic/dune-codegen.git',
+      packages=['dune.codegen',
+                'dune.codegen.blockstructured',
+                'dune.codegen.cgen',
+                'dune.codegen.generation',
+                'dune.codegen.loopy',
+                'dune.codegen.loopy.transformations',
+                'dune.codegen.pdelab',
+                'dune.codegen.pdelab.driver',
+                'dune.codegen.sumfact',
+                'dune.codegen.ufl',
+                'dune.codegen.ufl.transformations',
                 ],
       install_requires=['dune.testtools', 'sympy', 'frozendict', 'pytest', 'pytest-pep8', 'filelock'],
       cmdclass={'test': PyTest},
       entry_points = {
         "console_scripts": [
-            "generate_operators = dune.perftool.compile:entry_generate_operators",
-            "generate_driver = dune.perftool.compile:entry_generate_driver",
+            "generate_operators = dune.codegen.compile:entry_generate_operators",
+            "generate_driver = dune.codegen.compile:entry_generate_driver",
         ]
     })
diff --git a/python/test/dune/CMakeLists.txt b/python/test/dune/CMakeLists.txt
index aa7576d1c35c9909239d791d3662895bfe01ec0e..94215f15e886594a2c0cf4bd5d2ad2e32aed0a81 100644
--- a/python/test/dune/CMakeLists.txt
+++ b/python/test/dune/CMakeLists.txt
@@ -1 +1 @@
-add_subdirectory(perftool)
+add_subdirectory(codegen)
diff --git a/python/test/dune/perftool/CMakeLists.txt b/python/test/dune/codegen/CMakeLists.txt
similarity index 100%
rename from python/test/dune/perftool/CMakeLists.txt
rename to python/test/dune/codegen/CMakeLists.txt
diff --git a/python/test/dune/perftool/generation/CMakeLists.txt b/python/test/dune/codegen/generation/CMakeLists.txt
similarity index 86%
rename from python/test/dune/perftool/generation/CMakeLists.txt
rename to python/test/dune/codegen/generation/CMakeLists.txt
index ac853807fc3b55b37e3051baf8d40dfc407f47ce..2fc91aa467acb195bcdc7d3544f62b821e65a9f7 100644
--- a/python/test/dune/perftool/generation/CMakeLists.txt
+++ b/python/test/dune/codegen/generation/CMakeLists.txt
@@ -1,4 +1,4 @@
 dune_python_add_test(NAME pytest
                      COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pytest --pep8
-                     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python/test/dune/perftool/generation
+                     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python/test/dune/codegen/generation
                      )
diff --git a/python/test/dune/perftool/generation/test_backend.py b/python/test/dune/codegen/generation/test_backend.py
similarity index 76%
rename from python/test/dune/perftool/generation/test_backend.py
rename to python/test/dune/codegen/generation/test_backend.py
index 2a1e001cd9da6dad0d0d18c46d2da47d9506da7c..76bda979394f0293f5b9d1a9314a80ce58ba8a66 100644
--- a/python/test/dune/perftool/generation/test_backend.py
+++ b/python/test/dune/codegen/generation/test_backend.py
@@ -1,7 +1,7 @@
-from dune.perftool.generation import (backend,
-                                      get_backend,
-                                      generator_factory,
-                                      )
+from dune.codegen.generation import (backend,
+                                     get_backend,
+                                     generator_factory,
+                                     )
 
 
 @backend(interface="foo", name="f1")
diff --git a/python/test/dune/perftool/generation/test_cache.py b/python/test/dune/codegen/generation/test_cache.py
similarity index 94%
rename from python/test/dune/perftool/generation/test_cache.py
rename to python/test/dune/codegen/generation/test_cache.py
index f28c6e06227631ad2161527367e51c81920119f5..19d6ea5be11c819ed371aef7f5d16abf1a0c41f0 100644
--- a/python/test/dune/perftool/generation/test_cache.py
+++ b/python/test/dune/codegen/generation/test_cache.py
@@ -1,12 +1,12 @@
 from collections import Counter
 
-from dune.perftool.generation import(delete_cache_items,
-                                     generator_factory,
-                                     global_context,
-                                     no_caching,
-                                     retrieve_cache_functions,
-                                     retrieve_cache_items,
-                                     )
+from dune.codegen.generation import(delete_cache_items,
+                                    generator_factory,
+                                    global_context,
+                                    no_caching,
+                                    retrieve_cache_functions,
+                                    retrieve_cache_items,
+                                    )
 
 
 def print_cache():
diff --git a/test/adjoint/poisson_mc_driver.hh b/test/adjoint/poisson_mc_driver.hh
index d75f8b056ae11c39f299d243f04de10f866b00ea..5bd222b800baf36c09bd172c48d706a135912c80 100644
--- a/test/adjoint/poisson_mc_driver.hh
+++ b/test/adjoint/poisson_mc_driver.hh
@@ -11,7 +11,7 @@
 #include "dune/pdelab/function/callableadapter.hh"
 #include "dune/alugrid/grid.hh"
 #include "string"
-#include "dune/perftool/vtkpredicate.hh"
+#include "dune/codegen/vtkpredicate.hh"
 #include "dune/pdelab/gridfunctionspace/gridfunctionadapter.hh"
 #include "dune/common/parametertree.hh"
 #include "dune/pdelab/gridoperator/gridoperator.hh"
diff --git a/test/coeffeval/coeffeval_poisson.cc b/test/coeffeval/coeffeval_poisson.cc
index d4cd8e0d89850879394681162710f54e458a2bb3..4f9e8861b5139dacb8183327ad053b3cb2373b8b 100644
--- a/test/coeffeval/coeffeval_poisson.cc
+++ b/test/coeffeval/coeffeval_poisson.cc
@@ -10,7 +10,7 @@
 #include "dune/pdelab/finiteelementmap/pkfem.hh"
 #include <random>
 #include "dune/pdelab/function/callableadapter.hh"
-#include "dune/perftool/vtkpredicate.hh"
+#include "dune/codegen/vtkpredicate.hh"
 #include <string>
 #include "dune/alugrid/grid.hh"
 #include "dune/pdelab/common/functionutilities.hh"
diff --git a/test/heatequation/driver.hh b/test/heatequation/driver.hh
index 4222ca89cea72d35021faabee8344c24a5cc63f0..c86c22470a1b68c0ab60a358b062164de3770360 100644
--- a/test/heatequation/driver.hh
+++ b/test/heatequation/driver.hh
@@ -3,7 +3,7 @@
 //! \brief Driver function to set up and solve the problem
 /********************************************************/
 
-#include <dune/perftool/vtkpredicate.hh>
+#include <dune/codegen/vtkpredicate.hh>
 template<typename GV, typename FEM>
 void driver (const GV& gv, const FEM& fem, Dune::ParameterTree& ptree)
 {
diff --git a/test/navier-stokes/reference_program/taylor-green.cc b/test/navier-stokes/reference_program/taylor-green.cc
index e48e04296122dd89b615166f33d21219324d0726..48d6572d05eb4ca294a876a8afc5e6a80d7a0cd3 100644
--- a/test/navier-stokes/reference_program/taylor-green.cc
+++ b/test/navier-stokes/reference_program/taylor-green.cc
@@ -35,7 +35,7 @@
 #include <dune/pdelab/constraints/p0.hh>
 #include<dune/pdelab/gridoperator/onestep.hh>
 #include<dune/pdelab/newton/newton.hh>
-#include "dune/perftool/vtkpredicate.hh"
+#include "dune/codegen/vtkpredicate.hh"
 #include "dune/grid/io/file/vtk/vtksequencewriter.hh"
 
 #include "taylor-green.hh"
diff --git a/test/nonlinear/reference_driver.hh b/test/nonlinear/reference_driver.hh
index e24b24e1c534fac76d6c82bf12ec45426d9c327c..01f7103bd798ca536e1faa712d91e7a969aafb5a 100644
--- a/test/nonlinear/reference_driver.hh
+++ b/test/nonlinear/reference_driver.hh
@@ -13,7 +13,7 @@
 #include <dune/pdelab/gridoperator/gridoperator.hh>
 #include <dune/pdelab/gridfunctionspace/vtk.hh>
 #include <dune/pdelab/newton/newton.hh>
-#include <dune/perftool/vtkpredicate.hh>
+#include <dune/codegen/vtkpredicate.hh>
 #include <dune/pdelab/backend/istl.hh>
 #include <string>
 #include <dune/pdelab/backend/istl.hh>