Creating release candidate final from release_361 branch

git-svn-id: https://llvm.org/svn/llvm-project/polly/tags/RELEASE_361@237762 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/final/.arcconfig b/final/.arcconfig
new file mode 100644
index 0000000..d64a648
--- /dev/null
+++ b/final/.arcconfig
@@ -0,0 +1,11 @@
+{
+  "project_id" : "polly",
+  "conduit_uri" : "http://reviews.llvm.org/",
+  "history.immutable" : true,
+  "linter.scriptandregex.script": "sh -c './utils/check_format.sh \"$0\" 2> /dev/null || true'",
+  "linter.scriptandregex.regex": "/^(OK:(?P<ignore>.+)|Error:) (?P<message>.+)$/m",
+  "load" : [
+    "utils/arcanist/LitTestEngine"
+  ],
+  "unit.engine" : "LitTestEngine"
+}
diff --git a/final/.arclint b/final/.arclint
new file mode 100644
index 0000000..84546f5
--- /dev/null
+++ b/final/.arclint
@@ -0,0 +1,23 @@
+{
+  "linters": {
+    "format": {
+      "include": "(include/polly/.+\\.h$|lib/.+\\.cpp$)",
+      "exclude": "(lib/JSON/.*)",
+      "type": "script-and-regex"
+    },
+    "chmod": {
+      "type": "chmod"
+    },
+    "filename": {
+      "exclude": "(www/experiments/.+|.*\\.jscop.*)",
+      "type": "filename"
+    },
+    "merge-conflict": {
+      "type": "merge-conflict"
+    },
+    "spelling": {
+      "exclude": "(configure|autoconf/.*)",
+      "type": "spelling"
+    }
+  }
+}
diff --git a/final/.gitattributes b/final/.gitattributes
new file mode 100644
index 0000000..7105fff
--- /dev/null
+++ b/final/.gitattributes
@@ -0,0 +1,4 @@
+# Auto detect text files and perform LF normalization
+* text eol=lf
+*.png -text
+*.pdf -text
diff --git a/final/.gitignore b/final/.gitignore
new file mode 100644
index 0000000..8618b3d
--- /dev/null
+++ b/final/.gitignore
@@ -0,0 +1 @@
+test/lit.site.cfg
diff --git a/final/CMakeLists.txt b/final/CMakeLists.txt
new file mode 100644
index 0000000..6e72fba
--- /dev/null
+++ b/final/CMakeLists.txt
@@ -0,0 +1,165 @@
+# Check if this is a in tree build.
+if (NOT DEFINED LLVM_MAIN_SRC_DIR)
+  project(Polly)
+  cmake_minimum_required(VERSION 2.8)
+
+  # Where is LLVM installed?
+  set(LLVM_INSTALL_ROOT "" CACHE PATH "Root of LLVM install.")
+  # Check if the LLVM_INSTALL_ROOT valid.
+  if( NOT EXISTS ${LLVM_INSTALL_ROOT}/include/llvm )
+    message(FATAL_ERROR "LLVM_INSTALL_ROOT (${LLVM_INSTALL_ROOT}) is not a valid LLVM installation.")
+  endif(NOT EXISTS ${LLVM_INSTALL_ROOT}/include/llvm)
+  #FileCheck is not install by default, warn the user to Copy FileCheck
+  if( NOT EXISTS ${LLVM_INSTALL_ROOT}/bin/FileCheck
+      OR NOT EXISTS ${LLVM_INSTALL_ROOT}/bin/not)
+    message(WARNING "FileCheck or not are required by running regress tests, "
+                    "but they are not installed! Please copy it to "
+                    "${LLVM_INSTALL_ROOT}/bin.")
+  endif(NOT EXISTS ${LLVM_INSTALL_ROOT}/bin/FileCheck
+        OR NOT EXISTS ${LLVM_INSTALL_ROOT}/bin/not)
+  # Add the llvm header path.
+  include_directories(${LLVM_INSTALL_ROOT}/include/)
+
+  # Get the system librarys that will link into LLVM.
+  function(get_system_libs return_var)
+    # Returns in `return_var' a list of system libraries used by LLVM.
+    if( NOT MSVC )
+      if( MINGW )
+        set(system_libs ${system_libs} imagehlp psapi)
+      elseif( CMAKE_HOST_UNIX )
+        if( HAVE_LIBDL )
+          set(system_libs ${system_libs} ${CMAKE_DL_LIBS})
+        endif()
+        if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )
+          set(system_libs ${system_libs} pthread)
+        endif()
+      endif( MINGW )
+    endif( NOT MSVC )
+    set(${return_var} ${system_libs} PARENT_SCOPE)
+  endfunction(get_system_libs)
+
+  # Now set the header paths.
+  execute_process(COMMAND "${LLVM_INSTALL_ROOT}/bin/llvm-config" --includedir
+                  OUTPUT_VARIABLE LLVM_INCLUDE_DIR
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+  include_directories( ${LLVM_INCLUDE_DIR} )
+
+  # Get the TARGET_TRIPLE
+  execute_process(COMMAND "${LLVM_INSTALL_ROOT}/bin/llvm-config" --host-target
+                  OUTPUT_VARIABLE TARGET_TRIPLE
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+  # And then set the cxx flags.
+  execute_process(COMMAND "${LLVM_INSTALL_ROOT}/bin/llvm-config" --cxxflags
+                  OUTPUT_VARIABLE LLVM_CXX_FLAGS
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+  set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS})
+endif(NOT DEFINED LLVM_MAIN_SRC_DIR)
+
+set(POLLY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(POLLY_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+# Add path for custom modules
+set(CMAKE_MODULE_PATH
+  ${CMAKE_MODULE_PATH}
+  "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
+  )
+
+include("polly_macros")
+
+# Add appropriate flags for GCC
+if (CMAKE_COMPILER_IS_GNUCXX)
+  # FIXME: Turn off exceptions, RTTI:
+  # -fno-exceptions -fno-rtti
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -fno-exceptions -fno-rtti")
+endif ()
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
+
+# Add path for custom modules
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${POLLY_SOURCE_DIR}/cmake")
+
+SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+
+FIND_PACKAGE(Isl REQUIRED)
+set(POLLY_LINK_LIBS ${ISL_LIBRARY})
+
+FIND_PACKAGE(Pluto)
+if(PLUTO_FOUND)
+  set(POLLY_LINK_LIBS ${POLLY_LINK_LIBS} ${PLUTO_LIBRARY})
+endif(PLUTO_FOUND)
+
+if(GMP_FOUND)
+  set(POLLY_LINK_LIBS ${POLLY_LINK_LIBS} ${GMP_LIBRARY})
+endif(GMP_FOUND)
+
+option(POLLY_ENABLE_GPGPU_CODEGEN "Enable GPGPU code generation feature" OFF)
+if (POLLY_ENABLE_GPGPU_CODEGEN)
+  # Do not require CUDA, as GPU code generation test cases can be run without
+  # a cuda library.
+  FIND_PACKAGE(CUDA)
+  set(GPU_CODEGEN TRUE)
+endif(POLLY_ENABLE_GPGPU_CODEGEN)
+
+if (PLUTO_FOUND)
+  INCLUDE_DIRECTORIES( ${PLUTO_INCLUDE_DIR} )
+endif(PLUTO_FOUND)
+INCLUDE_DIRECTORIES( ${ISL_INCLUDE_DIR} )
+if (GMP_FOUND)
+  INCLUDE_DIRECTORIES( ${GMP_INCLUDE_DIR} )
+endif(GMP_FOUND)
+
+# Support GPGPU code generation if the library is available.
+if (CUDALIB_FOUND)
+  INCLUDE_DIRECTORIES( ${CUDALIB_INCLUDE_DIR} )
+endif(CUDALIB_FOUND)
+
+include_directories(
+  BEFORE
+  ${CMAKE_CURRENT_SOURCE_DIR}/include
+  ${CMAKE_CURRENT_SOURCE_DIR}/lib/JSON/include
+  ${CMAKE_CURRENT_BINARY_DIR}/include
+  )
+
+install(DIRECTORY include/
+  DESTINATION include
+  FILES_MATCHING
+  PATTERN "*.h"
+  PATTERN ".svn" EXCLUDE
+  )
+
+install(DIRECTORY ${POLLY_BINARY_DIR}/include/
+  DESTINATION include
+  FILES_MATCHING
+  PATTERN "*.h"
+  PATTERN "CMakeFiles" EXCLUDE
+  PATTERN ".svn" EXCLUDE
+  )
+
+add_definitions( -D_GNU_SOURCE )
+
+add_subdirectory(include)
+add_subdirectory(lib)
+add_subdirectory(test)
+add_subdirectory(tools)
+# TODO: docs.
+
+
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/polly/Config/config.h.cmake
+                ${POLLY_BINARY_DIR}/include/polly/Config/config.h )
+
+# Add target to check formatting of polly files
+file( GLOB_RECURSE files *.h *.cpp)
+file( GLOB_RECURSE jsonfiles lib/JSON/*.h lib/JSON/*.cpp)
+list( REMOVE_ITEM files ${jsonfiles} )
+add_custom_command( OUTPUT formatting COMMAND
+  CLANG_FORMAT=${LLVM_BINARY_DIR}/bin/clang-format
+  ${CMAKE_CURRENT_SOURCE_DIR}/utils/check_format.sh ${files})
+add_custom_target(polly-check-format DEPENDS formatting)
+add_custom_command( OUTPUT formatting-update COMMAND
+  CLANG_FORMAT=${LLVM_BINARY_DIR}/bin/clang-format
+  ${CMAKE_CURRENT_SOURCE_DIR}/utils/update_format.sh ${files})
+add_custom_target(polly-update-format DEPENDS formatting-update)
+
+# Set the variable POLLY_LINK_LIBS in the llvm/tools/ dir.
+set(POLLY_LINK_LIBS ${POLLY_LINK_LIBS} PARENT_SCOPE)
diff --git a/final/CREDITS.txt b/final/CREDITS.txt
new file mode 100644
index 0000000..98fb9cd
--- /dev/null
+++ b/final/CREDITS.txt
@@ -0,0 +1,42 @@
+This file is a partial list of people who have contributed to Polly.
+If you have contributed a patch or made some other contribution to
+Polly, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts.  The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Raghesh Aloor
+E: raghesh.a@gmail.com
+D: OpenMP code generation
+D: Google Summer of Code student 2011
+
+N: Tobias Grosser
+E: tobias@grosser.es
+W: http://www.grosser.es
+D: Co-founder, design of the overall architecture
+
+N: Yabin Hu
+E: yabin.hwu@gmail.com
+D: GPGPU code generation
+D: Google Summer of Code student 2012, 2014
+
+N: Andreas Simbuerger
+E: simbuerg@fim.uni-passau.de
+W: http://www.infosun.fim.uni-passau.de/cl/staff/simbuerger/
+D: Profiling infrastructure
+
+N: Hongbin Zheng
+E: etherzhhb@gmail.com
+D: Co-founder
+D: scop detection, automake/cmake infrastructure, scopinfo, scoppasses, ...
+D: Google Summer of Code student 2010
+
+N: Johannes Doerfert
+E: doerfert@cs.uni-saarland.de
+E: jdoerfert@codeaurora.org
+W: http://www.cdl.uni-saarland.de/people/doerfert/
+P: http://www.cdl.uni-saarland.de/people/doerfert/JohannesDoerfert.asc
+D: reductions, general infrastructure
diff --git a/final/LICENSE.txt b/final/LICENSE.txt
new file mode 100644
index 0000000..86d29f5
--- /dev/null
+++ b/final/LICENSE.txt
@@ -0,0 +1,61 @@
+==============================================================================
+Polly Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2014 Polly Team
+All rights reserved.
+
+Developed by:
+
+    Polly Team
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the Polly Team, copyright holders, nor the names of
+      its contributors may be used to endorse or promote products derived from
+      this Software without specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The Polly software contains code written by third parties.   Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the Polly Distribution, and nothing in any of the other
+licenses gives permission to use the names of the Polly Team or promote products
+derived from this Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+jsoncpp             lib/JSON
+
+
+
diff --git a/final/Makefile b/final/Makefile
new file mode 100644
index 0000000..2ad5b36
--- /dev/null
+++ b/final/Makefile
@@ -0,0 +1,17 @@
+##===- projects/polly/Makefile -----------------------------*- Makefile -*-===##
+#
+# This is a polly Makefile for a project that uses LLVM.
+#
+##===----------------------------------------------------------------------===##
+
+#
+# Indicates our relative path to the top of the project's root directory.
+#
+LEVEL = .
+DIRS = lib test tools
+EXTRA_DIST = include
+
+#
+# Include the Master Makefile that knows how to build all.
+#
+include $(LEVEL)/Makefile.common
diff --git a/final/Makefile.common.in b/final/Makefile.common.in
new file mode 100644
index 0000000..8a5b945
--- /dev/null
+++ b/final/Makefile.common.in
@@ -0,0 +1,34 @@
+#===-- Makefile.common - Common make rules for Polly -------*- Makefile -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+#
+# Configuration file to set paths specific to local installation of LLVM
+#
+PROJECT_NAME := polly
+PROJ_VERSION := 0.9
+# Set this variable to the top of the LLVM source tree.
+LLVM_SRC_ROOT = @LLVM_SRC@
+
+# Set the name of the project here
+
+# (this is *not* the same as OBJ_ROOT as defined in LLVM's Makefile.config).
+LLVM_OBJ_ROOT = @LLVM_OBJ@
+
+PROJ_SRC_ROOT := $(subst //,/,@abs_top_srcdir@)
+
+# Set the root directory of this project's object files
+PROJ_OBJ_ROOT := $(subst //,/,@abs_top_builddir@)
+
+ifndef LLVM_OBJ_ROOT
+include $(LEVEL)/Makefile.config
+else
+include $(PROJ_OBJ_ROOT)/Makefile.config
+endif
+
+# Include LLVM's Master Makefile.
+include $(LLVM_SRC_ROOT)/Makefile.common
diff --git a/final/Makefile.config.in b/final/Makefile.config.in
new file mode 100644
index 0000000..c84be0b
--- /dev/null
+++ b/final/Makefile.config.in
@@ -0,0 +1,40 @@
+#===-- Makefile.config - Local configuration for LLVM ------*- Makefile -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+#
+# This file is included by Makefile.common.  It defines paths and other
+# values specific to a particular installation of LLVM.
+#
+#===------------------------------------------------------------------------===#
+
+# Set the root directory of this polly's object files
+POLLY_SRC_ROOT := $(subst //,/,@abs_top_srcdir@)
+
+# Set this variable to the top level directory where LLVM was built
+POLLY_OBJ_ROOT := $(subst //,/,@abs_top_builddir@)
+
+# Set the root directory of this project's install prefix
+PROJ_INSTALL_ROOT := @prefix@
+
+# Set the C++ flags
+ifeq (@GXX@,yes)
+POLLY_CXXFLAGS := "-fno-common -Woverloaded-virtual -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings"
+endif
+
+POLLY_CXXFLAGS += "-fno-rtti -fno-exceptions"
+
+PLUTO_FOUND := @pluto_found@
+CUDALIB_FOUND := @cuda_found@
+
+# Set include directroys
+POLLY_INC :=  @gmp_inc@ @isl_inc@ @cuda_inc@\
+				      @pluto_inc@ -I$(POLLY_SRC_ROOT)/lib/JSON/include
+
+POLLY_LD := @gmp_ld@ @isl_ld@ @cuda_ld@ @pluto_ld@
+
+POLLY_LIB := @gmp_lib@ @isl_lib@ @cuda_lib@ @pluto_lib@
diff --git a/final/README b/final/README
new file mode 100644
index 0000000..09a4a54
--- /dev/null
+++ b/final/README
@@ -0,0 +1,12 @@
+Polly - Polyhedral optimizations for LLVM
+-----------------------------------------
+http://polly.llvm.org/
+
+Polly uses a mathematical representation, the polyhedral model, to represent and
+transform loops and other control flow structures. Using an abstract
+representation it is possible to reason about transformations in a more general
+way and to use highly optimized linear programming libraries to figure out the
+optimal loop structure. These transformations can be used to do constant
+propagation through arrays, remove dead loop iterations, optimize loops for
+cache locality, optimize arrays, apply advanced automatic parallelization, drive
+vectorization, or they can be used to do software pipelining.
diff --git a/final/autoconf/AutoRegen.sh b/final/autoconf/AutoRegen.sh
new file mode 100755
index 0000000..bafef34
--- /dev/null
+++ b/final/autoconf/AutoRegen.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+die () {
+	echo "$@" 1>&2
+	exit 1
+}
+
+test -d autoconf && test -f autoconf/configure.ac && cd autoconf
+test -f configure.ac || die "Can't find 'autoconf' dir; please cd into it first"
+autoconf --version | egrep '2\.[5-6][0-9]' > /dev/null
+if test $? -ne 0 ; then
+	die "Your autoconf was not detected as being 2.5x"
+fi
+cwd=`pwd`
+if test -d ../../../autoconf/m4 ; then
+  cd ../../../autoconf/m4
+  llvm_m4=`pwd`
+  cd $cwd
+elif test -d ../../llvm/autoconf/m4 ; then
+  cd ../../llvm/autoconf/m4
+  llvm_m4=`pwd`
+  cd $cwd
+else
+  die "Can't find the LLVM autoconf/m4 directory. polly should be checked out to projects directory"
+fi
+echo "Regenerating aclocal.m4 with aclocal"
+rm -f aclocal.m4
+aclocal -I $llvm_m4 -I "$llvm_m4/.." -I $(pwd)/m4 || die "aclocal failed"
+echo "Regenerating configure with autoconf 2.5x"
+autoconf --force --warnings=all -o ../configure configure.ac || die "autoconf failed"
+cd ..
+echo "Regenerating config.h.in with autoheader"
+autoheader --warnings=all -I autoconf -I autoconf/m4 -I $llvm_m4 -I "$llvm_m4/.." autoconf/configure.ac || die "autoheader failed"
+exit 0
diff --git a/final/autoconf/LICENSE.TXT b/final/autoconf/LICENSE.TXT
new file mode 100644
index 0000000..72fdd39
--- /dev/null
+++ b/final/autoconf/LICENSE.TXT
@@ -0,0 +1,24 @@
+------------------------------------------------------------------------------
+Autoconf Files
+------------------------------------------------------------------------------
+All autoconf files are licensed under the LLVM license with the following
+additions:
+
+llvm/autoconf/install-sh:
+	This script is licensed under the LLVM license, with the following
+	additional copyrights and restrictions:
+
+	Copyright 1991 by the Massachusetts Institute of Technology
+
+	Permission to use, copy, modify, distribute, and sell this software and its
+	documentation for any purpose is hereby granted without fee, provided that
+	the above copyright notice appear in all copies and that both that
+	copyright notice and this permission notice appear in supporting 
+	documentation, and that the name of M.I.T. not be used in advertising or
+	publicity pertaining to distribution of the software without specific,
+	written prior permission.  M.I.T. makes no representations about the
+	suitability of this software for any purpose.  It is provided "as is"
+	without express or implied warranty.
+
+Please see the source files for additional copyrights.
+
diff --git a/final/autoconf/aclocal.m4 b/final/autoconf/aclocal.m4
new file mode 100644
index 0000000..d503064
--- /dev/null
+++ b/final/autoconf/aclocal.m4
@@ -0,0 +1,77 @@
+# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+# Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+dnl find_lib_and_headers(name, verify-header, library-name, requirded?)
+dnl Export
+dnl         name_inc in -I"include-path" form
+dnl         name_lib in -l"library-name" form
+dnl         name_ld  in -L"library-path" form
+dnl         name_found set to "yes" if found
+
+AC_DEFUN([find_lib_and_headers],
+[
+  AC_LANG_PUSH(C++)
+  OLD_CXXFLAGS=$CXXFLAGS;
+  OLD_LDFLAGS=$LDFLAGS;
+  OLD_LIBS=$LIBS;
+
+  LIBS="$LIBS -l$3";
+
+  # Get include path and lib path
+  AC_ARG_WITH([$1],
+    [AS_HELP_STRING([--with-$1], [prefix of $1 ])],
+      [given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
+       given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"],
+      [given_inc_path=inc_not_give_$1;
+       given_lib_path=lib_not_give_$1]
+    )
+  # Check for library and headers works
+  AC_MSG_CHECKING([for $1: $2 in $given_inc_path, and lib$3 in $given_lib_path])
+
+  # try to compile a file that includes a header of the library
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <$2>]], [[;]])],
+    [AC_MSG_RESULT([ok])
+    AC_SUBST([$1_found],["yes"])
+    AS_IF([test "x$given_inc_path" != "xinc_not_give_$1"],
+      [AC_SUBST([$1_inc],["-I$given_inc_path"])])
+    AC_SUBST([$1_lib],["-l$3"])
+    AS_IF([test "x$given_lib_path" != "xlib_not_give_$1"],
+      [AC_SUBST([$1_ld],["-L$given_lib_path"])])],
+    [AS_IF([test "x$4" = "xrequired"],
+      [AC_MSG_ERROR([$1 required but not found])],
+      [AC_MSG_RESULT([not found])])]
+  )
+
+  # reset original CXXFLAGS
+  CXXFLAGS=$OLD_CXXFLAGS
+  LDFLAGS=$OLD_LDFLAGS;
+  LIBS=$OLD_LIBS
+  AC_LANG_POP(C++)
+])
+
+#
+# Provide the arguments and other processing needed for an LLVM project
+#
+AC_DEFUN([LLVM_CONFIG_PROJECT],
+  [AC_ARG_WITH([llvmsrc],
+    AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]),
+    [llvm_src="$withval"],[llvm_src="]$1["])
+  AC_SUBST(LLVM_SRC,$llvm_src)
+  AC_ARG_WITH([llvmobj],
+    AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]),
+    [llvm_obj="$withval"],[llvm_obj="]$2["])
+  AC_SUBST(LLVM_OBJ,$llvm_obj)
+  AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"])
+])
+
diff --git a/final/autoconf/config.guess b/final/autoconf/config.guess
new file mode 100644
index 0000000..cc726cd
--- /dev/null
+++ b/final/autoconf/config.guess
@@ -0,0 +1,1388 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-02-22'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    macppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mipseb-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sun3:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7 && exit 0 ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c \
+	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && exit 0
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    # avoid double evaluation of $set_cc_for_build
+	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    *:UNICOS/mp:*:*)
+	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
+	exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	# Determine whether the default compiler uses glibc.
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#if __GLIBC__ >= 2
+	LIBC=gnu
+	#else
+	LIBC=
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    x86:Interix*:3*)
+	echo i586-pc-interix3
+	exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit 0 ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#ifdef __INTEL_COMPILER
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit 0 ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	case `uname -p` in
+	    *86) UNAME_PROCESSOR=i686 ;;
+	    powerpc) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/final/autoconf/config.sub b/final/autoconf/config.sub
new file mode 100644
index 0000000..9772e87
--- /dev/null
+++ b/final/autoconf/config.sub
@@ -0,0 +1,1489 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-02-22'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+	| clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k \
+	| m32r | m68000 | m68k | m88k | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| msp430 \
+	| ns16k | ns32k \
+	| openrisc | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+	| strongarm \
+	| tahoe | thumb | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xscale | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* \
+	| bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* \
+	| m32r-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| msp430-* \
+	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+	| xtensa-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nv1)
+		basic_machine=nv1-cray
+		os=-unicosmp
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	or32 | or32-*)
+		basic_machine=or32-unknown
+		os=-coff
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2)
+		basic_machine=i686-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+        tic4x | c4x*)
+		basic_machine=tic4x-unknown
+		os=-coff
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/final/autoconf/configure.ac b/final/autoconf/configure.ac
new file mode 100644
index 0000000..15008f8
--- /dev/null
+++ b/final/autoconf/configure.ac
@@ -0,0 +1,116 @@
+dnl **************************************************************************
+dnl * Initialize
+dnl **************************************************************************
+AC_INIT([Polly],[0.01],[polly-dev@googlegroups.com])
+
+dnl Identify where LLVM source tree is
+LLVM_SRC_ROOT="`(cd $srcdir/../..; pwd)`"
+LLVM_OBJ_ROOT="`(cd ../..; pwd)`"
+
+dnl Tell autoconf that this is an LLVM project being configured
+dnl This provides the --with-llvmsrc and --with-llvmobj options
+LLVM_CONFIG_PROJECT($LLVM_SRC_ROOT,$LLVM_OBJ_ROOT)
+
+dnl Tell autoconf that the auxiliary files are actually located in
+dnl the LLVM autoconf directory, not here.
+AC_CONFIG_AUX_DIR($LLVM_SRC/autoconf)
+
+dnl Indicate that we require autoconf 2.59 or later. Ths is needed because we
+dnl use some autoconf macros only available in 2.59.
+AC_PREREQ(2.59)
+
+dnl Verify that the source directory is valid
+AC_CONFIG_SRCDIR(["lib/Analysis/ScopInfo.cpp"])
+
+dnl Configure a common Makefile
+AC_CONFIG_FILES(Makefile.config)
+AC_CONFIG_FILES(Makefile.common)
+
+dnl Configure project makefiles
+dnl List every Makefile that exists within your source tree
+
+dnl Quit if the source directory has already been configured.
+dnl NOTE: This relies upon undocumented autoconf behavior.
+if test ${srcdir} != "." ; then
+  if test -f ${srcdir}/include/polly/Config/config.h ; then
+    AC_MSG_ERROR([Already configured in ${srcdir}])
+  fi
+fi
+
+dnl **************************************************************************
+dnl * Determine which system we are building on
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Check for programs.
+dnl **************************************************************************
+
+dnl AC_PROG_CPP
+dnl AC_PROG_CC(gcc)
+dnl AC_PROG_CXX(g++)
+
+dnl **************************************************************************
+dnl * Check for libraries.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for header files.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for typedefs, structures, and compiler characteristics.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for library functions.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Enable various compile-time options
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Set the location of various third-party software packages
+dnl **************************************************************************
+dnl Find Gmp
+find_lib_and_headers([gmp], [gmp.h], [gmp])
+
+dnl Find Isl
+saved_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS"
+find_lib_and_headers([isl], [isl/val.h], [isl], [required])
+CXXFLAGS=$saved_CXXFLAGS
+
+dnl Check that we have libpluto.
+saved_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $gmp_inc $isl_inc"
+find_lib_and_headers([pluto], [pluto/libpluto.h], [pluto])
+CXXFLAGS=$saved_CXXFLAGS
+AS_IF([test "x$pluto_found" = "xyes"],
+  [AC_DEFINE([PLUTO_FOUND],[1],[Define if pluto found])])
+
+dnl Check if CUDA lib there
+dnl Disable the build of polly, even if it is checked out into tools/polly.
+AC_ARG_ENABLE(polly_gpu_codegen,
+              AS_HELP_STRING([--enable-polly-gpu-codegen],
+                             [Enable GPU code generation in Polly(default is NO)]),,
+                             enableval=default)
+case "$enableval" in
+  yes) AC_DEFINE([GPU_CODEGEN],[1], [Define if gpu codegen is enabled]) ;;
+  no) ;;
+  default) ;;
+  *) AC_MSG_ERROR([Invalid setting for --enable-polly-gpu-codegen. Use "yes" or "no"]) ;;
+esac
+
+find_lib_and_headers([cuda], [cuda.h], [cuda])
+
+AS_IF([test "x$cuda_found" = "xyes"],
+  [AC_DEFINE([CUDALIB_FOUND],[1],[Define if cudalib found])])
+
+dnl **************************************************************************
+dnl * Create the output files
+dnl **************************************************************************
+
+dnl This must be last
+AC_CONFIG_HEADERS(include/polly/Config/config.h)
+AC_OUTPUT
diff --git a/final/autoconf/configure.bak b/final/autoconf/configure.bak
new file mode 100644
index 0000000..f1cac90
--- /dev/null
+++ b/final/autoconf/configure.bak
@@ -0,0 +1,65 @@
+dnl **************************************************************************
+dnl * Initialize
+dnl **************************************************************************
+AC_INIT([Polly],[0.01],[etherzhhb@gmail.com grosser@fim.uni-passau.de ojomojo@gmail.com])
+
+dnl Identify where LLVM source tree is
+LLVM_SRC_ROOT="../.."
+LLVM_OBJ_ROOT="../.."
+dnl Tell autoconf that the auxiliary files are actually located in
+dnl the LLVM autoconf directory, not here.
+AC_CONFIG_AUX_DIR($LLVM_SRC_ROOT/autoconf)
+
+dnl Tell autoconf that this is an LLVM project being configured
+dnl This provides the --with-llvmsrc and --with-llvmobj options
+LLVM_CONFIG_PROJECT($LLVM_SRC_ROOT,$LLVM_OBJ_ROOT)
+
+dnl Verify that the source directory is valid
+AC_CONFIG_SRCDIR(["Makefile.common.in"])
+
+dnl Configure a common Makefile
+AC_CONFIG_FILES(Makefile.common)
+
+dnl Configure project makefiles
+dnl List every Makefile that exists within your source tree
+AC_CONFIG_MAKEFILE(Makefile)
+AC_CONFIG_MAKEFILE(lib/Makefile)
+
+dnl **************************************************************************
+dnl * Determine which system we are building on
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Check for programs.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Check for libraries.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for header files.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for typedefs, structures, and compiler characteristics.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for library functions.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Enable various compile-time options
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Set the location of various third-party software packages
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Create the output files
+dnl **************************************************************************
+
+dnl This must be last
+AC_OUTPUT
diff --git a/final/autoconf/m4/find_lib_and_headers.m4 b/final/autoconf/m4/find_lib_and_headers.m4
new file mode 100644
index 0000000..e872819
--- /dev/null
+++ b/final/autoconf/m4/find_lib_and_headers.m4
@@ -0,0 +1,47 @@
+dnl find_lib_and_headers(name, verify-header, library-name, requirded?)
+dnl Export
+dnl         name_inc in -I"include-path" form
+dnl         name_lib in -l"library-name" form
+dnl         name_ld  in -L"library-path" form
+dnl         name_found set to "yes" if found
+
+AC_DEFUN([find_lib_and_headers],
+[
+  AC_LANG_PUSH(C++)
+  OLD_CXXFLAGS=$CXXFLAGS;
+  OLD_LDFLAGS=$LDFLAGS;
+  OLD_LIBS=$LIBS;
+
+  LIBS="$LIBS -l$3";
+
+  # Get include path and lib path
+  AC_ARG_WITH([$1],
+    [AS_HELP_STRING([--with-$1], [prefix of $1 ])],
+      [given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
+       given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"],
+      [given_inc_path=inc_not_give_$1;
+       given_lib_path=lib_not_give_$1]
+    )
+  # Check for library and headers works
+  AC_MSG_CHECKING([for $1: $2 in $given_inc_path, and lib$3 in $given_lib_path])
+
+  # try to compile a file that includes a header of the library
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <$2>]], [[;]])],
+    [AC_MSG_RESULT([ok])
+    AC_SUBST([$1_found],["yes"])
+    AS_IF([test "x$given_inc_path" != "xinc_not_give_$1"],
+      [AC_SUBST([$1_inc],["-I$given_inc_path"])])
+    AC_SUBST([$1_lib],["-l$3"])
+    AS_IF([test "x$given_lib_path" != "xlib_not_give_$1"],
+      [AC_SUBST([$1_ld],["-L$given_lib_path"])])],
+    [AS_IF([test "x$4" = "xrequired"],
+      [AC_MSG_ERROR([$1 required but not found])],
+      [AC_MSG_RESULT([not found])])]
+  )
+
+  # reset original CXXFLAGS
+  CXXFLAGS=$OLD_CXXFLAGS
+  LDFLAGS=$OLD_LDFLAGS;
+  LIBS=$OLD_LIBS
+  AC_LANG_POP(C++)
+])
diff --git a/final/cmake/FindCUDA.cmake b/final/cmake/FindCUDA.cmake
new file mode 100644
index 0000000..37592f9
--- /dev/null
+++ b/final/cmake/FindCUDA.cmake
@@ -0,0 +1,23 @@
+IF (NOT CUDA_HEADER_PREFIX)
+  SET(CUDA_HEADER_PREFIX "/usr/local/cuda/include")
+ENDIF (NOT CUDA_HEADER_PREFIX)
+
+FIND_PATH(CUDALIB_INCLUDE_DIR
+  NAMES cuda.h
+  PATHS ${CUDA_HEADER_PREFIX})
+
+FIND_LIBRARY(CUDALIB_LIBRARY NAMES cuda)
+
+IF (CUDALIB_INCLUDE_DIR)
+  SET(CUDALIB_FOUND TRUE)
+ENDIF (CUDALIB_INCLUDE_DIR)
+
+IF (CUDALIB_FOUND)
+  IF (NOT CUDA_FIND_QUIETLY)
+    MESSAGE(STATUS "Found CUDA: ${CUDALIB_INCLUDE_DIR}")
+  ENDIF (NOT CUDA_FIND_QUIETLY)
+ELSE (CUDALIB_FOUND)
+  IF (CUDA_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find CUDA")
+  ENDIF (CUDA_FIND_REQUIRED)
+ENDIF (CUDALIB_FOUND)
diff --git a/final/cmake/FindGmp.cmake b/final/cmake/FindGmp.cmake
new file mode 100644
index 0000000..60def58
--- /dev/null
+++ b/final/cmake/FindGmp.cmake
@@ -0,0 +1,19 @@
+FIND_PATH(GMP_INCLUDE_DIR gmp.h)
+
+FIND_LIBRARY(GMP_LIBRARY NAMES gmp)
+
+IF (GMP_INCLUDE_DIR AND GMP_LIBRARY)
+  SET(GMP_FOUND TRUE)
+ENDIF (GMP_INCLUDE_DIR AND GMP_LIBRARY)
+
+
+IF (GMP_FOUND)
+  IF (NOT GMP_FIND_QUIETLY)
+    MESSAGE(STATUS "Found GMP: ${GMP_LIBRARY}")
+  ENDIF (NOT GMP_FIND_QUIETLY)
+ELSE (GMP_FOUND)
+  IF (GMP_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find GMP")
+  ENDIF (GMP_FIND_REQUIRED)
+ENDIF (GMP_FOUND)
+
diff --git a/final/cmake/FindIsl.cmake b/final/cmake/FindIsl.cmake
new file mode 100644
index 0000000..1c46e72
--- /dev/null
+++ b/final/cmake/FindIsl.cmake
@@ -0,0 +1,19 @@
+FIND_PATH(ISL_INCLUDE_DIR isl/val.h)
+
+FIND_LIBRARY(ISL_LIBRARY NAMES isl)
+
+IF (ISL_INCLUDE_DIR AND ISL_LIBRARY)
+  SET(ISL_FOUND TRUE)
+ENDIF (ISL_INCLUDE_DIR AND ISL_LIBRARY)
+
+
+IF (ISL_FOUND)
+  IF (NOT Isl_FIND_QUIETLY)
+    MESSAGE(STATUS "Found Isl: ${ISL_LIBRARY}")
+  ENDIF (NOT Isl_FIND_QUIETLY)
+ELSE (ISL_FOUND)
+  IF (Isl_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find Isl")
+  ENDIF (Isl_FIND_REQUIRED)
+ENDIF (ISL_FOUND)
+
diff --git a/final/cmake/FindPluto.cmake b/final/cmake/FindPluto.cmake
new file mode 100644
index 0000000..78d8563
--- /dev/null
+++ b/final/cmake/FindPluto.cmake
@@ -0,0 +1,19 @@
+FIND_PATH(PLUTO_INCLUDE_DIR pluto/libpluto.h)
+
+FIND_LIBRARY(PLUTO_LIBRARY NAMES pluto)
+
+IF (PLUTO_INCLUDE_DIR AND PLUTO_LIBRARY)
+  SET(PLUTO_FOUND TRUE)
+ENDIF (PLUTO_INCLUDE_DIR AND PLUTO_LIBRARY)
+
+
+IF (PLUTO_FOUND)
+  IF (NOT PLUTO_FIND_QUIETLY)
+    MESSAGE(STATUS "Found Pluto: ${PLUTO_LIBRARY}")
+  ENDIF (NOT PLUTO_FIND_QUIETLY)
+ELSE (PLUTO_FOUND)
+  IF (PLUTO_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find Pluto")
+  ENDIF (PLUTO_FIND_REQUIRED)
+ENDIF (PLUTO_FOUND)
+
diff --git a/final/cmake/polly_macros.cmake b/final/cmake/polly_macros.cmake
new file mode 100644
index 0000000..386eb64
--- /dev/null
+++ b/final/cmake/polly_macros.cmake
@@ -0,0 +1,73 @@
+
+macro(add_polly_library name)
+  set(srcs ${ARGN})
+  if(MSVC_IDE OR XCODE)
+    file( GLOB_RECURSE headers *.h *.td *.def)
+    set(srcs ${srcs} ${headers})
+    string( REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
+    list( GET split_path -1 dir)
+    file( GLOB_RECURSE headers
+      ../../include/polly${dir}/*.h)
+    set(srcs ${srcs} ${headers})
+  endif(MSVC_IDE OR XCODE)
+  if (MODULE)
+    set(libkind MODULE)
+  elseif (SHARED_LIBRARY)
+    set(libkind SHARED)
+  else()
+    set(libkind)
+  endif()
+  add_library( ${name} ${libkind} ${srcs} )
+  if( LLVM_COMMON_DEPENDS )
+    add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
+  endif( LLVM_COMMON_DEPENDS )
+  if( LLVM_USED_LIBS )
+    foreach(lib ${LLVM_USED_LIBS})
+      target_link_libraries( ${name} ${lib} )
+    endforeach(lib)
+  endif( LLVM_USED_LIBS )
+
+  if(POLLY_LINK_LIBS)
+    foreach(lib ${POLLY_LINK_LIBS})
+      target_link_libraries(${name} ${lib})
+    endforeach(lib)
+  endif(POLLY_LINK_LIBS)
+
+  if( LLVM_LINK_COMPONENTS )
+    llvm_config(${name} ${LLVM_LINK_COMPONENTS})
+  endif( LLVM_LINK_COMPONENTS )
+  if(MSVC)
+    get_target_property(cflag ${name} COMPILE_FLAGS)
+    if(NOT cflag)
+      set(cflag "")
+    endif(NOT cflag)
+    set(cflag "${cflag} /Za")
+    set_target_properties(${name} PROPERTIES COMPILE_FLAGS ${cflag})
+  endif(MSVC)
+  install(TARGETS ${name}
+    EXPORT LLVMExports
+    LIBRARY DESTINATION lib
+    ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
+  set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name})
+endmacro(add_polly_library)
+
+macro(add_polly_loadable_module name)
+  set(srcs ${ARGN})
+  # klduge: pass different values for MODULE with multiple targets in same dir
+  # this allows building shared-lib and module in same dir
+  # there must be a cleaner way to achieve this....
+  if (MODULE)
+  else()
+    set(GLOBAL_NOT_MODULE TRUE)
+  endif()
+  set(MODULE TRUE)
+  add_polly_library(${name} ${srcs})
+  if (GLOBAL_NOT_MODULE)
+    unset (MODULE)
+  endif()
+  if (APPLE)
+    # Darwin-specific linker flags for loadable modules.
+    set_target_properties(${name} PROPERTIES
+      LINK_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress")
+  endif()
+endmacro(add_polly_loadable_module)
diff --git a/final/configure b/final/configure
new file mode 100755
index 0000000..591ee39
--- /dev/null
+++ b/final/configure
@@ -0,0 +1,4051 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for Polly 0.01.
+#
+# Report bugs to <polly-dev@googlegroups.com>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: polly-dev@googlegroups.com about your system, including
+$0: any error possibly output before this message. Then
+$0: install a modern shell, or manually run the script
+$0: under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Polly'
+PACKAGE_TARNAME='polly'
+PACKAGE_VERSION='0.01'
+PACKAGE_STRING='Polly 0.01'
+PACKAGE_BUGREPORT='polly-dev@googlegroups.com'
+PACKAGE_URL=''
+
+ac_unique_file=""lib/Analysis/ScopInfo.cpp""
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+cuda_ld
+cuda_lib
+cuda_inc
+cuda_found
+pluto_ld
+pluto_lib
+pluto_inc
+pluto_found
+isl_ld
+isl_lib
+isl_inc
+isl_found
+gmp_ld
+gmp_lib
+gmp_inc
+gmp_found
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+LLVM_OBJ
+LLVM_SRC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_llvmsrc
+with_llvmobj
+with_gmp
+with_isl
+with_pluto
+enable_polly_gpu_codegen
+with_cuda
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures Polly 0.01 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/polly]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Polly 0.01:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-polly-gpu-codegen
+                          Enable GPU code generation in Polly(default is NO)
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-llvmsrc          Location of LLVM Source Code
+  --with-llvmobj          Location of LLVM Object Code
+  --with-gmp              prefix of gmp
+  --with-isl              prefix of isl
+  --with-pluto            prefix of pluto
+  --with-cuda             prefix of cuda
+
+Some influential environment variables:
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <polly-dev@googlegroups.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Polly configure 0.01
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Polly $as_me 0.01, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+LLVM_SRC_ROOT="`(cd $srcdir/../..; pwd)`"
+LLVM_OBJ_ROOT="`(cd ../..; pwd)`"
+
+
+# Check whether --with-llvmsrc was given.
+if test "${with_llvmsrc+set}" = set; then :
+  withval=$with_llvmsrc; llvm_src="$withval"
+else
+  llvm_src="$LLVM_SRC_ROOT"
+fi
+
+  LLVM_SRC=$llvm_src
+
+
+# Check whether --with-llvmobj was given.
+if test "${with_llvmobj+set}" = set; then :
+  withval=$with_llvmobj; llvm_obj="$withval"
+else
+  llvm_obj="$LLVM_OBJ_ROOT"
+fi
+
+  LLVM_OBJ=$llvm_obj
+
+  ac_config_commands="$ac_config_commands setup"
+
+
+
+ac_aux_dir=
+for ac_dir in $LLVM_SRC/autoconf "$srcdir"/$LLVM_SRC/autoconf; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in $LLVM_SRC/autoconf \"$srcdir\"/$LLVM_SRC/autoconf" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile.config"
+
+ac_config_files="$ac_config_files Makefile.common"
+
+
+
+if test ${srcdir} != "." ; then
+  if test -f ${srcdir}/include/polly/Config/config.h ; then
+    as_fn_error $? "Already configured in ${srcdir}" "$LINENO" 5
+  fi
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5
+$as_echo_n "checking whether the C++ compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C++ compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5
+$as_echo_n "checking for C++ compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+  OLD_CXXFLAGS=$CXXFLAGS;
+  OLD_LDFLAGS=$LDFLAGS;
+  OLD_LIBS=$LIBS;
+
+  LIBS="$LIBS -lgmp";
+
+  # Get include path and lib path
+
+# Check whether --with-gmp was given.
+if test "${with_gmp+set}" = set; then :
+  withval=$with_gmp; given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
+       given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"
+else
+  given_inc_path=inc_not_give_gmp;
+       given_lib_path=lib_not_give_gmp
+
+fi
+
+  # Check for library and headers works
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gmp: gmp.h in $given_inc_path, and libgmp in $given_lib_path" >&5
+$as_echo_n "checking for gmp: gmp.h in $given_inc_path, and libgmp in $given_lib_path... " >&6; }
+
+  # try to compile a file that includes a header of the library
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <gmp.h>
+int
+main ()
+{
+;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+    gmp_found="yes"
+
+    if test "x$given_inc_path" != "xinc_not_give_gmp"; then :
+  gmp_inc="-I$given_inc_path"
+
+fi
+    gmp_lib="-lgmp"
+
+    if test "x$given_lib_path" != "xlib_not_give_gmp"; then :
+  gmp_ld="-L$given_lib_path"
+
+fi
+else
+  if test "x" = "xrequired"; then :
+  as_fn_error $? "gmp required but not found" "$LINENO" 5
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+  # reset original CXXFLAGS
+  CXXFLAGS=$OLD_CXXFLAGS
+  LDFLAGS=$OLD_LDFLAGS;
+  LIBS=$OLD_LIBS
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+saved_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS"
+
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+  OLD_CXXFLAGS=$CXXFLAGS;
+  OLD_LDFLAGS=$LDFLAGS;
+  OLD_LIBS=$LIBS;
+
+  LIBS="$LIBS -lisl";
+
+  # Get include path and lib path
+
+# Check whether --with-isl was given.
+if test "${with_isl+set}" = set; then :
+  withval=$with_isl; given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
+       given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"
+else
+  given_inc_path=inc_not_give_isl;
+       given_lib_path=lib_not_give_isl
+
+fi
+
+  # Check for library and headers works
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for isl: isl/val.h in $given_inc_path, and libisl in $given_lib_path" >&5
+$as_echo_n "checking for isl: isl/val.h in $given_inc_path, and libisl in $given_lib_path... " >&6; }
+
+  # try to compile a file that includes a header of the library
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <isl/val.h>
+int
+main ()
+{
+;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+    isl_found="yes"
+
+    if test "x$given_inc_path" != "xinc_not_give_isl"; then :
+  isl_inc="-I$given_inc_path"
+
+fi
+    isl_lib="-lisl"
+
+    if test "x$given_lib_path" != "xlib_not_give_isl"; then :
+  isl_ld="-L$given_lib_path"
+
+fi
+else
+  if test "xrequired" = "xrequired"; then :
+  as_fn_error $? "isl required but not found" "$LINENO" 5
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+  # reset original CXXFLAGS
+  CXXFLAGS=$OLD_CXXFLAGS
+  LDFLAGS=$OLD_LDFLAGS;
+  LIBS=$OLD_LIBS
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+CXXFLAGS=$saved_CXXFLAGS
+CXXFLAGS="$CXXFLAGS $gmp_inc $isl_inc"
+
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+  OLD_CXXFLAGS=$CXXFLAGS;
+  OLD_LDFLAGS=$LDFLAGS;
+  OLD_LIBS=$LIBS;
+
+  LIBS="$LIBS -lpluto";
+
+  # Get include path and lib path
+
+# Check whether --with-pluto was given.
+if test "${with_pluto+set}" = set; then :
+  withval=$with_pluto; given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
+       given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"
+else
+  given_inc_path=inc_not_give_pluto;
+       given_lib_path=lib_not_give_pluto
+
+fi
+
+  # Check for library and headers works
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pluto: pluto/libpluto.h in $given_inc_path, and libpluto in $given_lib_path" >&5
+$as_echo_n "checking for pluto: pluto/libpluto.h in $given_inc_path, and libpluto in $given_lib_path... " >&6; }
+
+  # try to compile a file that includes a header of the library
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <pluto/libpluto.h>
+int
+main ()
+{
+;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+    pluto_found="yes"
+
+    if test "x$given_inc_path" != "xinc_not_give_pluto"; then :
+  pluto_inc="-I$given_inc_path"
+
+fi
+    pluto_lib="-lpluto"
+
+    if test "x$given_lib_path" != "xlib_not_give_pluto"; then :
+  pluto_ld="-L$given_lib_path"
+
+fi
+else
+  if test "x" = "xrequired"; then :
+  as_fn_error $? "pluto required but not found" "$LINENO" 5
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+  # reset original CXXFLAGS
+  CXXFLAGS=$OLD_CXXFLAGS
+  LDFLAGS=$OLD_LDFLAGS;
+  LIBS=$OLD_LIBS
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+CXXFLAGS=$saved_CXXFLAGS
+if test "x$pluto_found" = "xyes"; then :
+
+$as_echo "#define PLUTO_FOUND 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-polly_gpu_codegen was given.
+if test "${enable_polly_gpu_codegen+set}" = set; then :
+  enableval=$enable_polly_gpu_codegen;
+else
+  enableval=default
+fi
+
+case "$enableval" in
+  yes)
+$as_echo "#define GPU_CODEGEN 1" >>confdefs.h
+ ;;
+  no) ;;
+  default) ;;
+  *) as_fn_error $? "Invalid setting for --enable-polly-gpu-codegen. Use \"yes\" or \"no\"" "$LINENO" 5 ;;
+esac
+
+
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+  OLD_CXXFLAGS=$CXXFLAGS;
+  OLD_LDFLAGS=$LDFLAGS;
+  OLD_LIBS=$LIBS;
+
+  LIBS="$LIBS -lcuda";
+
+  # Get include path and lib path
+
+# Check whether --with-cuda was given.
+if test "${with_cuda+set}" = set; then :
+  withval=$with_cuda; given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
+       given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"
+else
+  given_inc_path=inc_not_give_cuda;
+       given_lib_path=lib_not_give_cuda
+
+fi
+
+  # Check for library and headers works
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cuda: cuda.h in $given_inc_path, and libcuda in $given_lib_path" >&5
+$as_echo_n "checking for cuda: cuda.h in $given_inc_path, and libcuda in $given_lib_path... " >&6; }
+
+  # try to compile a file that includes a header of the library
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <cuda.h>
+int
+main ()
+{
+;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+    cuda_found="yes"
+
+    if test "x$given_inc_path" != "xinc_not_give_cuda"; then :
+  cuda_inc="-I$given_inc_path"
+
+fi
+    cuda_lib="-lcuda"
+
+    if test "x$given_lib_path" != "xlib_not_give_cuda"; then :
+  cuda_ld="-L$given_lib_path"
+
+fi
+else
+  if test "x" = "xrequired"; then :
+  as_fn_error $? "cuda required but not found" "$LINENO" 5
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+  # reset original CXXFLAGS
+  CXXFLAGS=$OLD_CXXFLAGS
+  LDFLAGS=$OLD_LDFLAGS;
+  LIBS=$OLD_LIBS
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+if test "x$cuda_found" = "xyes"; then :
+
+$as_echo "#define CUDALIB_FOUND 1" >>confdefs.h
+
+fi
+
+
+ac_config_headers="$ac_config_headers include/polly/Config/config.h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Polly $as_me 0.01, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <polly-dev@googlegroups.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+Polly config.status 0.01
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+llvm_src="${LLVM_SRC}"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;;
+    "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;;
+    "Makefile.common") CONFIG_FILES="$CONFIG_FILES Makefile.common" ;;
+    "include/polly/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/polly/Config/config.h" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/final/include/CMakeLists.txt b/final/include/CMakeLists.txt
new file mode 100644
index 0000000..abe73d1
--- /dev/null
+++ b/final/include/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(polly)
diff --git a/final/include/polly/CMakeLists.txt b/final/include/polly/CMakeLists.txt
new file mode 100644
index 0000000..ef92163
--- /dev/null
+++ b/final/include/polly/CMakeLists.txt
@@ -0,0 +1,9 @@
+if( MSVC_IDE OR XCODE )
+  # Creates a dummy target containing all headers for the benefit of
+  # Visual Studio users.
+  file(GLOB_RECURSE headers *.h)
+  add_library(polly_headers_do_not_build EXCLUDE_FROM_ALL
+    # We need at least one source file:
+    ${POLLY_SOURCE_DIR}/lib/Support/GICHelper.cpp
+    ${headers})
+endif()
diff --git a/final/include/polly/Canonicalization.h b/final/include/polly/Canonicalization.h
new file mode 100644
index 0000000..c69bf13
--- /dev/null
+++ b/final/include/polly/Canonicalization.h
@@ -0,0 +1,27 @@
+//===--- Canonicalization.h - Set of canonicalization passes ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_CANONICALIZATION_H
+#define POLLY_CANONICALIZATION_H
+
+#include "llvm/PassManager.h"
+
+namespace polly {
+
+/// @brief Schedule a set of canonicalization passes to prepare for Polly
+///
+/// The set of optimization passes was partially taken/copied from the
+/// set of default optimization passes in LLVM. It is used to bring the code
+/// into a canonical form that simplifies the analysis and optimization passes
+/// of Polly. The set of optimization passes scheduled here is probably not yet
+/// optimal. TODO: Optimize the set of canonicalization passes.
+void registerCanonicalicationPasses(llvm::PassManagerBase &PM);
+}
+
+#endif
diff --git a/final/include/polly/CodeGen/BlockGenerators.h b/final/include/polly/CodeGen/BlockGenerators.h
new file mode 100644
index 0000000..cb56898
--- /dev/null
+++ b/final/include/polly/CodeGen/BlockGenerators.h
@@ -0,0 +1,332 @@
+//===-BlockGenerators.h - Helper to generate code for statements-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the BlockGenerator and VectorBlockGenerator classes, which
+// generate sequential code and vectorized code for a polyhedral statement,
+// respectively.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_BLOCK_GENERATORS_H
+#define POLLY_BLOCK_GENERATORS_H
+
+#include "polly/CodeGen/IRBuilder.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+
+#include "isl/map.h"
+
+#include <vector>
+
+struct isl_ast_build;
+
+namespace llvm {
+class Pass;
+class Region;
+class ScalarEvolution;
+}
+
+namespace polly {
+using namespace llvm;
+class ScopStmt;
+class MemoryAccess;
+class IslExprBuilder;
+
+typedef DenseMap<const Value *, Value *> ValueMapT;
+typedef std::vector<ValueMapT> VectorValueMapT;
+
+/// @brief Check whether an instruction can be synthesized by the code
+///        generator.
+///
+/// Some instructions will be recalculated only from information that is code
+/// generated from the polyhedral representation. For such instructions we do
+/// not need to ensure that their operands are available during code generation.
+///
+/// @param I The instruction to check.
+/// @param LI The LoopInfo analysis.
+/// @param SE The scalar evolution database.
+/// @param R The region out of which SSA names are parameters.
+/// @return If the instruction I can be regenerated from its
+///         scalar evolution representation, return true,
+///         otherwise return false.
+bool canSynthesize(const llvm::Instruction *I, const llvm::LoopInfo *LI,
+                   llvm::ScalarEvolution *SE, const llvm::Region *R);
+
+/// @brief Generate a new basic block for a polyhedral statement.
+///
+/// The only public function exposed is generate().
+class BlockGenerator {
+public:
+  /// @brief Generate a new BasicBlock for a ScopStmt.
+  ///
+  /// @param Builder   The LLVM-IR Builder used to generate the statement. The
+  ///                  code is generated at the location, the Builder points to.
+  /// @param Stmt      The statement to code generate.
+  /// @param GlobalMap A map that defines for certain Values referenced from the
+  ///                  original code new Values they should be replaced with.
+  /// @param P         A reference to the pass this function is called from.
+  ///                  The pass is needed to update other analysis.
+  /// @param LI        The loop info for the current function
+  /// @param SE        The scalar evolution info for the current function
+  /// @param Build       The AST build with the new schedule.
+  /// @param ExprBuilder An expression builder to generate new access functions.
+  static void generate(PollyIRBuilder &Builder, ScopStmt &Stmt,
+                       ValueMapT &GlobalMap, LoopToScevMapT &LTS, Pass *P,
+                       LoopInfo &LI, ScalarEvolution &SE,
+                       __isl_keep isl_ast_build *Build = nullptr,
+                       IslExprBuilder *ExprBuilder = nullptr) {
+    BlockGenerator Generator(Builder, Stmt, P, LI, SE, Build, ExprBuilder);
+    Generator.copyBB(GlobalMap, LTS);
+  }
+
+protected:
+  PollyIRBuilder &Builder;
+  ScopStmt &Statement;
+  Pass *P;
+  LoopInfo &LI;
+  ScalarEvolution &SE;
+  isl_ast_build *Build;
+  IslExprBuilder *ExprBuilder;
+
+  BlockGenerator(PollyIRBuilder &B, ScopStmt &Stmt, Pass *P, LoopInfo &LI,
+                 ScalarEvolution &SE, __isl_keep isl_ast_build *Build,
+                 IslExprBuilder *ExprBuilder);
+
+  /// @brief Get the new version of a value.
+  ///
+  /// Given an old value, we first check if a new version of this value is
+  /// available in the BBMap or GlobalMap. In case it is not and the value can
+  /// be recomputed using SCEV, we do so. If we can not recompute a value
+  /// using SCEV, but we understand that the value is constant within the scop,
+  /// we return the old value.  If the value can still not be derived, this
+  /// function will assert.
+  ///
+  /// @param Old       The old Value.
+  /// @param BBMap     A mapping from old values to their new values
+  ///                  (for values recalculated within this basic block).
+  /// @param GlobalMap A mapping from old values to their new values
+  ///                  (for values recalculated in the new ScoP, but not
+  ///                   within this basic block).
+  /// @param LTS       A mapping from loops virtual canonical induction
+  ///                  variable to their new values
+  ///                  (for values recalculated in the new ScoP, but not
+  ///                   within this basic block).
+  /// @param L         The loop that surrounded the instruction that referenced
+  ///                  this value in the original code. This loop is used to
+  ///                  evaluate the scalar evolution at the right scope.
+  ///
+  /// @returns  o The old value, if it is still valid.
+  ///           o The new value, if available.
+  ///           o NULL, if no value is found.
+  Value *getNewValue(const Value *Old, ValueMapT &BBMap, ValueMapT &GlobalMap,
+                     LoopToScevMapT &LTS, Loop *L) const;
+
+  void copyInstScalar(const Instruction *Inst, ValueMapT &BBMap,
+                      ValueMapT &GlobalMap, LoopToScevMapT &LTS);
+
+  /// @brief Get the innermost loop that surrounds an instruction.
+  ///
+  /// @param Inst The instruction for which we get the loop.
+  /// @return The innermost loop that surrounds the instruction.
+  Loop *getLoopForInst(const Instruction *Inst);
+
+  /// @brief Get the new operand address according to access relation of @p MA.
+  Value *getNewAccessOperand(const MemoryAccess &MA);
+
+  /// @brief Generate the operand address
+  Value *generateLocationAccessed(const Instruction *Inst, const Value *Pointer,
+                                  ValueMapT &BBMap, ValueMapT &GlobalMap,
+                                  LoopToScevMapT &LTS);
+
+  Value *generateScalarLoad(const LoadInst *load, ValueMapT &BBMap,
+                            ValueMapT &GlobalMap, LoopToScevMapT &LTS);
+
+  Value *generateScalarStore(const StoreInst *store, ValueMapT &BBMap,
+                             ValueMapT &GlobalMap, LoopToScevMapT &LTS);
+
+  /// @brief Copy a single Instruction.
+  ///
+  /// This copies a single Instruction and updates references to old values
+  /// with references to new values, as defined by GlobalMap and BBMap.
+  ///
+  /// @param BBMap     A mapping from old values to their new values
+  ///                  (for values recalculated within this basic block).
+  /// @param GlobalMap A mapping from old values to their new values
+  ///                  (for values recalculated in the new ScoP, but not
+  ///                  within this basic block).
+  void copyInstruction(const Instruction *Inst, ValueMapT &BBMap,
+                       ValueMapT &GlobalMap, LoopToScevMapT &LTS);
+
+  /// @brief Copy the basic block.
+  ///
+  /// This copies the entire basic block and updates references to old values
+  /// with references to new values, as defined by GlobalMap.
+  ///
+  /// @param GlobalMap A mapping from old values to their new values
+  ///                  (for values recalculated in the new ScoP, but not
+  ///                  within this basic block).
+  void copyBB(ValueMapT &GlobalMap, LoopToScevMapT &LTS);
+};
+
+/// @brief Generate a new vector basic block for a polyhedral statement.
+///
+/// The only public function exposed is generate().
+class VectorBlockGenerator : BlockGenerator {
+public:
+  /// @brief Generate a new vector basic block for a ScoPStmt.
+  ///
+  /// This code generation is similar to the normal, scalar code generation,
+  /// except that each instruction is code generated for several vector lanes
+  /// at a time. If possible instructions are issued as actual vector
+  /// instructions, but e.g. for address calculation instructions we currently
+  /// generate scalar instructions for each vector lane.
+  ///
+  /// @param Stmt       The statement to code generate.
+  /// @param GlobalMaps A vector of maps that define for certain Values
+  ///                   referenced from the original code new Values they should
+  ///                   be replaced with. Each map in the vector of maps is
+  ///                   used for one vector lane. The number of elements in the
+  ///                   vector defines the width of the generated vector
+  ///                   instructions.
+  /// @param Schedule   A map from the statement to a schedule where the
+  ///                   innermost dimension is the dimension of the innermost
+  ///                   loop containing the statemenet.
+  /// @param P          A reference to the pass this function is called from.
+  ///                   The pass is needed to update other analysis.
+  /// @param LI        The loop info for the current function
+  /// @param SE        The scalar evolution info for the current function
+  /// @param Build       The AST build with the new schedule.
+  /// @param ExprBuilder An expression builder to generate new access functions.
+  static void generate(PollyIRBuilder &B, ScopStmt &Stmt,
+                       VectorValueMapT &GlobalMaps,
+                       std::vector<LoopToScevMapT> &VLTS,
+                       __isl_keep isl_map *Schedule, Pass *P, LoopInfo &LI,
+                       ScalarEvolution &SE,
+                       __isl_keep isl_ast_build *Build = nullptr,
+                       IslExprBuilder *ExprBuilder = nullptr) {
+    VectorBlockGenerator Generator(B, GlobalMaps, VLTS, Stmt, Schedule, P, LI,
+                                   SE, Build, ExprBuilder);
+    Generator.copyBB();
+  }
+
+private:
+  // This is a vector of global value maps.  The first map is used for the first
+  // vector lane, ...
+  // Each map, contains information about Instructions in the old ScoP, which
+  // are recalculated in the new SCoP. When copying the basic block, we replace
+  // all referenes to the old instructions with their recalculated values.
+  VectorValueMapT &GlobalMaps;
+
+  // This is a vector of loop->scev maps.  The first map is used for the first
+  // vector lane, ...
+  // Each map, contains information about Instructions in the old ScoP, which
+  // are recalculated in the new SCoP. When copying the basic block, we replace
+  // all referenes to the old instructions with their recalculated values.
+  //
+  // For example, when the code generator produces this AST:
+  //
+  //   for (int c1 = 0; c1 <= 1023; c1 += 1)
+  //     for (int c2 = 0; c2 <= 1023; c2 += VF)
+  //       for (int lane = 0; lane <= VF; lane += 1)
+  //         Stmt(c2 + lane + 3, c1);
+  //
+  // VLTS[lane] contains a map:
+  //   "outer loop in the old loop nest" -> SCEV("c2 + lane + 3"),
+  //   "inner loop in the old loop nest" -> SCEV("c1").
+  std::vector<LoopToScevMapT> &VLTS;
+
+  // A map from the statement to a schedule where the innermost dimension is the
+  // dimension of the innermost loop containing the statemenet.
+  isl_map *Schedule;
+
+  VectorBlockGenerator(PollyIRBuilder &B, VectorValueMapT &GlobalMaps,
+                       std::vector<LoopToScevMapT> &VLTS, ScopStmt &Stmt,
+                       __isl_keep isl_map *Schedule, Pass *P, LoopInfo &LI,
+                       ScalarEvolution &SE,
+                       __isl_keep isl_ast_build *Build = nullptr,
+                       IslExprBuilder *ExprBuilder = nullptr);
+
+  int getVectorWidth();
+
+  Value *getVectorValue(const Value *Old, ValueMapT &VectorMap,
+                        VectorValueMapT &ScalarMaps, Loop *L);
+
+  Type *getVectorPtrTy(const Value *V, int Width);
+
+  /// @brief Load a vector from a set of adjacent scalars
+  ///
+  /// In case a set of scalars is known to be next to each other in memory,
+  /// create a vector load that loads those scalars
+  ///
+  /// %vector_ptr= bitcast double* %p to <4 x double>*
+  /// %vec_full = load <4 x double>* %vector_ptr
+  ///
+  /// @param NegativeStride This is used to indicate a -1 stride. In such
+  ///                       a case we load the end of a base address and
+  ///                       shuffle the accesses in reverse order into the
+  ///                       vector. By default we would do only positive
+  ///                       strides.
+  ///
+  Value *generateStrideOneLoad(const LoadInst *Load,
+                               VectorValueMapT &ScalarMaps,
+                               bool NegativeStride);
+
+  /// @brief Load a vector initialized from a single scalar in memory
+  ///
+  /// In case all elements of a vector are initialized to the same
+  /// scalar value, this value is loaded and shuffeled into all elements
+  /// of the vector.
+  ///
+  /// %splat_one = load <1 x double>* %p
+  /// %splat = shufflevector <1 x double> %splat_one, <1 x
+  ///       double> %splat_one, <4 x i32> zeroinitializer
+  ///
+  Value *generateStrideZeroLoad(const LoadInst *Load, ValueMapT &BBMap);
+
+  /// @brief Load a vector from scalars distributed in memory
+  ///
+  /// In case some scalars a distributed randomly in memory. Create a vector
+  /// by loading each scalar and by inserting one after the other into the
+  /// vector.
+  ///
+  /// %scalar_1= load double* %p_1
+  /// %vec_1 = insertelement <2 x double> undef, double %scalar_1, i32 0
+  /// %scalar 2 = load double* %p_2
+  /// %vec_2 = insertelement <2 x double> %vec_1, double %scalar_1, i32 1
+  ///
+  Value *generateUnknownStrideLoad(const LoadInst *Load,
+                                   VectorValueMapT &ScalarMaps);
+
+  void generateLoad(const LoadInst *Load, ValueMapT &VectorMap,
+                    VectorValueMapT &ScalarMaps);
+
+  void copyUnaryInst(const UnaryInstruction *Inst, ValueMapT &VectorMap,
+                     VectorValueMapT &ScalarMaps);
+
+  void copyBinaryInst(const BinaryOperator *Inst, ValueMapT &VectorMap,
+                      VectorValueMapT &ScalarMaps);
+
+  void copyStore(const StoreInst *Store, ValueMapT &VectorMap,
+                 VectorValueMapT &ScalarMaps);
+
+  void copyInstScalarized(const Instruction *Inst, ValueMapT &VectorMap,
+                          VectorValueMapT &ScalarMaps);
+
+  bool extractScalarValues(const Instruction *Inst, ValueMapT &VectorMap,
+                           VectorValueMapT &ScalarMaps);
+
+  bool hasVectorOperands(const Instruction *Inst, ValueMapT &VectorMap);
+
+  void copyInstruction(const Instruction *Inst, ValueMapT &VectorMap,
+                       VectorValueMapT &ScalarMaps);
+
+  void copyBB();
+};
+}
+#endif
diff --git a/final/include/polly/CodeGen/CodeGeneration.h b/final/include/polly/CodeGen/CodeGeneration.h
new file mode 100644
index 0000000..f87c396
--- /dev/null
+++ b/final/include/polly/CodeGen/CodeGeneration.h
@@ -0,0 +1,79 @@
+//===------ polly/CodeGeneration.h - The Polly code generator *- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_CODEGENERATION_H
+#define POLLY_CODEGENERATION_H
+
+#include "polly/Config/config.h"
+
+#include "isl/set.h"
+#include "isl/map.h"
+
+namespace polly {
+enum VectorizerChoice {
+  VECTORIZER_NONE,
+  VECTORIZER_POLLY,
+  VECTORIZER_UNROLL_ONLY,
+  VECTORIZER_FIRST_NEED_GROUPED_UNROLL = VECTORIZER_UNROLL_ONLY,
+  VECTORIZER_BB
+};
+extern VectorizerChoice PollyVectorizerChoice;
+
+enum CodeGenChoice { CODEGEN_ISL, CODEGEN_NONE };
+extern CodeGenChoice PollyCodeGenChoice;
+
+/// @brief Flag to turn on/off annotation of alias scopes.
+extern bool PollyAnnotateAliasScopes;
+
+static inline int getNumberOfIterations(__isl_take isl_set *Domain) {
+  int Dim = isl_set_dim(Domain, isl_dim_set);
+
+  // Calculate a map similar to the identity map, but with the last input
+  // and output dimension not related.
+  //  [i0, i1, i2, i3] -> [i0, i1, i2, o0]
+  isl_space *Space = isl_set_get_space(Domain);
+  Space = isl_space_drop_dims(Space, isl_dim_out, Dim - 1, 1);
+  Space = isl_space_map_from_set(Space);
+  isl_map *Identity = isl_map_identity(Space);
+  Identity = isl_map_add_dims(Identity, isl_dim_in, 1);
+  Identity = isl_map_add_dims(Identity, isl_dim_out, 1);
+
+  Domain = isl_set_reset_tuple_id(Domain);
+
+  isl_map *Map =
+      isl_map_from_domain_and_range(isl_set_copy(Domain), isl_set_copy(Domain));
+  isl_set_free(Domain);
+  Map = isl_map_intersect(Map, Identity);
+
+  isl_map *LexMax = isl_map_lexmax(isl_map_copy(Map));
+  isl_map *LexMin = isl_map_lexmin(Map);
+  isl_map *Sub = isl_map_sum(LexMax, isl_map_neg(LexMin));
+
+  isl_set *Elements = isl_map_range(Sub);
+
+  if (!isl_set_is_singleton(Elements)) {
+    isl_set_free(Elements);
+    return -1;
+  }
+
+  isl_point *P = isl_set_sample_point(Elements);
+
+  isl_val *V;
+  V = isl_point_get_coordinate_val(P, isl_dim_set, Dim - 1);
+  int NumberIterations = isl_val_get_num_si(V);
+  isl_val_free(V);
+  isl_point_free(P);
+
+  return NumberIterations;
+}
+}
+
+#endif // POLLY_CODEGENERATION_H
diff --git a/final/include/polly/CodeGen/IRBuilder.h b/final/include/polly/CodeGen/IRBuilder.h
new file mode 100644
index 0000000..fb56d8a
--- /dev/null
+++ b/final/include/polly/CodeGen/IRBuilder.h
@@ -0,0 +1,123 @@
+//===- Codegen/IRBuilder.h - The IR builder used by Polly -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
+// that are used e.g. to emit the llvm.loop.parallel metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_CODEGEN_IRBUILDER_H
+#define POLLY_CODEGEN_IRBUILDER_H
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/Analysis/LoopInfo.h"
+
+namespace llvm {
+class ScalarEvolution;
+}
+
+namespace polly {
+class Scop;
+
+/// @brief Helper class to annotate newly generated SCoPs with metadata.
+///
+/// The annotations are twofold:
+///   1) Loops are stored in a stack-like structure in the order they are
+///      constructed and the LoopID metadata node is added to the backedge.
+///      Contained memory instructions and loop headers are annotated according
+///      to all parallel surrounding loops.
+///   2) The new SCoP is assumed alias free (either due to the result of
+///      AliasAnalysis queries or runtime alias checks). We annotate therefore
+///      all memory instruction with alias scopes to indicate that fact to
+///      later optimizations.
+///      These alias scopes live in a new alias domain only used in this SCoP.
+///      Each base pointer has its own alias scope and is annotated to not
+///      alias with any access to different base pointers.
+class ScopAnnotator {
+public:
+  ScopAnnotator();
+
+  /// @brief Build all alias scopes for the given SCoP.
+  void buildAliasScopes(Scop &S);
+
+  /// @brief Add a new loop @p L which is parallel if @p IsParallel is true.
+  void pushLoop(llvm::Loop *L, bool IsParallel);
+
+  /// @brief Remove the last added loop.
+  void popLoop(bool isParallel);
+
+  /// @brief Annotate the new instruction @p I for all parallel loops.
+  void annotate(llvm::Instruction *I);
+
+  /// @brief Annotate the loop latch @p B wrt. @p L.
+  void annotateLoopLatch(llvm::BranchInst *B, llvm::Loop *L,
+                         bool IsParallel) const;
+
+private:
+  /// @brief The ScalarEvolution analysis we use to find base pointers.
+  llvm::ScalarEvolution *SE;
+
+  /// @brief All loops currently under construction.
+  llvm::SmallVector<llvm::Loop *, 8> ActiveLoops;
+
+  /// @brief Metadata pointing to parallel loops currently under construction.
+  llvm::SmallVector<llvm::MDNode *, 8> ParallelLoops;
+
+  /// @brief The alias scope domain for the current SCoP.
+  llvm::MDNode *AliasScopeDomain;
+
+  /// @brief A map from base pointers to its alias scope.
+  llvm::DenseMap<llvm::Value *, llvm::MDNode *> AliasScopeMap;
+
+  /// @brief A map from base pointers to an alias scope list of other pointers.
+  llvm::DenseMap<llvm::Value *, llvm::MDNode *> OtherAliasScopeListMap;
+};
+
+/// @brief Add Polly specifics when running IRBuilder.
+///
+/// This is used to add additional items such as e.g. the llvm.loop.parallel
+/// metadata.
+template <bool PreserveNames>
+class PollyBuilderInserter
+    : protected llvm::IRBuilderDefaultInserter<PreserveNames> {
+public:
+  PollyBuilderInserter() : Annotator(0) {}
+  PollyBuilderInserter(class ScopAnnotator &A) : Annotator(&A) {}
+
+protected:
+  void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
+                    llvm::BasicBlock *BB,
+                    llvm::BasicBlock::iterator InsertPt) const {
+    llvm::IRBuilderDefaultInserter<PreserveNames>::InsertHelper(I, Name, BB,
+                                                                InsertPt);
+    if (Annotator)
+      Annotator->annotate(I);
+  }
+
+private:
+  class ScopAnnotator *Annotator;
+};
+
+// TODO: We should not name instructions in NDEBUG builds.
+//
+// We currently always name instructions, as the polly test suite currently
+// matches for certain names.
+typedef PollyBuilderInserter<true> IRInserter;
+typedef llvm::IRBuilder<true, llvm::ConstantFolder, IRInserter> PollyIRBuilder;
+
+/// @brief Return an IR builder pointed before the @p BB terminator.
+static inline PollyIRBuilder createPollyIRBuilder(llvm::BasicBlock *BB,
+                                                  ScopAnnotator &LA) {
+  PollyIRBuilder Builder(BB->getContext(), llvm::ConstantFolder(),
+                         polly::IRInserter(LA));
+  Builder.SetInsertPoint(BB->getTerminator());
+  return Builder;
+}
+}
+#endif
diff --git a/final/include/polly/CodeGen/IslAst.h b/final/include/polly/CodeGen/IslAst.h
new file mode 100644
index 0000000..dfd949f
--- /dev/null
+++ b/final/include/polly/CodeGen/IslAst.h
@@ -0,0 +1,156 @@
+//===- IslAst.h - Interface to the isl code generator-------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The isl code generator interface takes a Scop and generates a isl_ast. This
+// ist_ast can either be returned directly or it can be pretty printed to
+// stdout.
+//
+// A typical isl_ast output looks like this:
+//
+// for (c2 = max(0, ceild(n + m, 2); c2 <= min(511, floord(5 * n, 3)); c2++) {
+//   bb2(c2);
+// }
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_ISL_AST_H
+#define POLLY_ISL_AST_H
+
+#include "polly/Config/config.h"
+#include "polly/ScopPass.h"
+
+#include "isl/ast.h"
+
+namespace llvm {
+class raw_ostream;
+}
+
+struct isl_ast_node;
+struct isl_ast_expr;
+struct isl_ast_build;
+struct isl_union_map;
+struct isl_pw_multi_aff;
+
+namespace polly {
+class Scop;
+class IslAst;
+class MemoryAccess;
+
+class IslAstInfo : public ScopPass {
+public:
+  using MemoryAccessSet = SmallPtrSet<MemoryAccess *, 4>;
+
+  /// @brief Payload information used to annotate an AST node.
+  struct IslAstUserPayload {
+    /// @brief Construct and initialize the payload.
+    IslAstUserPayload()
+        : IsInnermost(false), IsInnermostParallel(false),
+          IsOutermostParallel(false), IsReductionParallel(false),
+          MinimalDependenceDistance(nullptr), Build(nullptr) {}
+
+    /// @brief Cleanup all isl structs on destruction.
+    ~IslAstUserPayload();
+
+    /// @brief Flag to mark innermost loops.
+    bool IsInnermost;
+
+    /// @brief Flag to mark innermost parallel loops.
+    bool IsInnermostParallel;
+
+    /// @brief Flag to mark outermost parallel loops.
+    bool IsOutermostParallel;
+
+    /// @brief Flag to mark parallel loops which break reductions.
+    bool IsReductionParallel;
+
+    /// @brief The minimal dependence distance for non parallel loops.
+    isl_pw_aff *MinimalDependenceDistance;
+
+    /// @brief The build environment at the time this node was constructed.
+    isl_ast_build *Build;
+
+    /// @brief Set of accesses which break reduction dependences.
+    MemoryAccessSet BrokenReductions;
+  };
+
+private:
+  Scop *S;
+  IslAst *Ast;
+
+public:
+  static char ID;
+  IslAstInfo() : ScopPass(ID), S(nullptr), Ast(nullptr) {}
+
+  /// @brief Build the AST for the given SCoP @p S.
+  bool runOnScop(Scop &S);
+
+  /// @brief Print a source code representation of the program.
+  void printScop(llvm::raw_ostream &OS) const;
+
+  /// @brief Return a copy of the AST root node.
+  __isl_give isl_ast_node *getAst() const;
+
+  /// @brief Get the run condition.
+  ///
+  /// Only if the run condition evaluates at run-time to a non-zero value, the
+  /// assumptions that have been taken hold. If the run condition evaluates to
+  /// zero/false some assumptions do not hold and the original code needs to
+  /// be executed.
+  __isl_give isl_ast_expr *getRunCondition() const;
+
+  /// @name Extract information attached to an isl ast (for) node.
+  ///
+  ///{
+
+  /// @brief Get the complete payload attached to @p Node.
+  static IslAstUserPayload *getNodePayload(__isl_keep isl_ast_node *Node);
+
+  /// @brief Is this loop an innermost loop?
+  static bool isInnermost(__isl_keep isl_ast_node *Node);
+
+  /// @brief Is this loop a parallel loop?
+  static bool isParallel(__isl_keep isl_ast_node *Node);
+
+  /// @brief Is this loop an outermost parallel loop?
+  static bool isOutermostParallel(__isl_keep isl_ast_node *Node);
+
+  /// @brief Is this loop an innermost parallel loop?
+  static bool isInnermostParallel(__isl_keep isl_ast_node *Node);
+
+  /// @brief Is this loop a reduction parallel loop?
+  static bool isReductionParallel(__isl_keep isl_ast_node *Node);
+
+  /// @brief Will the loop be run as thread parallel?
+  static bool isExecutedInParallel(__isl_keep isl_ast_node *Node);
+
+  /// @brief Get the nodes schedule or a nullptr if not available.
+  static __isl_give isl_union_map *getSchedule(__isl_keep isl_ast_node *Node);
+
+  /// @brief Get minimal dependence distance or nullptr if not available.
+  static __isl_give isl_pw_aff *
+  getMinimalDependenceDistance(__isl_keep isl_ast_node *Node);
+
+  /// @brief Get the nodes broken reductions or a nullptr if not available.
+  static MemoryAccessSet *getBrokenReductions(__isl_keep isl_ast_node *Node);
+
+  /// @brief Get the nodes build context or a nullptr if not available.
+  static __isl_give isl_ast_build *getBuild(__isl_keep isl_ast_node *Node);
+
+  ///}
+
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual void releaseMemory();
+};
+}
+
+namespace llvm {
+class PassRegistry;
+void initializeIslAstInfoPass(llvm::PassRegistry &);
+}
+#endif /* POLLY_ISL_AST_H */
diff --git a/final/include/polly/CodeGen/IslExprBuilder.h b/final/include/polly/CodeGen/IslExprBuilder.h
new file mode 100644
index 0000000..74b1a09
--- /dev/null
+++ b/final/include/polly/CodeGen/IslExprBuilder.h
@@ -0,0 +1,148 @@
+//===-IslExprBuilder.h - Helper to generate code for isl AST expressions --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_ISL_EXPR_BUILDER_H
+#define POLLY_ISL_EXPR_BUILDER_H
+
+#include "polly/CodeGen/IRBuilder.h"
+
+#include "llvm/ADT/MapVector.h"
+
+#include "isl/ast.h"
+
+namespace llvm {
+class SCEVExpander;
+}
+
+namespace polly {
+
+/// @brief LLVM-IR generator for isl_ast_expr[essions]
+///
+/// This generator generates LLVM-IR that performs the computation described by
+/// an isl_ast_expr[ession].
+///
+/// Example:
+///
+///   An isl_ast_expr[ession] can look like this:
+///
+///     (N + M) + 10
+///
+///   The IslExprBuilder could create the following LLVM-IR:
+///
+///     %tmp1 = add nsw i64 %N
+///     %tmp2 = add nsw i64 %tmp1, %M
+///     %tmp3 = add nsw i64 %tmp2, 10
+///
+/// The implementation of this class is mostly a mapping from isl_ast_expr
+/// constructs to the corresponding LLVM-IR constructs.
+///
+/// The following decisions may need some explanation:
+///
+/// 1) Which data-type to choose
+///
+/// isl_ast_expr[essions] are untyped expressions that assume arbitrary
+/// precision integer computations. LLVM-IR instead has fixed size integers.
+/// When lowering to LLVM-IR we need to chose both the size of the data type and
+/// the sign of the operations we use.
+///
+/// At the moment, we hardcode i64 bit signed computations. Our experience has
+/// shown that 64 bit are generally large enough for the loop bounds that appear
+/// in the wild. Signed computations are needed, as loop bounds may become
+/// negative.
+///
+/// FIXME: Hardcoding sizes can cause issues:
+///
+///   a) Certain run-time checks that we may want to generate can involve the
+///      size of the data types the computation is performed on. When code
+///      generating these run-time checks to isl_ast_expr[essions], the
+///      resulting computation may require more than 64 bit.
+///
+///   b) On embedded systems and especially for high-level-synthesis 64 bit
+///      computations are very costly.
+///
+///   The right approach is to compute the minimal necessary bitwidth and
+///   signedness for each subexpression during in the isl AST generation and
+///   to use this information in our IslAstGenerator. Preliminary patches are
+///   available, but have not been committed yet.
+///
+/// 2) We always flag computations with 'nsw'
+///
+/// As isl_ast_expr[essions] assume arbitrary precision, no wrapping should
+/// ever occur in the generated LLVM-IR (assuming the data type chosen is large
+/// enough).
+class IslExprBuilder {
+public:
+  /// @brief A map from isl_ids to llvm::Values.
+  typedef llvm::MapVector<isl_id *, llvm::Value *> IDToValueTy;
+
+  /// @brief Construct an IslExprBuilder.
+  ///
+  /// @param Builder The IRBuilder used to construct the isl_ast_expr[ession].
+  ///                The insert location of this IRBuilder defines WHERE the
+  ///                corresponding LLVM-IR is generated.
+  ///
+  /// @param IDToValue The isl_ast_expr[ession] may reference parameters or
+  ///                  variables (identified by an isl_id). The IDTOValue map
+  ///                  specifies the LLVM-IR Values that correspond to these
+  ///                  parameters and variables.
+  /// @param Expander  A SCEVExpander to create the indices for multi
+  ///                  dimensional accesses.
+  IslExprBuilder(PollyIRBuilder &Builder, IDToValueTy &IDToValue,
+                 llvm::SCEVExpander &Expander)
+      : Builder(Builder), IDToValue(IDToValue), Expander(Expander) {}
+
+  /// @brief Create LLVM-IR for an isl_ast_expr[ession].
+  ///
+  /// @param Expr The ast expression for which we generate LLVM-IR.
+  ///
+  /// @return The llvm::Value* containing the result of the computation.
+  llvm::Value *create(__isl_take isl_ast_expr *Expr);
+
+  /// @brief Return the largest of two types.
+  ///
+  /// @param T1 The first type.
+  /// @param T2 The second type.
+  ///
+  /// @return The largest of the two types.
+  llvm::Type *getWidestType(llvm::Type *T1, llvm::Type *T2);
+
+  /// @brief Return the type with which this expression should be computed.
+  ///
+  /// The type needs to be large enough to hold all possible input and all
+  /// possible output values.
+  ///
+  /// @param Expr The expression for which to find the type.
+  /// @return The type with which the expression should be computed.
+  llvm::IntegerType *getType(__isl_keep isl_ast_expr *Expr);
+
+private:
+  PollyIRBuilder &Builder;
+  IDToValueTy &IDToValue;
+
+  /// @brief A SCEVExpander to translate dimension sizes to llvm values.
+  llvm::SCEVExpander &Expander;
+
+  llvm::Value *createOp(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpUnary(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpAccess(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpBin(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpNAry(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpSelect(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpICmp(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpBoolean(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createId(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createInt(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createOpAddressOf(__isl_take isl_ast_expr *Expr);
+  llvm::Value *createAccessAddress(__isl_take isl_ast_expr *Expr);
+};
+}
+
+#endif
diff --git a/final/include/polly/CodeGen/LoopGenerators.h b/final/include/polly/CodeGen/LoopGenerators.h
new file mode 100644
index 0000000..db48f7e
--- /dev/null
+++ b/final/include/polly/CodeGen/LoopGenerators.h
@@ -0,0 +1,214 @@
+//===- LoopGenerators.h - IR helper to create loops -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions to create scalar and OpenMP parallel loops
+// as LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLLY_LOOP_GENERATORS_H
+#define POLLY_LOOP_GENERATORS_H
+
+#include "polly/CodeGen/IRBuilder.h"
+
+#include "llvm/IR/ValueMap.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace llvm {
+class Value;
+class Pass;
+class BasicBlock;
+}
+
+namespace polly {
+using namespace llvm;
+
+/// @brief Create a scalar do/for-style loop.
+///
+/// @param LowerBound The starting value of the induction variable.
+/// @param UpperBound The upper bound of the induction variable.
+/// @param Stride     The value by which the induction variable is incremented.
+///
+/// @param Builder    The builder used to create the loop.
+/// @param P          A pointer to the pass that uses this function. It is used
+///                   to update analysis information.
+/// @param LI         The loop info for the current function
+/// @param DT         The dominator tree we need to update
+/// @param ExitBlock  The block the loop will exit to.
+/// @param Predicate  The predicate used to generate the upper loop bound.
+/// @param Annotator  This function can (optionally) take a ScopAnnotator which
+///                   annotates loops and alias information in the SCoP.
+/// @param Parallel   If this loop should be marked parallel in the Annotator.
+/// @param UseGuard   Create a guard in front of the header to check if the
+///                   loop is executed at least once, otherwise just assume it.
+///
+/// @return Value*    The newly created induction variable for this loop.
+Value *createLoop(Value *LowerBound, Value *UpperBound, Value *Stride,
+                  PollyIRBuilder &Builder, Pass *P, LoopInfo &LI,
+                  DominatorTree &DT, BasicBlock *&ExitBlock,
+                  ICmpInst::Predicate Predicate,
+                  ScopAnnotator *Annotator = NULL, bool Parallel = false,
+                  bool UseGuard = true);
+
+/// @brief The ParallelLoopGenerator allows to create parallelized loops
+///
+/// To parallelize a loop, we perform the following steps:
+///   o  Generate a subfunction which will hold the loop body.
+///   o  Create a struct to hold all outer values needed in the loop body.
+///   o  Create calls to a runtime library to achieve the actual parallelism.
+///      These calls will spawn and join threads, define how the work (here the
+///      iterations) are distributed between them and make sure each has access
+///      to the struct holding all needed values.
+///
+/// At the moment we support only one parallel runtime, OpenMP.
+///
+/// If we parallelize the outer loop of the following loop nest,
+///
+///   S0;
+///   for (int i = 0; i < N; i++)
+///     for (int j = 0; j < M; j++)
+///       S1(i, j);
+///   S2;
+///
+/// we will generate the following code (with different runtime function names):
+///
+///   S0;
+///   auto *values = storeValuesIntoStruct();
+///   // Execute subfunction with multiple threads
+///   spawn_threads(subfunction, values);
+///   join_threads();
+///   S2;
+///
+///  // This function is executed in parallel by different threads
+///   void subfunction(values) {
+///     while (auto *WorkItem = getWorkItem()) {
+///       int LB = WorkItem.begin();
+///       int UB = WorkItem.end();
+///       for (int i = LB; i < UB; i++)
+///         for (int j = 0; j < M; j++)
+///           S1(i, j);
+///     }
+///     cleanup_thread();
+///   }
+class ParallelLoopGenerator {
+public:
+  using ValueToValueMapTy = llvm::ValueMap<Value *, Value *>;
+
+  /// @brief Create a parallel loop generator for the current function.
+  ParallelLoopGenerator(PollyIRBuilder &Builder, Pass *P, LoopInfo &LI,
+                        DominatorTree &DT, const DataLayout &DL)
+      : Builder(Builder), P(P), LI(LI), DT(DT), DL(DL),
+        LongType(
+            Type::getIntNTy(Builder.getContext(), DL.getPointerSizeInBits())),
+        M(Builder.GetInsertBlock()->getParent()->getParent()) {}
+
+  /// @brief Create a parallel loop
+  ///
+  ///
+  /// @param LB        The lower bound for the loop we parallelize.
+  /// @param UB        The upper bound for the loop we parallelize.
+  /// @param Stride    The stride of the loop we parallelize.
+  /// @param Values    A set of LLVM-IR Values that should be available in
+  ///                  the new loop body.
+  /// @param VMap      A map to allow outside access to the new versions of
+  ///                  the values in @p Values.
+  /// @param LoopBody  A pointer to an iterator that is set to point to the
+  ///                  body of the created loop. It should be used to insert
+  ///                  instructions that form the actual loop body.
+  ///
+  /// @return The newly created induction variable for this loop.
+  Value *createParallelLoop(Value *LB, Value *UB, Value *Stride,
+                            SetVector<Value *> &Values, ValueToValueMapTy &VMap,
+                            BasicBlock::iterator *LoopBody);
+
+private:
+  /// @brief The IR builder we use to create instructions.
+  PollyIRBuilder &Builder;
+
+  /// @brief A pass pointer to update analysis information.
+  Pass *P;
+
+  /// @brief The loop info of the current function we need to update.
+  LoopInfo &LI;
+
+  /// @brief The dominance tree of the current function we need to update.
+  DominatorTree &DT;
+
+  /// @brief The target layout to get the right size for types.
+  const DataLayout &DL;
+
+  /// @brief The type of a "long" on this hardware used for backend calls.
+  Type *LongType;
+
+  /// @brief The current module
+  Module *M;
+
+  /// @brief Create a runtime library call to spawn the worker threads.
+  ///
+  /// @param SubFn      The subfunction which holds the loop body.
+  /// @param SubFnParam The parameter for the subfunction (basically the struct
+  ///                   filled with the outside values).
+  /// @param LB         The lower bound for the loop we parallelize.
+  /// @param UB         The upper bound for the loop we parallelize.
+  /// @param Stride     The stride of the loop we parallelize.
+  void createCallSpawnThreads(Value *SubFn, Value *SubFnParam, Value *LB,
+                              Value *UB, Value *Stride);
+
+  /// @brief Create a runtime library call to join the worker threads.
+  void createCallJoinThreads();
+
+  /// @brief Create a runtime library call to get the next work item.
+  ///
+  /// @param LBPtr A pointer value to store the work item begin in.
+  /// @param UBPtr A pointer value to store the work item end in.
+  ///
+  /// @returns A true value if the work item is not empty.
+  Value *createCallGetWorkItem(Value *LBPtr, Value *UBPtr);
+
+  /// @brief Create a runtime library call to allow cleanup of the thread.
+  ///
+  /// @note This function is called right before the thread will exit the
+  ///       subfunction and only if the runtime system depends depends on it.
+  void createCallCleanupThread();
+
+  /// @brief Create a struct for all @p Values and store them in there.
+  ///
+  /// @param Values The values which should be stored in the struct.
+  ///
+  /// @return The created struct.
+  Value *storeValuesIntoStruct(SetVector<Value *> &Values);
+
+  /// @brief Extract all values from the @p Struct and construct the mapping.
+  ///
+  /// @param Values The values which were stored in the struct.
+  /// @param Struct The struct holding all the values in @p Values.
+  /// @param VMap   A map to associate every element of @p Values with the
+  ///               new llvm value loaded from the @p Struct.
+  void extractValuesFromStruct(SetVector<Value *> Values, Value *Struct,
+                               ValueToValueMapTy &VMap);
+
+  /// @brief Create the definition of the parallel subfunction.
+  Function *createSubFnDefinition();
+
+  /// @brief Create the parallel subfunction.
+  ///
+  /// @param Stride The induction variable increment.
+  /// @param Struct A struct holding all values in @p Values.
+  /// @param Values A set of LLVM-IR Values that should be available in
+  ///               the new loop body.
+  /// @param VMap   A map to allow outside access to the new versions of
+  ///               the values in @p Values.
+  /// @param SubFn  The newly created subfunction is returned here.
+  ///
+  /// @return The newly created induction variable.
+  Value *createSubFn(Value *Stride, Value *Struct,
+                     SetVector<Value *> UsedValues, ValueToValueMapTy &VMap,
+                     Function **SubFn);
+};
+} // end namespace polly
+#endif
diff --git a/final/include/polly/CodeGen/PTXGenerator.h b/final/include/polly/CodeGen/PTXGenerator.h
new file mode 100644
index 0000000..f4c5038
--- /dev/null
+++ b/final/include/polly/CodeGen/PTXGenerator.h
@@ -0,0 +1,184 @@
+//===- PTXGenerator.h - IR helper to create GPGPU LLVM-IR -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions to create GPGPU parallel loops as LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLLY_CODEGEN_PTXGENERATOR_H
+#define POLLY_CODEGEN_PTXGENERATOR_H
+
+#include "polly/Config/config.h"
+
+#ifdef GPU_CODEGEN
+#include "polly/CodeGen/IRBuilder.h"
+#include "llvm/ADT/SetVector.h"
+
+#include <map>
+
+namespace llvm {
+class Value;
+class Pass;
+class BasicBlock;
+}
+
+namespace polly {
+using namespace llvm;
+
+class PTXGenerator {
+public:
+  typedef std::map<Value *, Value *> ValueToValueMapTy;
+
+  PTXGenerator(PollyIRBuilder &Builder, Pass *P, const std::string &Triple);
+
+  /// @brief Create a GPGPU parallel loop.
+  ///
+  /// @param UsedValues   A set of LLVM-IR Values that should be available to
+  ///                     the new loop body.
+  /// @param OriginalIVS  The new values of the original induction variables.
+  /// @param VMap         This map is filled by createParallelLoop(). It
+  ///                     maps the values in UsedValues to Values through which
+  ///                     their content is available within the loop body.
+  /// @param LoopBody     A pointer to an iterator that is set to point to the
+  ///                     body of the created loop. It should be used to insert
+  ///                     instructions that form the actual loop body.
+  void startGeneration(SetVector<Value *> &UsedValues,
+                       SetVector<Value *> &OriginalIVS, ValueToValueMapTy &VMap,
+                       BasicBlock::iterator *LoopBody);
+
+  /// @brief Execute the post-operations to build a GPGPU parallel loop.
+  ///
+  void finishGeneration(Function *SubFunction);
+
+  /// @brief Set the parameters for launching PTX kernel.
+  ///
+  /// @param GridW    A value of the width of a GPU grid.
+  /// @param GridH    A value of the height of a GPU grid.
+  /// @param BlockW   A value of the width of a GPU block.
+  /// @param BlockH   A value of the height of a GPU block.
+  void setLaunchingParameters(int GridW, int GridH, int BlockW, int BlockH) {
+    GridWidth = GridW;
+    GridHeight = GridH;
+    BlockWidth = BlockW;
+    BlockHeight = BlockH;
+  }
+
+  /// @brief Set the size of the output array.
+  ///
+  /// This size is used to allocate memory on the device and the host.
+  ///
+  /// @param Bytes        Output array size in bytes.
+  void setOutputBytes(unsigned Bytes) { OutputBytes = Bytes; }
+
+private:
+  PollyIRBuilder &Builder;
+  Pass *P;
+
+  /// @brief The target triple of the device.
+  const std::string &GPUTriple;
+
+  ///@brief Parameters used for launching PTX kernel.
+  int GridWidth, GridHeight, BlockWidth, BlockHeight;
+
+  /// @brief Size of the output array in bytes.
+  unsigned OutputBytes;
+
+  /// @brief Polly's GPU data types.
+  StructType *ContextTy, *ModuleTy, *KernelTy, *DeviceTy, *DevDataTy, *EventTy;
+
+  void InitializeGPUDataTypes();
+  IntegerType *getInt64Type();           // i64
+  PointerType *getI8PtrType();           // char *
+  PointerType *getPtrI8PtrType();        // char **
+  PointerType *getFloatPtrType();        // float *
+  PointerType *getGPUContextPtrType();   // %struct.PollyGPUContextT *
+  PointerType *getGPUModulePtrType();    // %struct.PollyGPUModuleT *
+  PointerType *getGPUDevicePtrType();    // %struct.PollyGPUDeviceT *
+  PointerType *getPtrGPUDevicePtrType(); // %struct.PollyGPUDevicePtrT *
+  PointerType *getGPUFunctionPtrType();  // %struct.PollyGPUFunctionT *
+  PointerType *getGPUEventPtrType();     // %struct.PollyGPUEventT *
+
+  Module *getModule();
+
+  /// @brief Create the kernel string containing LLVM IR.
+  ///
+  /// @param SubFunction  A pointer to the device code function.
+  /// @return             A global string variable containing the LLVM IR codes
+  //                      of the SubFunction.
+  Value *createPTXKernelFunction(Function *SubFunction);
+
+  /// @brief Get the entry name of the device kernel function.
+  ///
+  /// @param SubFunction  A pointer to the device code function.
+  /// @return             A global string variable containing the entry name of
+  ///                     the SubFunction.
+  Value *getPTXKernelEntryName(Function *SubFunction);
+
+  void createCallInitDevice(Value *Context, Value *Device);
+  void createCallGetPTXModule(Value *Buffer, Value *Module);
+  void createCallGetPTXKernelEntry(Value *Entry, Value *Module, Value *Kernel);
+  void createCallAllocateMemoryForHostAndDevice(Value *HostData,
+                                                Value *DeviceData, Value *Size);
+  void createCallCopyFromHostToDevice(Value *DeviceData, Value *HostData,
+                                      Value *Size);
+  void createCallCopyFromDeviceToHost(Value *HostData, Value *DeviceData,
+                                      Value *Size);
+  void createCallSetKernelParameters(Value *Kernel, Value *BlockWidth,
+                                     Value *BlockHeight, Value *DeviceData);
+  void createCallLaunchKernel(Value *Kernel, Value *GridWidth,
+                              Value *GridHeight);
+  void createCallStartTimerByCudaEvent(Value *StartEvent, Value *StopEvent);
+  void createCallStopTimerByCudaEvent(Value *StartEvent, Value *StopEvent,
+                                      Value *Timer);
+  void createCallCleanupGPGPUResources(Value *HostData, Value *DeviceData,
+                                       Value *Module, Value *Context,
+                                       Value *Kernel);
+
+  /// @brief Create the CUDA subfunction.
+  ///
+  /// @param UsedValues   A set of LLVM-IR Values that should be available to
+  ///                     the new loop body.
+  /// @param VMap         This map that is filled by createSubfunction(). It
+  ///                     maps the values in UsedValues to Values through which
+  ///                     their content is available within the loop body.
+  /// @param OriginalIVS  The new values of the original induction variables.
+  /// @param SubFunction  The newly created SubFunction is returned here.
+  void createSubfunction(SetVector<Value *> &UsedValues,
+                         SetVector<Value *> &OriginalIVS,
+                         ValueToValueMapTy &VMap, Function **SubFunction);
+
+  /// @brief Create the definition of the CUDA subfunction.
+  ///
+  /// @param NumArgs      The number of parameters of this subfunction. This is
+  ///                     usually set to the number of memory accesses which
+  ///                     will be copied from host to device.
+  Function *createSubfunctionDefinition(int NumArgs);
+
+  /// @brief Get the Value of CUDA block width.
+  Value *getCUDABlockWidth();
+
+  /// @brief Get the Value of CUDA block height.
+  Value *getCUDABlockHeight();
+
+  /// @brief Get the Value of CUDA Gird width.
+  Value *getCUDAGridWidth();
+
+  /// @brief Get the Value of CUDA grid height.
+  Value *getCUDAGridHeight();
+
+  /// @brief Get the Value of the bytes of the output array.
+  Value *getOutputArraySizeInBytes();
+
+  /// @brief Erase the ptx-related subfunctions and declarations.
+  ///
+  /// @param SubFunction  A pointer to the device code function.
+  void eraseUnusedFunctions(Function *SubFunction);
+};
+} // end namespace polly
+#endif /* GPU_CODEGEN */
+#endif /* POLLY_CODEGEN_PTXGENERATOR_H */
diff --git a/final/include/polly/CodeGen/RuntimeDebugBuilder.h b/final/include/polly/CodeGen/RuntimeDebugBuilder.h
new file mode 100644
index 0000000..5d8d4c6
--- /dev/null
+++ b/final/include/polly/CodeGen/RuntimeDebugBuilder.h
@@ -0,0 +1,59 @@
+//===--- RuntimeDebugBuilder.h --- Helper to insert prints into LLVM-IR ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RUNTIME_DEBUG_BUILDER_H
+#define RUNTIME_DEBUG_BUILDER_H
+
+#include "polly/CodeGen/IRBuilder.h"
+
+#include <string>
+
+namespace llvm {
+class Value;
+class Function;
+}
+
+namespace polly {
+
+/// @brief Insert function calls that print certain LLVM values at run time.
+///
+/// This class inserts libc function calls to print certain LLVM values at
+/// run time.
+struct RuntimeDebugBuilder {
+
+  /// @brief Print a string to stdout.
+  ///
+  /// @param String The string to print.
+  static void createStrPrinter(PollyIRBuilder &Builder,
+                               const std::string &String);
+
+  /// @brief Print a value to stdout.
+  ///
+  /// @param V The value to print.
+  ///
+  /// @note Only integer, floating point and pointer values up to 64bit are
+  ///       supported.
+  static void createValuePrinter(PollyIRBuilder &Builder, llvm::Value *V);
+
+  /// @brief Add a call to the fflush function with no file pointer given.
+  ///
+  /// This call will flush all opened file pointers including stdout and stderr.
+  static void createFlush(PollyIRBuilder &Builder);
+
+  /// @brief Get a reference to the 'printf' function.
+  ///
+  /// If the current module does not yet contain a reference to printf, we
+  /// insert a reference to it. Otherwise the existing reference is returned.
+  static llvm::Function *getPrintF(PollyIRBuilder &Builder);
+};
+}
+
+#endif
diff --git a/final/include/polly/CodeGen/Utils.h b/final/include/polly/CodeGen/Utils.h
new file mode 100644
index 0000000..0752aa3
--- /dev/null
+++ b/final/include/polly/CodeGen/Utils.h
@@ -0,0 +1,61 @@
+//===- Utils.h - Utility functions for code generation ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions for the code generation.
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_CODEGEN_UTILS_H
+#define POLLY_CODEGEN_UTILS_H
+
+namespace llvm {
+class Pass;
+class Value;
+class BasicBlock;
+}
+
+namespace polly {
+
+class Scop;
+
+/// @brief Execute a Scop conditionally wrt @p RTC.
+///
+/// In the CFG the optimized code of the Scop is generated next to the
+/// original code. Both the new and the original version of the code remain
+/// in the CFG. A branch statement decides which version is executed based on
+/// the runtime value of @p RTC.
+///
+/// Before transformation:
+///
+///                        bb0
+///                         |
+///                     orig_scop
+///                         |
+///                        bb1
+///
+/// After transformation:
+///                        bb0
+///                         |
+///                  polly.splitBlock
+///                     /       \.
+///                     |     startBlock
+///                     |        |
+///               orig_scop   new_scop
+///                     \      /
+///                      \    /
+///                        bb1 (joinBlock)
+///
+/// @param S   The Scop to execute conditionally.
+/// @param P   A reference to the pass calling this function.
+/// @param RTC The runtime condition checked before executing the new SCoP.
+///
+/// @return The 'StartBlock' to which new code can be added.
+llvm::BasicBlock *executeScopConditionally(Scop &S, llvm::Pass *P,
+                                           llvm::Value *RTC);
+}
+#endif
diff --git a/final/include/polly/Config/config.h.cmake b/final/include/polly/Config/config.h.cmake
new file mode 100644
index 0000000..ea58925
--- /dev/null
+++ b/final/include/polly/Config/config.h.cmake
@@ -0,0 +1,22 @@
+//===- polly/Config.h ------------ Configuration of Polly -------*- C++ -*-===//
+//
+//                      The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Configuration of Polly.
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLLY_CONFIG_H
+#define POLLY_CONFIG_H
+
+#cmakedefine CLOOG_FOUND
+#cmakedefine PLUTO_FOUND
+#cmakedefine SCOPLIB_FOUND
+#cmakedefine CUDALIB_FOUND
+#cmakedefine GPU_CODEGEN
+
+#endif
diff --git a/final/include/polly/Config/config.h.in b/final/include/polly/Config/config.h.in
new file mode 100644
index 0000000..295e10a
--- /dev/null
+++ b/final/include/polly/Config/config.h.in
@@ -0,0 +1,28 @@
+/* include/polly/Config/config.h.in.  Generated from autoconf/configure.ac by autoheader.  */
+
+/* Define if cudalib found */
+#undef CUDALIB_FOUND
+
+/* Define if gpu codegen is enabled */
+#undef GPU_CODEGEN
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if pluto found */
+#undef PLUTO_FOUND
diff --git a/final/include/polly/Dependences.h b/final/include/polly/Dependences.h
new file mode 100644
index 0000000..df03d2c
--- /dev/null
+++ b/final/include/polly/Dependences.h
@@ -0,0 +1,171 @@
+//===------ polly/Dependences.h - Polyhedral dependency analysis *- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Calculate the data dependency relations for a Scop using ISL.
+//
+// The integer set library (ISL) from Sven, has a integrated dependency analysis
+// to calculate data dependences. This pass takes advantage of this and
+// calculate those dependences a Scop.
+//
+// The dependences in this pass are exact in terms that for a specific read
+// statement instance only the last write statement instance is returned. In
+// case of may writes a set of possible write instances is returned. This
+// analysis will never produce redundant dependences.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_DEPENDENCES_H
+#define POLLY_DEPENDENCES_H
+
+#include "polly/ScopPass.h"
+
+#include <map>
+#include "isl/ctx.h"
+
+struct isl_pw_aff;
+struct isl_union_map;
+struct isl_union_set;
+struct isl_map;
+struct isl_set;
+struct clast_for;
+
+using namespace llvm;
+
+namespace polly {
+
+class Scop;
+class ScopStmt;
+class MemoryAccess;
+
+class Dependences : public ScopPass {
+public:
+  static char ID;
+
+  /// @brief The type of the dependences.
+  ///
+  /// Reduction dependences are separated from RAW/WAW/WAR dependences because
+  /// we can ignore them during the scheduling. This is the case since the order
+  /// in which the reduction statements are executed does not matter. However,
+  /// if they are executed in parallel we need to take additional measures
+  /// (e.g, privatization) to ensure a correct result. The (reverse) transitive
+  /// closure of the reduction dependences are used to check for parallel
+  /// executed reduction statements during code generation. These dependences
+  /// connect all instances of a reduction with each other, they are therefor
+  /// cyclic and possibly "reversed".
+  enum Type {
+    // Write after read
+    TYPE_WAR = 1 << 0,
+
+    // Read after write
+    TYPE_RAW = 1 << 1,
+
+    // Write after write
+    TYPE_WAW = 1 << 2,
+
+    // Reduction dependences
+    TYPE_RED = 1 << 3,
+
+    // Transitive closure of the reduction dependences (& the reverse)
+    TYPE_TC_RED = 1 << 4,
+  };
+
+  typedef std::map<ScopStmt *, isl_map *> StatementToIslMapTy;
+
+  Dependences();
+
+  /// @brief Check if a new scattering is valid.
+  ///
+  /// @param NewScattering The new scatterings
+  ///
+  /// @return bool True if the new scattering is valid, false it it reverses
+  ///              dependences.
+  bool isValidScattering(StatementToIslMapTy *NewScatterings);
+
+  /// @brief Check if a partial schedule is parallel wrt to @p Deps.
+  ///
+  /// @param Schedule       The subset of the scattering space that we want to
+  ///                       check.
+  /// @param Deps           The dependences @p Schedule needs to respect.
+  /// @param MinDistancePtr If not nullptr, the minimal dependence distance will
+  ///                       be returned at the address of that pointer
+  ///
+  /// @return Returns true, if executing parallel the outermost dimension of
+  ///         @p Schedule is valid according to the dependences @p Deps.
+  bool isParallel(__isl_keep isl_union_map *Schedule,
+                  __isl_take isl_union_map *Deps,
+                  __isl_give isl_pw_aff **MinDistancePtr = nullptr);
+
+  /// @brief Get the dependences in this Scop.
+  ///
+  /// @param Kinds This integer defines the different kinds of dependences
+  ///              that will be returned. To return more than one kind, the
+  ///              different kinds are 'ored' together.
+  isl_union_map *getDependences(int Kinds);
+
+  /// @brief Report if valid dependences are available.
+  bool hasValidDependences();
+
+  /// @brief Return the reduction dependences caused by @p MA.
+  ///
+  /// @return The reduction dependences caused by @p MA or nullptr if None.
+  __isl_give isl_map *getReductionDependences(MemoryAccess *MA);
+
+  /// @brief Return the reduction dependences mapped by the causing @p MA.
+  const DenseMap<MemoryAccess *, isl_map *> &getReductionDependences() const {
+    return ReductionDependences;
+  }
+
+  /// @brief Recompute dependences from schedule and memory accesses.
+  void recomputeDependences();
+
+  bool runOnScop(Scop &S);
+  void printScop(raw_ostream &OS) const;
+  virtual void releaseMemory();
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+
+private:
+  Scop *S;
+
+  /// @brief The different kinds of dependences we calculate.
+  isl_union_map *RAW;
+  isl_union_map *WAR;
+  isl_union_map *WAW;
+
+  /// @brief The map of reduction dependences
+  isl_union_map *RED = nullptr;
+
+  /// @brief The (reverse) transitive closure of reduction dependences
+  isl_union_map *TC_RED = nullptr;
+
+  /// @brief Map from memory accesses to their reduction dependences.
+  DenseMap<MemoryAccess *, isl_map *> ReductionDependences;
+
+  /// @brief Collect information about the SCoP.
+  void collectInfo(Scop &S, isl_union_map **Read, isl_union_map **Write,
+                   isl_union_map **MayWrite, isl_union_map **AccessSchedule,
+                   isl_union_map **StmtSchedule);
+
+  /// @brief Calculate and add at the privatization dependences
+  void addPrivatizationDependences();
+
+  /// @brief Calculate the dependences for a certain SCoP.
+  void calculateDependences(Scop &S);
+
+  /// @brief Set the reduction dependences for @p MA to @p Deps.
+  void setReductionDependences(MemoryAccess *MA, __isl_take isl_map *Deps);
+};
+
+} // End polly namespace.
+
+namespace llvm {
+class PassRegistry;
+void initializeDependencesPass(llvm::PassRegistry &);
+}
+
+#endif
diff --git a/final/include/polly/LinkAllPasses.h b/final/include/polly/LinkAllPasses.h
new file mode 100644
index 0000000..3853b55
--- /dev/null
+++ b/final/include/polly/LinkAllPasses.h
@@ -0,0 +1,104 @@
+//===- polly/LinkAllPasses.h ----------- Reference All Passes ---*- C++ -*-===//
+//
+//                      The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file pulls in all transformation and analysis passes for tools
+// like opt and bugpoint that need this functionality.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_LINKALLPASSES_H
+#define POLLY_LINKALLPASSES_H
+
+#include "polly/Config/config.h"
+#include <cstdlib>
+
+namespace llvm {
+class Pass;
+class PassInfo;
+class PassRegistry;
+class RegionPass;
+}
+
+namespace polly {
+llvm::Pass *createCodePreparationPass();
+llvm::Pass *createDeadCodeElimPass();
+llvm::Pass *createDependencesPass();
+llvm::Pass *createDOTOnlyPrinterPass();
+llvm::Pass *createDOTOnlyViewerPass();
+llvm::Pass *createDOTPrinterPass();
+llvm::Pass *createDOTViewerPass();
+llvm::Pass *createIndependentBlocksPass();
+llvm::Pass *createJSONExporterPass();
+llvm::Pass *createJSONImporterPass();
+#ifdef PLUTO_FOUND
+llvm::Pass *createPlutoOptimizerPass();
+#endif
+llvm::Pass *createPollyCanonicalizePass();
+llvm::Pass *createScopDetectionPass();
+llvm::Pass *createScopInfoPass();
+llvm::Pass *createIslAstInfoPass();
+llvm::Pass *createIslCodeGenerationPass();
+llvm::Pass *createIslScheduleOptimizerPass();
+llvm::Pass *createTempScopInfoPass();
+
+extern char &IndependentBlocksID;
+extern char &CodePreparationID;
+}
+
+namespace {
+struct PollyForcePassLinking {
+  PollyForcePassLinking() {
+    // We must reference the passes in such a way that compilers will not
+    // delete it all as dead code, even with whole program optimization,
+    // yet is effectively a NO-OP. As the compiler isn't smart enough
+    // to know that getenv() never returns -1, this will do the job.
+    if (std::getenv("bar") != (char *)-1)
+      return;
+
+    polly::createCodePreparationPass();
+    polly::createDeadCodeElimPass();
+    polly::createDependencesPass();
+    polly::createDOTOnlyPrinterPass();
+    polly::createDOTOnlyViewerPass();
+    polly::createDOTPrinterPass();
+    polly::createDOTViewerPass();
+    polly::createIndependentBlocksPass();
+    polly::createJSONExporterPass();
+    polly::createJSONImporterPass();
+    polly::createScopDetectionPass();
+    polly::createScopInfoPass();
+#ifdef PLUTO_FOUND
+    polly::createPlutoOptimizerPass();
+#endif
+    polly::createPollyCanonicalizePass();
+    polly::createIslAstInfoPass();
+    polly::createIslCodeGenerationPass();
+    polly::createIslScheduleOptimizerPass();
+    polly::createTempScopInfoPass();
+  }
+} PollyForcePassLinking; // Force link by creating a global definition.
+}
+
+namespace llvm {
+class PassRegistry;
+void initializeCodePreparationPass(llvm::PassRegistry &);
+void initializeDeadCodeElimPass(llvm::PassRegistry &);
+void initializeIndependentBlocksPass(llvm::PassRegistry &);
+void initializeJSONExporterPass(llvm::PassRegistry &);
+void initializeJSONImporterPass(llvm::PassRegistry &);
+void initializeIslAstInfoPass(llvm::PassRegistry &);
+void initializeIslCodeGenerationPass(llvm::PassRegistry &);
+void initializeIslScheduleOptimizerPass(llvm::PassRegistry &);
+#ifdef PLUTO_FOUND
+void initializePlutoOptimizerPass(llvm::PassRegistry &);
+#endif
+void initializePollyCanonicalizePass(llvm::PassRegistry &);
+}
+
+#endif
diff --git a/final/include/polly/Options.h b/final/include/polly/Options.h
new file mode 100644
index 0000000..62e0960
--- /dev/null
+++ b/final/include/polly/Options.h
@@ -0,0 +1,20 @@
+//===--------------- polly/Options.h - The Polly option category *- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Introduce an option category for Polly.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_OPTIONS_H
+#define POLLY_OPTIONS_H
+
+#include "llvm/Support/CommandLine.h"
+
+extern llvm::cl::OptionCategory PollyCategory;
+#endif
diff --git a/final/include/polly/RegisterPasses.h b/final/include/polly/RegisterPasses.h
new file mode 100644
index 0000000..91e1e9c
--- /dev/null
+++ b/final/include/polly/RegisterPasses.h
@@ -0,0 +1,29 @@
+//===------ polly/RegisterPasses.h - Register the Polly passes *- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Functions to register the Polly passes in a LLVM pass manager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_REGISTER_PASSES_H
+#define POLLY_REGISTER_PASSES_H
+
+#include "llvm/PassManager.h"
+
+namespace llvm {
+namespace legacy {
+class PassManagerBase;
+}
+}
+
+namespace polly {
+void initializePollyPasses(llvm::PassRegistry &Registry);
+void registerPollyPasses(llvm::PassManagerBase &PM);
+}
+#endif
diff --git a/final/include/polly/ScheduleOptimizer.h b/final/include/polly/ScheduleOptimizer.h
new file mode 100644
index 0000000..80272d2
--- /dev/null
+++ b/final/include/polly/ScheduleOptimizer.h
@@ -0,0 +1,19 @@
+//===------ polly/ScheduleOptimizer.h - The Schedule Optimizer *- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SCHEDULE_OPTIMIZER_H
+#define POLLY_SCHEDULE_OPTIMIZER_H
+
+namespace polly {
+extern bool DisablePollyTiling;
+}
+
+#endif
diff --git a/final/include/polly/ScopDetection.h b/final/include/polly/ScopDetection.h
new file mode 100644
index 0000000..9753e38
--- /dev/null
+++ b/final/include/polly/ScopDetection.h
@@ -0,0 +1,389 @@
+//===--- ScopDetection.h - Detect Scops -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Detect the maximal Scops of a function.
+//
+// A static control part (Scop) is a subgraph of the control flow graph (CFG)
+// that only has statically known control flow and can therefore be described
+// within the polyhedral model.
+//
+// Every Scop fullfills these restrictions:
+//
+// * It is a single entry single exit region
+//
+// * Only affine linear bounds in the loops
+//
+// Every natural loop in a Scop must have a number of loop iterations that can
+// be described as an affine linear function in surrounding loop iterators or
+// parameters. (A parameter is a scalar that does not change its value during
+// execution of the Scop).
+//
+// * Only comparisons of affine linear expressions in conditions
+//
+// * All loops and conditions perfectly nested
+//
+// The control flow needs to be structured such that it could be written using
+// just 'for' and 'if' statements, without the need for any 'goto', 'break' or
+// 'continue'.
+//
+// * Side effect free functions call
+//
+// Only function calls and intrinsics that do not have side effects are allowed
+// (readnone).
+//
+// The Scop detection finds the largest Scops by checking if the largest
+// region is a Scop. If this is not the case, its canonical subregions are
+// checked until a region is a Scop. It is now tried to extend this Scop by
+// creating a larger non canonical region.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SCOP_DETECTION_H
+#define POLLY_SCOP_DETECTION_H
+
+#include "llvm/Pass.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Analysis/AliasSetTracker.h"
+
+#include "polly/ScopDetectionDiagnostic.h"
+
+#include "llvm/ADT/SetVector.h"
+
+#include <set>
+#include <map>
+
+using namespace llvm;
+
+namespace llvm {
+class RegionInfo;
+class Region;
+class LoopInfo;
+class Loop;
+class ScalarEvolution;
+class SCEV;
+class SCEVAddRecExpr;
+class SCEVUnknown;
+class CallInst;
+class Instruction;
+class AliasAnalysis;
+class Value;
+}
+
+namespace polly {
+typedef std::set<const SCEV *> ParamSetType;
+
+// Description of the shape of an array.
+struct ArrayShape {
+  // Base pointer identifying all accesses to this array.
+  const SCEVUnknown *BasePointer;
+
+  // Sizes of each delinearized dimension.
+  SmallVector<const SCEV *, 4> DelinearizedSizes;
+
+  ArrayShape(const SCEVUnknown *B) : BasePointer(B), DelinearizedSizes() {}
+};
+
+struct MemAcc {
+  const Instruction *Insn;
+
+  // A pointer to the shape description of the array.
+  ArrayShape *Shape;
+
+  // Subscripts computed by delinearization.
+  SmallVector<const SCEV *, 4> DelinearizedSubscripts;
+
+  MemAcc(const Instruction *I, ArrayShape *S)
+      : Insn(I), Shape(S), DelinearizedSubscripts() {}
+};
+
+typedef std::map<const Instruction *, MemAcc *> MapInsnToMemAcc;
+typedef std::pair<const Instruction *, const SCEV *> PairInstSCEV;
+typedef std::vector<PairInstSCEV> AFs;
+typedef std::map<const SCEVUnknown *, AFs> BaseToAFs;
+typedef std::map<const SCEVUnknown *, const SCEV *> BaseToElSize;
+
+extern bool PollyTrackFailures;
+extern bool PollyDelinearize;
+extern bool PollyUseRuntimeAliasChecks;
+
+/// @brief A function attribute which will cause Polly to skip the function
+extern llvm::StringRef PollySkipFnAttr;
+
+//===----------------------------------------------------------------------===//
+/// @brief Pass to detect the maximal static control parts (Scops) of a
+/// function.
+class ScopDetection : public FunctionPass {
+public:
+  typedef SetVector<const Region *> RegionSet;
+
+private:
+  //===--------------------------------------------------------------------===//
+  ScopDetection(const ScopDetection &) LLVM_DELETED_FUNCTION;
+  const ScopDetection &operator=(const ScopDetection &) LLVM_DELETED_FUNCTION;
+
+  /// @brief Analysis passes used.
+  //@{
+  ScalarEvolution *SE;
+  LoopInfo *LI;
+  RegionInfo *RI;
+  AliasAnalysis *AA;
+  //@}
+
+  /// @brief Context variables for SCoP detection.
+  struct DetectionContext {
+    Region &CurRegion;   // The region to check.
+    AliasSetTracker AST; // The AliasSetTracker to hold the alias information.
+    bool Verifying;      // If we are in the verification phase?
+    RejectLog Log;
+
+    /// @brief Map a base pointer to all access functions accessing it.
+    ///
+    /// This map is indexed by the base pointer. Each element of the map
+    /// is a list of memory accesses that reference this base pointer.
+    BaseToAFs Accesses;
+
+    /// @brief The set of base pointers with non-affine accesses.
+    ///
+    /// This set contains all base pointers which are used in memory accesses
+    /// that can not be detected as affine accesses.
+    SetVector<const SCEVUnknown *> NonAffineAccesses;
+    BaseToElSize ElementSize;
+
+    DetectionContext(Region &R, AliasAnalysis &AA, bool Verify)
+        : CurRegion(R), AST(AA), Verifying(Verify), Log(&R) {}
+  };
+
+  // Remember the valid regions
+  RegionSet ValidRegions;
+
+  // Remember a list of errors for every region.
+  mutable RejectLogsContainer RejectLogs;
+
+  // Delinearize all non affine memory accesses and return false when there
+  // exists a non affine memory access that cannot be delinearized. Return true
+  // when all array accesses are affine after delinearization.
+  bool hasAffineMemoryAccesses(DetectionContext &Context) const;
+
+  // Try to expand the region R. If R can be expanded return the expanded
+  // region, NULL otherwise.
+  Region *expandRegion(Region &R);
+
+  /// Find the Scops in this region tree.
+  ///
+  /// @param The region tree to scan for scops.
+  void findScops(Region &R);
+
+  /// @brief Check if all basic block in the region are valid.
+  ///
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if all blocks in R are valid, false otherwise.
+  bool allBlocksValid(DetectionContext &Context) const;
+
+  /// @brief Check the exit block of a region is valid.
+  ///
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if the exit of R is valid, false otherwise.
+  bool isValidExit(DetectionContext &Context) const;
+
+  /// @brief Check if a region is a Scop.
+  ///
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if R is a Scop, false otherwise.
+  bool isValidRegion(DetectionContext &Context) const;
+
+  /// @brief Check if a region is a Scop.
+  ///
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if R is a Scop, false otherwise.
+  bool isValidRegion(Region &R) const;
+
+  /// @brief Check if a call instruction can be part of a Scop.
+  ///
+  /// @param CI The call instruction to check.
+  /// @return True if the call instruction is valid, false otherwise.
+  static bool isValidCallInst(CallInst &CI);
+
+  /// @brief Check if a value is invariant in the region Reg.
+  ///
+  /// @param Val Value to check for invariance.
+  /// @param Reg The region to consider for the invariance of Val.
+  ///
+  /// @return True if the value represented by Val is invariant in the region
+  ///         identified by Reg.
+  bool isInvariant(const Value &Val, const Region &Reg) const;
+
+  /// @brief Check if a memory access can be part of a Scop.
+  ///
+  /// @param Inst The instruction accessing the memory.
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if the memory access is valid, false otherwise.
+  bool isValidMemoryAccess(Instruction &Inst, DetectionContext &Context) const;
+
+  /// @brief Check if an instruction has any non trivial scalar dependencies
+  ///        as part of a Scop.
+  ///
+  /// @param Inst The instruction to check.
+  /// @param RefRegion The region in respect to which we check the access
+  ///                  function.
+  ///
+  /// @return True if the instruction has scalar dependences, false otherwise.
+  bool hasScalarDependency(Instruction &Inst, Region &RefRegion) const;
+
+  /// @brief Check if an instruction can be part of a Scop.
+  ///
+  /// @param Inst The instruction to check.
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if the instruction is valid, false otherwise.
+  bool isValidInstruction(Instruction &Inst, DetectionContext &Context) const;
+
+  /// @brief Check if the control flow in a basic block is valid.
+  ///
+  /// @param BB The BB to check the control flow.
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if the BB contains only valid control flow.
+  bool isValidCFG(BasicBlock &BB, DetectionContext &Context) const;
+
+  /// @brief Is a loop valid with respect to a given region.
+  ///
+  /// @param L The loop to check.
+  /// @param Context The context of scop detection.
+  ///
+  /// @return True if the loop is valid in the region.
+  bool isValidLoop(Loop *L, DetectionContext &Context) const;
+
+  /// @brief Check if the function @p F is marked as invalid.
+  ///
+  /// @note An OpenMP subfunction will be marked as invalid.
+  bool isValidFunction(llvm::Function &F);
+
+  /// @brief Print the locations of all detected scops.
+  void printLocations(llvm::Function &F);
+
+  /// @brief Track diagnostics for invalid scops.
+  ///
+  /// @param Context The context of scop detection.
+  /// @param Assert Throw an assert in verify mode or not.
+  /// @param Args Argument list that gets passed to the constructor of RR.
+  template <class RR, typename... Args>
+  inline bool invalid(DetectionContext &Context, bool Assert,
+                      Args &&... Arguments) const;
+
+public:
+  static char ID;
+  explicit ScopDetection();
+
+  /// @brief Get the RegionInfo stored in this pass.
+  ///
+  /// This was added to give the DOT printer easy access to this information.
+  RegionInfo *getRI() const { return RI; }
+
+  /// @brief Is the region is the maximum region of a Scop?
+  ///
+  /// @param R The Region to test if it is maximum.
+  /// @param Verify Rerun the scop detection to verify SCoP was not invalidated
+  ///               meanwhile.
+  ///
+  /// @return Return true if R is the maximum Region in a Scop, false otherwise.
+  bool isMaxRegionInScop(const Region &R, bool Verify = true) const;
+
+  /// @brief Get a message why a region is invalid
+  ///
+  /// @param R The region for which we get the error message
+  ///
+  /// @return The error or "" if no error appeared.
+  std::string regionIsInvalidBecause(const Region *R) const;
+
+  /// @name Maximum Region In Scops Iterators
+  ///
+  /// These iterators iterator over all maximum region in Scops of this
+  /// function.
+  //@{
+  typedef RegionSet::iterator iterator;
+  typedef RegionSet::const_iterator const_iterator;
+
+  iterator begin() { return ValidRegions.begin(); }
+  iterator end() { return ValidRegions.end(); }
+
+  const_iterator begin() const { return ValidRegions.begin(); }
+  const_iterator end() const { return ValidRegions.end(); }
+  //@}
+
+  /// @name Reject log iterators
+  ///
+  /// These iterators iterate over the logs of all rejected regions of this
+  //  function.
+  //@{
+  typedef std::map<const Region *, RejectLog>::iterator reject_iterator;
+  typedef std::map<const Region *, RejectLog>::const_iterator
+      const_reject_iterator;
+
+  reject_iterator reject_begin() { return RejectLogs.begin(); }
+  reject_iterator reject_end() { return RejectLogs.end(); }
+
+  const_reject_iterator reject_begin() const { return RejectLogs.begin(); }
+  const_reject_iterator reject_end() const { return RejectLogs.end(); }
+  //@}
+
+  /// @brief Emit rejection remarks for all smallest invalid regions.
+  ///
+  /// @param F The function to emit remarks for.
+  /// @param R The region to start the region tree traversal for.
+  void emitMissedRemarksForLeaves(const Function &F, const Region *R);
+
+  /// @brief Emit rejection remarks for the parent regions of all valid regions.
+  ///
+  /// Emitting rejection remarks for the parent regions of all valid regions
+  /// may give the end-user clues about how to increase the size of the
+  /// detected Scops.
+  ///
+  /// @param F The function to emit remarks for.
+  /// @param ValidRegions The set of valid regions to emit remarks for.
+  void emitMissedRemarksForValidRegions(const Function &F,
+                                        const RegionSet &ValidRegions);
+
+  /// @brief Mark the function as invalid so we will not extract any scop from
+  ///        the function.
+  ///
+  /// @param F The function to mark as invalid.
+  void markFunctionAsInvalid(Function *F) const;
+
+  /// @brief Verify if all valid Regions in this Function are still valid
+  /// after some transformations.
+  void verifyAnalysis() const;
+
+  /// @brief Verify if R is still a valid part of Scop after some
+  /// transformations.
+  ///
+  /// @param R The Region to verify.
+  void verifyRegion(const Region &R) const;
+
+  /// @name FunctionPass interface
+  //@{
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual void releaseMemory();
+  virtual bool runOnFunction(Function &F);
+  virtual void print(raw_ostream &OS, const Module *) const;
+  //@}
+};
+
+} // end namespace polly
+
+namespace llvm {
+class PassRegistry;
+void initializeScopDetectionPass(llvm::PassRegistry &);
+}
+
+#endif
diff --git a/final/include/polly/ScopDetectionDiagnostic.h b/final/include/polly/ScopDetectionDiagnostic.h
new file mode 100644
index 0000000..c463597
--- /dev/null
+++ b/final/include/polly/ScopDetectionDiagnostic.h
@@ -0,0 +1,835 @@
+//=== ScopDetectionDiagnostic.h -- Diagnostic for ScopDetection -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Small set of diagnostic helper classes to encapsulate any errors occurred
+// during the detection of Scops.
+//
+// The ScopDetection defines a set of error classes (via Statistic variables)
+// that groups a number of individual errors into a group, e.g. non-affinity
+// related errors.
+// On error we generate an object that carries enough additional information
+// to diagnose the error and generate a helpful error message.
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLLY_SCOP_DETECTION_DIAGNOSTIC_H
+#define POLLY_SCOP_DETECTION_DIAGNOSTIC_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/AliasSetTracker.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Value.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Support/Casting.h"
+
+#include <string>
+#include <memory>
+
+using namespace llvm;
+
+namespace llvm {
+class SCEV;
+class BasicBlock;
+class Value;
+class Region;
+}
+
+namespace polly {
+
+/// @brief Get the location of a region from the debug info.
+///
+/// @param R The region to get debug info for.
+/// @param LineBegin The first line in the region.
+/// @param LineEnd The last line in the region.
+/// @param FileName The filename where the region was defined.
+void getDebugLocation(const Region *R, unsigned &LineBegin, unsigned &LineEnd,
+                      std::string &FileName);
+
+class RejectLog;
+/// @brief Emit optimization remarks about the rejected regions to the user.
+///
+/// This emits the content of the reject log as optimization remarks.
+/// Remember to at least track failures (-polly-detect-track-failures).
+/// @param F The function we emit remarks for.
+/// @param Log The error log containing all messages being emitted as remark.
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log);
+
+/// @brief Emit diagnostic remarks for a valid Scop
+///
+/// @param F The function we emit remarks for
+/// @param R The region that marks a valid Scop
+void emitValidRemarks(const llvm::Function &F, const Region *R);
+
+// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
+enum RejectReasonKind {
+  // CFG Category
+  rrkCFG,
+  rrkNonBranchTerminator,
+  rrkCondition,
+  rrkLastCFG,
+
+  // Non-Affinity
+  rrkAffFunc,
+  rrkUndefCond,
+  rrkInvalidCond,
+  rrkUndefOperand,
+  rrkNonAffBranch,
+  rrkNoBasePtr,
+  rrkUndefBasePtr,
+  rrkVariantBasePtr,
+  rrkNonAffineAccess,
+  rrkDifferentElementSize,
+  rrkLastAffFunc,
+
+  // IndVar
+  rrkIndVar,
+  rrkPhiNodeRefInRegion,
+  rrkLastIndVar,
+
+  rrkIndEdge,
+
+  rrkLoopBound,
+
+  rrkFuncCall,
+
+  rrkAlias,
+
+  rrkSimpleLoop,
+
+  // Other
+  rrkOther,
+  rrkIntToPtr,
+  rrkAlloca,
+  rrkUnknownInst,
+  rrkPHIinExit,
+  rrkEntry,
+  rrkLastOther
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class of all reject reasons found during Scop detection.
+///
+/// Subclasses of RejectReason should provide means to capture enough
+/// diagnostic information to help clients figure out what and where something
+/// went wrong in the Scop detection.
+class RejectReason {
+  //===--------------------------------------------------------------------===//
+private:
+  const RejectReasonKind Kind;
+
+protected:
+  static const DebugLoc Unknown;
+
+public:
+  RejectReasonKind getKind() const { return Kind; }
+
+  RejectReason(RejectReasonKind K) : Kind(K) {}
+
+  virtual ~RejectReason() {}
+
+  /// @brief Generate a reasonable diagnostic message describing this error.
+  ///
+  /// @return A debug message representing this error.
+  virtual std::string getMessage() const = 0;
+
+  /// @brief Generate a message for the end-user describing this error.
+  ///
+  /// The message provided has to be suitable for the end-user. So it should
+  /// not reference any LLVM internal data structures or terminology.
+  /// Ideally, the message helps the end-user to increase the size of the
+  /// regions amenable to Polly.
+  ///
+  /// @return A short message representing this error.
+  virtual std::string getEndUserMessage() const {
+    return "Unspecified error.";
+  };
+
+  /// @brief Get the source location of this error.
+  ///
+  /// @return The debug location for this error.
+  virtual const llvm::DebugLoc &getDebugLoc() const;
+};
+
+typedef std::shared_ptr<RejectReason> RejectReasonPtr;
+
+/// @brief Stores all errors that ocurred during the detection.
+class RejectLog {
+  Region *R;
+  llvm::SmallVector<RejectReasonPtr, 1> ErrorReports;
+
+public:
+  explicit RejectLog(Region *R) : R(R) {}
+
+  typedef llvm::SmallVector<RejectReasonPtr, 1>::const_iterator iterator;
+
+  iterator begin() const { return ErrorReports.begin(); }
+  iterator end() const { return ErrorReports.end(); }
+  size_t size() const { return ErrorReports.size(); }
+
+  /// @brief Returns true, if we store at least one error.
+  ///
+  /// @return true, if we store at least one error.
+  bool hasErrors() const { return size() > 0; }
+
+  void print(raw_ostream &OS, int level = 0) const;
+
+  const Region *region() const { return R; }
+  void report(RejectReasonPtr Reject) { ErrorReports.push_back(Reject); }
+};
+
+/// @brief Store reject logs
+class RejectLogsContainer {
+  std::map<const Region *, RejectLog> Logs;
+
+public:
+  typedef std::map<const Region *, RejectLog>::iterator iterator;
+  typedef std::map<const Region *, RejectLog>::const_iterator const_iterator;
+
+  iterator begin() { return Logs.begin(); }
+  iterator end() { return Logs.end(); }
+
+  const_iterator begin() const { return Logs.begin(); }
+  const_iterator end() const { return Logs.end(); }
+
+  std::pair<iterator, bool>
+  insert(const std::pair<const Region *, RejectLog> &New) {
+    return Logs.insert(New);
+  }
+
+  std::map<const Region *, RejectLog>::mapped_type at(const Region *R) {
+    return Logs.at(R);
+  }
+
+  void clear() { Logs.clear(); }
+
+  size_t count(const Region *R) const { return Logs.count(R); }
+
+  size_t size(const Region *R) const {
+    if (!Logs.count(R))
+      return 0;
+    return Logs.at(R).size();
+  }
+
+  bool hasErrors(const Region *R) const {
+    if (!Logs.count(R))
+      return false;
+
+    RejectLog Log = Logs.at(R);
+    return Log.hasErrors();
+  }
+
+  bool hasErrors(Region *R) const { return hasErrors((const Region *)R); }
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for CFG related reject reasons.
+///
+/// Scop candidates that violate structural restrictions can be grouped under
+/// this reject reason class.
+class ReportCFG : public RejectReason {
+  //===--------------------------------------------------------------------===//
+public:
+  ReportCFG(const RejectReasonKind K);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non-branch terminator within a Scop candidate.
+class ReportNonBranchTerminator : public ReportCFG {
+  BasicBlock *BB;
+
+public:
+  ReportNonBranchTerminator(BasicBlock *BB)
+      : ReportCFG(rrkNonBranchTerminator), BB(BB) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a not well-structured condition within the CFG.
+class ReportCondition : public ReportCFG {
+  //===--------------------------------------------------------------------===//
+
+  // The BasicBlock we found the broken condition in.
+  BasicBlock *BB;
+
+public:
+  ReportCondition(BasicBlock *BB) : ReportCFG(rrkCondition), BB(BB) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for non-affine reject reasons.
+///
+/// Scop candidates that violate restrictions to affinity are reported under
+/// this class.
+class ReportAffFunc : public RejectReason {
+  //===--------------------------------------------------------------------===//
+
+  // The instruction that caused non-affinity to occur.
+  const Instruction *Inst;
+
+public:
+  ReportAffFunc(const RejectReasonKind K, const Instruction *Inst);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual const DebugLoc &getDebugLoc() const override {
+    return Inst->getDebugLoc();
+  };
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a condition that is based on an 'undef' value.
+class ReportUndefCond : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The BasicBlock we found the broken condition in.
+  BasicBlock *BB;
+
+public:
+  ReportUndefCond(const Instruction *Inst, BasicBlock *BB)
+      : ReportAffFunc(rrkUndefCond, Inst), BB(BB) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures an invalid condition
+///
+/// Conditions have to be either constants or icmp instructions.
+class ReportInvalidCond : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The BasicBlock we found the broken condition in.
+  BasicBlock *BB;
+
+public:
+  ReportInvalidCond(const Instruction *Inst, BasicBlock *BB)
+      : ReportAffFunc(rrkInvalidCond, Inst), BB(BB) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures an undefined operand.
+class ReportUndefOperand : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The BasicBlock we found the undefined operand in.
+  BasicBlock *BB;
+
+public:
+  ReportUndefOperand(BasicBlock *BB, const Instruction *Inst)
+      : ReportAffFunc(rrkUndefOperand, Inst), BB(BB) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non-affine branch.
+class ReportNonAffBranch : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The BasicBlock we found the non-affine branch in.
+  BasicBlock *BB;
+
+  /// @brief LHS & RHS of the failed condition.
+  //@{
+  const SCEV *LHS;
+  const SCEV *RHS;
+  //@}
+
+public:
+  ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS,
+                     const Instruction *Inst)
+      : ReportAffFunc(rrkNonAffBranch, Inst), BB(BB), LHS(LHS), RHS(RHS) {}
+
+  const SCEV *lhs() { return LHS; }
+  const SCEV *rhs() { return RHS; }
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a missing base pointer.
+class ReportNoBasePtr : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+public:
+  ReportNoBasePtr(const Instruction *Inst)
+      : ReportAffFunc(rrkNoBasePtr, Inst) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures an undefined base pointer.
+class ReportUndefBasePtr : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+public:
+  ReportUndefBasePtr(const Instruction *Inst)
+      : ReportAffFunc(rrkUndefBasePtr, Inst) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a base pointer that is not invariant in the region.
+class ReportVariantBasePtr : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The variant base pointer.
+  Value *BaseValue;
+
+public:
+  ReportVariantBasePtr(Value *BaseValue, const Instruction *Inst)
+      : ReportAffFunc(rrkVariantBasePtr, Inst), BaseValue(BaseValue) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual std::string getEndUserMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non-affine access function.
+class ReportNonAffineAccess : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The non-affine access function.
+  const SCEV *AccessFunction;
+
+  // The base pointer of the memory access.
+  const Value *BaseValue;
+
+public:
+  ReportNonAffineAccess(const SCEV *AccessFunction, const Instruction *Inst,
+                        const Value *V)
+      : ReportAffFunc(rrkNonAffineAccess, Inst), AccessFunction(AccessFunction),
+        BaseValue(V) {}
+
+  const SCEV *get() { return AccessFunction; }
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual std::string getEndUserMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Report array accesses with differing element size.
+class ReportDifferentArrayElementSize : public ReportAffFunc {
+  //===--------------------------------------------------------------------===//
+
+  // The base pointer of the memory access.
+  const Value *BaseValue;
+
+public:
+  ReportDifferentArrayElementSize(const Instruction *Inst, const Value *V)
+      : ReportAffFunc(rrkDifferentElementSize, Inst), BaseValue(V) {}
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual std::string getEndUserMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for reject reasons related to induction variables.
+///
+//  ReportIndVar reject reasons are generated when the ScopDetection finds
+/// errors in the induction variable(s) of the Scop candidate.
+class ReportIndVar : public RejectReason {
+  //===--------------------------------------------------------------------===//
+public:
+  ReportIndVar(const RejectReasonKind K);
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a phi node that refers to SSA names in the current region.
+class ReportPhiNodeRefInRegion : public ReportIndVar {
+  //===--------------------------------------------------------------------===//
+
+  // The offending instruction.
+  Instruction *Inst;
+
+public:
+  ReportPhiNodeRefInRegion(Instruction *Inst);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a region with invalid entering edges.
+class ReportIndEdge : public RejectReason {
+  //===--------------------------------------------------------------------===//
+
+  BasicBlock *BB;
+
+public:
+  ReportIndEdge(BasicBlock *BB);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with non affine loop bounds.
+class ReportLoopBound : public RejectReason {
+  //===--------------------------------------------------------------------===//
+
+  // The offending loop.
+  Loop *L;
+
+  // The non-affine loop bound.
+  const SCEV *LoopCount;
+
+  // A copy of the offending loop's debug location.
+  const DebugLoc Loc;
+
+public:
+  ReportLoopBound(Loop *L, const SCEV *LoopCount);
+
+  const SCEV *loopCount() { return LoopCount; }
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  virtual std::string getEndUserMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with non-side-effect-known function calls.
+class ReportFuncCall : public RejectReason {
+  //===--------------------------------------------------------------------===//
+
+  // The offending call instruction.
+  Instruction *Inst;
+
+public:
+  ReportFuncCall(Instruction *Inst);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  virtual std::string getEndUserMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with aliasing.
+class ReportAlias : public RejectReason {
+  //===--------------------------------------------------------------------===//
+public:
+  typedef std::vector<const llvm::Value *> PointerSnapshotTy;
+
+private:
+  /// @brief Format an invalid alias set.
+  ///
+  //  @param Prefix A prefix string to put before the list of aliasing pointers.
+  //  @param Suffix A suffix string to put after the list of aliasing pointers.
+  std::string formatInvalidAlias(std::string Prefix = "",
+                                 std::string Suffix = "") const;
+
+  Instruction *Inst;
+
+  // A snapshot of the llvm values that took part in the aliasing error.
+  mutable PointerSnapshotTy Pointers;
+
+public:
+  ReportAlias(Instruction *Inst, AliasSet &AS);
+
+  const PointerSnapshotTy &getPointers() const { return Pointers; }
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  virtual std::string getEndUserMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with non simplified loops.
+class ReportSimpleLoop : public RejectReason {
+  //===--------------------------------------------------------------------===//
+public:
+  ReportSimpleLoop();
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for otherwise ungrouped reject reasons.
+class ReportOther : public RejectReason {
+  //===--------------------------------------------------------------------===//
+public:
+  ReportOther(const RejectReasonKind K);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with bad IntToPtr instructions.
+class ReportIntToPtr : public ReportOther {
+  //===--------------------------------------------------------------------===//
+
+  // The offending base value.
+  Instruction *BaseValue;
+
+public:
+  ReportIntToPtr(Instruction *BaseValue);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with alloca instructions.
+class ReportAlloca : public ReportOther {
+  //===--------------------------------------------------------------------===//
+  Instruction *Inst;
+
+public:
+  ReportAlloca(Instruction *Inst);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with unknown instructions.
+class ReportUnknownInst : public ReportOther {
+  //===--------------------------------------------------------------------===//
+  Instruction *Inst;
+
+public:
+  ReportUnknownInst(Instruction *Inst);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with phi nodes in exit BBs.
+class ReportPHIinExit : public ReportOther {
+  //===--------------------------------------------------------------------===//
+  Instruction *Inst;
+
+public:
+  ReportPHIinExit(Instruction *Inst);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with regions containing the function entry block.
+class ReportEntry : public ReportOther {
+  //===--------------------------------------------------------------------===//
+  BasicBlock *BB;
+
+public:
+  ReportEntry(BasicBlock *BB);
+
+  /// @name LLVM-RTTI interface
+  //@{
+  static bool classof(const RejectReason *RR);
+  //@}
+
+  /// @name RejectReason interface
+  //@{
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  //@}
+};
+
+} // namespace polly
+
+#endif // POLLY_SCOP_DETECTION_DIAGNOSTIC_H
diff --git a/final/include/polly/ScopInfo.h b/final/include/polly/ScopInfo.h
new file mode 100644
index 0000000..df13781
--- /dev/null
+++ b/final/include/polly/ScopInfo.h
@@ -0,0 +1,970 @@
+//===------ polly/ScopInfo.h - Create Scops from LLVM IR --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Create a polyhedral description for a static control flow region.
+//
+// The pass creates a polyhedral description of the Scops detected by the Scop
+// detection derived from their LLVM-IR code.
+//
+// This representation is shared among several tools in the polyhedral
+// community, which are e.g. CLooG, Pluto, Loopo, Graphite.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SCOP_INFO_H
+#define POLLY_SCOP_INFO_H
+
+#include "polly/ScopDetection.h"
+
+#include "llvm/Analysis/RegionPass.h"
+
+#include "isl/ctx.h"
+
+using namespace llvm;
+
+namespace llvm {
+class Loop;
+class LoopInfo;
+class PHINode;
+class ScalarEvolution;
+class SCEV;
+class SCEVAddRecExpr;
+class Type;
+}
+
+struct isl_ctx;
+struct isl_map;
+struct isl_basic_map;
+struct isl_id;
+struct isl_set;
+struct isl_union_set;
+struct isl_union_map;
+struct isl_space;
+struct isl_constraint;
+struct isl_pw_multi_aff;
+
+namespace polly {
+
+class IRAccess;
+class Scop;
+class ScopStmt;
+class ScopInfo;
+class TempScop;
+class SCEVAffFunc;
+class Comparison;
+
+/// @brief A class to store information about arrays in the SCoP.
+///
+/// Objects are accessible via the ScoP, MemoryAccess or the id associated with
+/// the MemoryAccess access function.
+///
+class ScopArrayInfo {
+public:
+  /// @brief Construct a ScopArrayInfo object.
+  ///
+  /// @param BasePtr        The array base pointer.
+  /// @param AccessType     The type used to access this array.
+  /// @param IslCtx         The isl context used to create the base pointer id.
+  /// @param DimensionSizes A vector containing the size of each dimension.
+  ScopArrayInfo(Value *BasePtr, Type *AccessType, isl_ctx *IslCtx,
+                const SmallVector<const SCEV *, 4> &DimensionSizes);
+
+  /// @brief Destructor to free the isl id of the base pointer.
+  ~ScopArrayInfo();
+
+  /// @brief Return the base pointer.
+  Value *getBasePtr() const { return BasePtr; }
+
+  /// @brief Return the number of dimensions.
+  unsigned getNumberOfDimensions() const { return DimensionSizes.size(); }
+
+  /// @brief Return the size of dimension @p dim.
+  const SCEV *getDimensionSize(unsigned dim) const {
+    assert(dim < getNumberOfDimensions() && "Invalid dimension");
+    return DimensionSizes[dim];
+  }
+
+  /// @brief Return the type used to access this array in the SCoP.
+  Type *getType() const { return AccessType; }
+
+  /// @brief Return the isl id for the base pointer.
+  __isl_give isl_id *getBasePtrId() const;
+
+  /// @brief Dump a readable representation to stderr.
+  void dump() const;
+
+  /// @brief Print a readable representation to @p OS.
+  void print(raw_ostream &OS) const;
+
+  /// @brief Access the ScopArrayInfo associated with an access function.
+  static const ScopArrayInfo *
+  getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA);
+
+  /// @brief Access the ScopArrayInfo associated with an isl Id.
+  static const ScopArrayInfo *getFromId(__isl_take isl_id *Id);
+
+private:
+  /// @brief The base pointer.
+  Value *BasePtr;
+
+  /// @brief The type used to access this array.
+  Type *AccessType;
+
+  /// @brief The isl id for the base pointer.
+  isl_id *Id;
+
+  /// @brief The sizes of each dimension.
+  SmallVector<const SCEV *, 4> DimensionSizes;
+};
+
+/// @brief Represent memory accesses in statements.
+class MemoryAccess {
+public:
+  /// @brief The access type of a memory access
+  ///
+  /// There are three kind of access types:
+  ///
+  /// * A read access
+  ///
+  /// A certain set of memory locations are read and may be used for internal
+  /// calculations.
+  ///
+  /// * A must-write access
+  ///
+  /// A certain set of memory locations is definitely written. The old value is
+  /// replaced by a newly calculated value. The old value is not read or used at
+  /// all.
+  ///
+  /// * A may-write access
+  ///
+  /// A certain set of memory locations may be written. The memory location may
+  /// contain a new value if there is actually a write or the old value may
+  /// remain, if no write happens.
+  enum AccessType { READ, MUST_WRITE, MAY_WRITE };
+
+  /// @brief Reduction access type
+  ///
+  /// Commutative and associative binary operations suitable for reductions
+  enum ReductionType {
+    RT_NONE, ///< Indicate no reduction at all
+    RT_ADD,  ///< Addition
+    RT_MUL,  ///< Multiplication
+    RT_BOR,  ///< Bitwise Or
+    RT_BXOR, ///< Bitwise XOr
+    RT_BAND, ///< Bitwise And
+  };
+
+private:
+  MemoryAccess(const MemoryAccess &) LLVM_DELETED_FUNCTION;
+  const MemoryAccess &operator=(const MemoryAccess &) LLVM_DELETED_FUNCTION;
+
+  isl_map *AccessRelation;
+  enum AccessType AccType;
+
+  /// @brief The base address (e.g., A for A[i+j]).
+  Value *BaseAddr;
+
+  std::string BaseName;
+  isl_basic_map *createBasicAccessMap(ScopStmt *Statement);
+  ScopStmt *Statement;
+
+  /// @brief Reduction type for reduction like accesses, RT_NONE otherwise
+  ///
+  /// An access is reduction like if it is part of a load-store chain in which
+  /// both access the same memory location (use the same LLVM-IR value
+  /// as pointer reference). Furthermore, between the load and the store there
+  /// is exactly one binary operator which is known to be associative and
+  /// commutative.
+  ///
+  /// TODO:
+  ///
+  /// We can later lift the constraint that the same LLVM-IR value defines the
+  /// memory location to handle scops such as the following:
+  ///
+  ///    for i
+  ///      for j
+  ///        sum[i+j] = sum[i] + 3;
+  ///
+  /// Here not all iterations access the same memory location, but iterations
+  /// for which j = 0 holds do. After lifing the equality check in ScopInfo,
+  /// subsequent transformations do not only need check if a statement is
+  /// reduction like, but they also need to verify that that the reduction
+  /// property is only exploited for statement instances that load from and
+  /// store to the same data location. Doing so at dependence analysis time
+  /// could allow us to handle the above example.
+  ReductionType RedType = RT_NONE;
+
+  /// @brief The access instruction of this memory access.
+  Instruction *Inst;
+
+  /// Updated access relation read from JSCOP file.
+  isl_map *newAccessRelation;
+
+  void assumeNoOutOfBound(const IRAccess &Access);
+
+  /// @brief Get the original access function as read from IR.
+  isl_map *getOriginalAccessRelation() const;
+
+  /// @brief Return the space in which the access relation lives in.
+  __isl_give isl_space *getOriginalAccessRelationSpace() const;
+
+  /// @brief Get the new access function imported or set by a pass
+  isl_map *getNewAccessRelation() const;
+
+public:
+  /// @brief Create a memory access from an access in LLVM-IR.
+  ///
+  /// @param Access    The memory access.
+  /// @param AccInst   The access instruction.
+  /// @param Statement The statement that contains the access.
+  /// @param SAI       The ScopArrayInfo object for this base pointer.
+  MemoryAccess(const IRAccess &Access, Instruction *AccInst,
+               ScopStmt *Statement, const ScopArrayInfo *SAI);
+
+  ~MemoryAccess();
+
+  /// @brief Get the type of a memory access.
+  enum AccessType getType() { return AccType; }
+
+  /// @brief Is this a reduction like access?
+  bool isReductionLike() const { return RedType != RT_NONE; }
+
+  /// @brief Is this a read memory access?
+  bool isRead() const { return AccType == MemoryAccess::READ; }
+
+  /// @brief Is this a must-write memory access?
+  bool isMustWrite() const { return AccType == MemoryAccess::MUST_WRITE; }
+
+  /// @brief Is this a may-write memory access?
+  bool isMayWrite() const { return AccType == MemoryAccess::MAY_WRITE; }
+
+  /// @brief Is this a write memory access?
+  bool isWrite() const { return isMustWrite() || isMayWrite(); }
+
+  /// @brief Check if a new access relation was imported or set by a pass.
+  bool hasNewAccessRelation() const { return newAccessRelation; }
+
+  /// @brief Return the newest access relation of this access.
+  ///
+  /// There are two possibilities:
+  ///   1) The original access relation read from the LLVM-IR.
+  ///   2) A new access relation imported from a json file or set by another
+  ///      pass (e.g., for privatization).
+  ///
+  /// As 2) is by construction "newer" than 1) we return the new access
+  /// relation if present.
+  ///
+  isl_map *getAccessRelation() const {
+    return hasNewAccessRelation() ? getNewAccessRelation()
+                                  : getOriginalAccessRelation();
+  }
+
+  /// @brief Return the access relation after the schedule was applied.
+  __isl_give isl_pw_multi_aff *
+  applyScheduleToAccessRelation(__isl_keep isl_union_map *Schedule) const;
+
+  /// @brief Get an isl string representing the access function read from IR.
+  std::string getOriginalAccessRelationStr() const;
+
+  /// @brief Get the base address of this access (e.g. A for A[i+j]).
+  Value *getBaseAddr() const { return BaseAddr; }
+
+  /// @brief Get the base array isl_id for this access.
+  __isl_give isl_id *getArrayId() const;
+
+  /// @brief Get the ScopArrayInfo object for the base address.
+  const ScopArrayInfo *getScopArrayInfo() const;
+
+  /// @brief Return a string representation of the accesse's reduction type.
+  const std::string getReductionOperatorStr() const;
+
+  /// @brief Return a string representation of the reduction type @p RT.
+  static const std::string getReductionOperatorStr(ReductionType RT);
+
+  const std::string &getBaseName() const { return BaseName; }
+
+  /// @brief Return the access instruction of this memory access.
+  Instruction *getAccessInstruction() const { return Inst; }
+
+  /// Get the stride of this memory access in the specified Schedule. Schedule
+  /// is a map from the statement to a schedule where the innermost dimension is
+  /// the dimension of the innermost loop containing the statement.
+  isl_set *getStride(__isl_take const isl_map *Schedule) const;
+
+  /// Is the stride of the access equal to a certain width? Schedule is a map
+  /// from the statement to a schedule where the innermost dimension is the
+  /// dimension of the innermost loop containing the statement.
+  bool isStrideX(__isl_take const isl_map *Schedule, int StrideWidth) const;
+
+  /// Is consecutive memory accessed for a given statement instance set?
+  /// Schedule is a map from the statement to a schedule where the innermost
+  /// dimension is the dimension of the innermost loop containing the
+  /// statement.
+  bool isStrideOne(__isl_take const isl_map *Schedule) const;
+
+  /// Is always the same memory accessed for a given statement instance set?
+  /// Schedule is a map from the statement to a schedule where the innermost
+  /// dimension is the dimension of the innermost loop containing the
+  /// statement.
+  bool isStrideZero(__isl_take const isl_map *Schedule) const;
+
+  /// @brief Check if this is a scalar memory access.
+  bool isScalar() const;
+
+  /// @brief Get the statement that contains this memory access.
+  ScopStmt *getStatement() const { return Statement; }
+
+  /// @brief Get the reduction type of this access
+  ReductionType getReductionType() const { return RedType; }
+
+  /// @brief Set the updated access relation read from JSCOP file.
+  void setNewAccessRelation(__isl_take isl_map *newAccessRelation);
+
+  /// @brief Mark this a reduction like access
+  void markAsReductionLike(ReductionType RT) { RedType = RT; }
+
+  /// @brief Align the parameters in the access relation to the scop context
+  void realignParams();
+
+  /// @brief Print the MemoryAccess.
+  ///
+  /// @param OS The output stream the MemoryAccess is printed to.
+  void print(raw_ostream &OS) const;
+
+  /// @brief Print the MemoryAccess to stderr.
+  void dump() const;
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                              MemoryAccess::ReductionType RT);
+
+///===----------------------------------------------------------------------===//
+/// @brief Statement of the Scop
+///
+/// A Scop statement represents an instruction in the Scop.
+///
+/// It is further described by its iteration domain, its schedule and its data
+/// accesses.
+/// At the moment every statement represents a single basic block of LLVM-IR.
+class ScopStmt {
+  //===-------------------------------------------------------------------===//
+  ScopStmt(const ScopStmt &) LLVM_DELETED_FUNCTION;
+  const ScopStmt &operator=(const ScopStmt &) LLVM_DELETED_FUNCTION;
+
+  /// Polyhedral description
+  //@{
+
+  /// The Scop containing this ScopStmt
+  Scop &Parent;
+
+  /// The iteration domain describes the set of iterations for which this
+  /// statement is executed.
+  ///
+  /// Example:
+  ///     for (i = 0; i < 100 + b; ++i)
+  ///       for (j = 0; j < i; ++j)
+  ///         S(i,j);
+  ///
+  /// 'S' is executed for different values of i and j. A vector of all
+  /// induction variables around S (i, j) is called iteration vector.
+  /// The domain describes the set of possible iteration vectors.
+  ///
+  /// In this case it is:
+  ///
+  ///     Domain: 0 <= i <= 100 + b
+  ///             0 <= j <= i
+  ///
+  /// A pair of statement and iteration vector (S, (5,3)) is called statement
+  /// instance.
+  isl_set *Domain;
+
+  /// The scattering map describes the execution order of the statement
+  /// instances.
+  ///
+  /// A statement and its iteration domain do not give any information about the
+  /// order in time in which the different statement instances are executed.
+  /// This information is provided by the scattering.
+  ///
+  /// The scattering maps every instance of each statement into a multi
+  /// dimensional scattering space. This space can be seen as a multi
+  /// dimensional clock.
+  ///
+  /// Example:
+  ///
+  /// <S,(5,4)>  may be mapped to (5,4) by this scattering:
+  ///
+  /// s0 = i (Year of execution)
+  /// s1 = j (Day of execution)
+  ///
+  /// or to (9, 20) by this scattering:
+  ///
+  /// s0 = i + j (Year of execution)
+  /// s1 = 20 (Day of execution)
+  ///
+  /// The order statement instances are executed is defined by the
+  /// scattering vectors they are mapped to. A statement instance
+  /// <A, (i, j, ..)> is executed before a statement instance <B, (i', ..)>, if
+  /// the scattering vector of A is lexicographic smaller than the scattering
+  /// vector of B.
+  isl_map *Scattering;
+
+  /// The memory accesses of this statement.
+  ///
+  /// The only side effects of a statement are its memory accesses.
+  typedef SmallVector<MemoryAccess *, 8> MemoryAccessVec;
+  MemoryAccessVec MemAccs;
+  std::map<const Instruction *, MemoryAccess *> InstructionToAccess;
+
+  //@}
+
+  /// The BasicBlock represented by this statement.
+  BasicBlock *BB;
+
+  std::vector<Loop *> NestLoops;
+
+  std::string BaseName;
+
+  /// Build the statement.
+  //@{
+  __isl_give isl_set *buildConditionSet(const Comparison &Cmp);
+  __isl_give isl_set *addConditionsToDomain(__isl_take isl_set *Domain,
+                                            TempScop &tempScop,
+                                            const Region &CurRegion);
+  __isl_give isl_set *addLoopBoundsToDomain(__isl_take isl_set *Domain,
+                                            TempScop &tempScop);
+  __isl_give isl_set *buildDomain(TempScop &tempScop, const Region &CurRegion);
+  void buildScattering(SmallVectorImpl<unsigned> &Scatter);
+  void buildAccesses(TempScop &tempScop);
+
+  /// @brief Detect and mark reductions in the ScopStmt
+  void checkForReductions();
+
+  /// @brief Collect loads which might form a reduction chain with @p StoreMA
+  void
+  collectCandiateReductionLoads(MemoryAccess *StoreMA,
+                                llvm::SmallVectorImpl<MemoryAccess *> &Loads);
+  //@}
+
+  /// @brief Derive assumptions about parameter values from GetElementPtrInst
+  ///
+  /// In case a GEP instruction references into a fixed size array e.g., an
+  /// access A[i][j] into an array A[100x100], LLVM-IR does not guarantee that
+  /// the subscripts always compute values that are within array bounds. In this
+  /// function we derive the set of parameter values for which all accesses are
+  /// within bounds and add the assumption that the scop is only every executed
+  /// with this set of parameter values.
+  ///
+  /// Example:
+  ///
+  ///   void foo(float A[][20], long n, long m {
+  ///     for (long i = 0; i < n; i++)
+  ///       for (long j = 0; j < m; j++)
+  ///         A[i][j] = ...
+  ///
+  /// This loop yields out-of-bound accesses if m is at least 20 and at the same
+  /// time at least one iteration of the outer loop is executed. Hence, we
+  /// assume:
+  ///
+  ///   n <= 0 or m <= 20.
+  ///
+  /// TODO: The location where the GEP instruction is executed is not
+  /// necessarily the location where the memory is actually accessed. As a
+  /// result scanning for GEP[s] is imprecise. Even though this is not a
+  /// correctness problem, this imprecision may result in missed optimizations
+  /// or non-optimal run-time checks.
+  void deriveAssumptionsFromGEP(GetElementPtrInst *Inst);
+
+  /// @brief Scan the scop and derive assumptions about parameter values.
+  void deriveAssumptions();
+
+  /// Create the ScopStmt from a BasicBlock.
+  ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
+           BasicBlock &bb, SmallVectorImpl<Loop *> &NestLoops,
+           SmallVectorImpl<unsigned> &Scatter);
+
+  friend class Scop;
+
+public:
+  ~ScopStmt();
+
+  /// @brief Get an isl_ctx pointer.
+  isl_ctx *getIslCtx() const;
+
+  /// @brief Get the iteration domain of this ScopStmt.
+  ///
+  /// @return The iteration domain of this ScopStmt.
+  __isl_give isl_set *getDomain() const;
+
+  /// @brief Get the space of the iteration domain
+  ///
+  /// @return The space of the iteration domain
+  __isl_give isl_space *getDomainSpace() const;
+
+  /// @brief Get the id of the iteration domain space
+  ///
+  /// @return The id of the iteration domain space
+  isl_id *getDomainId() const;
+
+  /// @brief Get an isl string representing this domain.
+  std::string getDomainStr() const;
+
+  /// @brief Get the scattering function of this ScopStmt.
+  ///
+  /// @return The scattering function of this ScopStmt.
+  __isl_give isl_map *getScattering() const;
+  void setScattering(isl_map *scattering);
+
+  /// @brief Get an isl string representing this scattering.
+  std::string getScatteringStr() const;
+
+  /// @brief Get the BasicBlock represented by this ScopStmt.
+  ///
+  /// @return The BasicBlock represented by this ScopStmt.
+  BasicBlock *getBasicBlock() const { return BB; }
+
+  const MemoryAccess &getAccessFor(const Instruction *Inst) const {
+    MemoryAccess *A = lookupAccessFor(Inst);
+    assert(A && "Cannot get memory access because it does not exist!");
+    return *A;
+  }
+
+  MemoryAccess *lookupAccessFor(const Instruction *Inst) const {
+    std::map<const Instruction *, MemoryAccess *>::const_iterator at =
+        InstructionToAccess.find(Inst);
+    return at == InstructionToAccess.end() ? NULL : at->second;
+  }
+
+  void setBasicBlock(BasicBlock *Block) { BB = Block; }
+
+  typedef MemoryAccessVec::iterator iterator;
+  typedef MemoryAccessVec::const_iterator const_iterator;
+
+  iterator begin() { return MemAccs.begin(); }
+  iterator end() { return MemAccs.end(); }
+  const_iterator begin() const { return MemAccs.begin(); }
+  const_iterator end() const { return MemAccs.end(); }
+
+  unsigned getNumParams() const;
+  unsigned getNumIterators() const;
+  unsigned getNumScattering() const;
+
+  Scop *getParent() { return &Parent; }
+  const Scop *getParent() const { return &Parent; }
+
+  const char *getBaseName() const;
+
+  /// @brief Restrict the domain of the statement.
+  ///
+  /// @param NewDomain The new statement domain.
+  void restrictDomain(__isl_take isl_set *NewDomain);
+
+  /// @brief Get the loop for a dimension.
+  ///
+  /// @param Dimension The dimension of the induction variable
+  /// @return The loop at a certain dimension.
+  const Loop *getLoopForDimension(unsigned Dimension) const;
+
+  /// @brief Align the parameters in the statement to the scop context
+  void realignParams();
+
+  /// @brief Print the ScopStmt.
+  ///
+  /// @param OS The output stream the ScopStmt is printed to.
+  void print(raw_ostream &OS) const;
+
+  /// @brief Print the ScopStmt to stderr.
+  void dump() const;
+};
+
+/// @brief Print ScopStmt S to raw_ostream O.
+static inline raw_ostream &operator<<(raw_ostream &O, const ScopStmt &S) {
+  S.print(O);
+  return O;
+}
+
+///===----------------------------------------------------------------------===//
+/// @brief Static Control Part
+///
+/// A Scop is the polyhedral representation of a control flow region detected
+/// by the Scop detection. It is generated by translating the LLVM-IR and
+/// abstracting its effects.
+///
+/// A Scop consists of a set of:
+///
+///   * A set of statements executed in the Scop.
+///
+///   * A set of global parameters
+///   Those parameters are scalar integer values, which are constant during
+///   execution.
+///
+///   * A context
+///   This context contains information about the values the parameters
+///   can take and relations between different parameters.
+class Scop {
+public:
+  /// @brief Type to represent a pair of minimal/maximal access to an array.
+  using MinMaxAccessTy = std::pair<isl_pw_multi_aff *, isl_pw_multi_aff *>;
+
+  /// @brief Vector of minimal/maximal accesses to different arrays.
+  using MinMaxVectorTy = SmallVector<MinMaxAccessTy, 4>;
+
+  /// @brief Vector of minimal/maximal access vectors one for each alias group.
+  using MinMaxVectorVectorTy = SmallVector<MinMaxVectorTy *, 4>;
+
+private:
+  Scop(const Scop &) LLVM_DELETED_FUNCTION;
+  const Scop &operator=(const Scop &) LLVM_DELETED_FUNCTION;
+
+  ScalarEvolution *SE;
+
+  /// The underlying Region.
+  Region &R;
+
+  /// Max loop depth.
+  unsigned MaxLoopDepth;
+
+  typedef std::vector<ScopStmt *> StmtSet;
+  /// The statements in this Scop.
+  StmtSet Stmts;
+
+  /// Parameters of this Scop
+  typedef SmallVector<const SCEV *, 8> ParamVecType;
+  ParamVecType Parameters;
+
+  /// The isl_ids that are used to represent the parameters
+  typedef std::map<const SCEV *, int> ParamIdType;
+  ParamIdType ParameterIds;
+
+  /// Isl context.
+  isl_ctx *IslCtx;
+
+  /// @brief A map from basic blocks to SCoP statements.
+  DenseMap<BasicBlock *, ScopStmt *> StmtMap;
+
+  /// Constraints on parameters.
+  isl_set *Context;
+
+  /// @brief A map to remember ScopArrayInfo objects for all base pointers.
+  DenseMap<const Value *, const ScopArrayInfo *> ScopArrayInfoMap;
+
+  /// @brief The assumptions under which this scop was built.
+  ///
+  /// When constructing a scop sometimes the exact representation of a statement
+  /// or condition would be very complex, but there is a common case which is a
+  /// lot simpler, but which is only valid under certain assumptions. The
+  /// assumed context records the assumptions taken during the construction of
+  /// this scop and that need to be code generated as a run-time test.
+  isl_set *AssumedContext;
+
+  /// @brief The set of minimal/maximal accesses for each alias group.
+  ///
+  /// When building runtime alias checks we look at all memory instructions and
+  /// build so called alias groups. Each group contains a set of accesses to
+  /// different base arrays which might alias with each other. However, between
+  /// alias groups there is no aliasing possible.
+  ///
+  /// In a program with int and float pointers annotated with tbaa information
+  /// we would probably generate two alias groups, one for the int pointers and
+  /// one for the float pointers.
+  ///
+  /// During code generation we will create a runtime alias check for each alias
+  /// group to ensure the SCoP is executed in an alias free environment.
+  MinMaxVectorVectorTy MinMaxAliasGroups;
+
+  /// Create the static control part with a region, max loop depth of this
+  /// region and parameters used in this region.
+  Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, isl_ctx *ctx);
+
+  /// @brief Check if a basic block is trivial.
+  ///
+  /// A trivial basic block does not contain any useful calculation. Therefore,
+  /// it does not need to be represented as a polyhedral statement.
+  ///
+  /// @param BB The basic block to check
+  /// @param tempScop TempScop returning further information regarding the Scop.
+  ///
+  /// @return True if the basic block is trivial, otherwise false.
+  static bool isTrivialBB(BasicBlock *BB, TempScop &tempScop);
+
+  /// @brief Build the Context of the Scop.
+  void buildContext();
+
+  /// @brief Add the bounds of the parameters to the context.
+  void addParameterBounds();
+
+  /// @brief Simplify the assumed context.
+  void simplifyAssumedContext();
+
+  /// Build the Scop and Statement with precalculated scop information.
+  void buildScop(TempScop &TempScop, const Region &CurRegion,
+                 // Loops in Scop containing CurRegion
+                 SmallVectorImpl<Loop *> &NestLoops,
+                 // The scattering numbers
+                 SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI);
+
+  /// @name Helper function for printing the Scop.
+  ///
+  ///{
+  void printContext(raw_ostream &OS) const;
+  void printStatements(raw_ostream &OS) const;
+  void printAliasAssumptions(raw_ostream &OS) const;
+  ///}
+
+  friend class ScopInfo;
+
+public:
+  ~Scop();
+
+  ScalarEvolution *getSE() const;
+
+  /// @brief Get the count of parameters used in this Scop.
+  ///
+  /// @return The count of parameters used in this Scop.
+  inline ParamVecType::size_type getNumParams() const {
+    return Parameters.size();
+  }
+
+  /// @brief Get a set containing the parameters used in this Scop
+  ///
+  /// @return The set containing the parameters used in this Scop.
+  inline const ParamVecType &getParams() const { return Parameters; }
+
+  /// @brief Take a list of parameters and add the new ones to the scop.
+  void addParams(std::vector<const SCEV *> NewParameters);
+
+  /// @brief Return the isl_id that represents a certain parameter.
+  ///
+  /// @param Parameter A SCEV that was recognized as a Parameter.
+  ///
+  /// @return The corresponding isl_id or NULL otherwise.
+  isl_id *getIdForParam(const SCEV *Parameter) const;
+
+  /// @name Parameter Iterators
+  ///
+  /// These iterators iterate over all parameters of this Scop.
+  //@{
+  typedef ParamVecType::iterator param_iterator;
+  typedef ParamVecType::const_iterator const_param_iterator;
+
+  param_iterator param_begin() { return Parameters.begin(); }
+  param_iterator param_end() { return Parameters.end(); }
+  const_param_iterator param_begin() const { return Parameters.begin(); }
+  const_param_iterator param_end() const { return Parameters.end(); }
+  //@}
+
+  /// @brief Get the maximum region of this static control part.
+  ///
+  /// @return The maximum region of this static control part.
+  inline const Region &getRegion() const { return R; }
+  inline Region &getRegion() { return R; }
+
+  /// @brief Get the maximum depth of the loop.
+  ///
+  /// @return The maximum depth of the loop.
+  inline unsigned getMaxLoopDepth() const { return MaxLoopDepth; }
+
+  /// @brief Get the scattering dimension number of this Scop.
+  ///
+  /// @return The scattering dimension number of this Scop.
+  inline unsigned getScatterDim() const {
+    unsigned maxScatterDim = 0;
+
+    for (const_iterator SI = begin(), SE = end(); SI != SE; ++SI)
+      maxScatterDim = std::max(maxScatterDim, (*SI)->getNumScattering());
+
+    return maxScatterDim;
+  }
+
+  /// @brief Get the name of this Scop.
+  std::string getNameStr() const;
+
+  /// @brief Get the constraint on parameter of this Scop.
+  ///
+  /// @return The constraint on parameter of this Scop.
+  __isl_give isl_set *getContext() const;
+  __isl_give isl_space *getParamSpace() const;
+
+  /// @brief Get the assumed context for this Scop.
+  ///
+  /// @return The assumed context of this Scop.
+  __isl_give isl_set *getAssumedContext() const;
+
+  /// @brief Add assumptions to assumed context.
+  ///
+  /// The assumptions added will be assumed to hold during the execution of the
+  /// scop. However, as they are generally not statically provable, at code
+  /// generation time run-time checks will be generated that ensure the
+  /// assumptions hold.
+  ///
+  /// WARNING: We currently exploit in simplifyAssumedContext the knowledge
+  ///          that assumptions do not change the set of statement instances
+  ///          executed.
+  ///
+  /// @param Set A set describing relations between parameters that are assumed
+  ///            to hold.
+  void addAssumption(__isl_take isl_set *Set);
+
+  /// @brief Build all alias groups for this SCoP.
+  ///
+  /// @returns True if __no__ error occurred, false otherwise.
+  bool buildAliasGroups(AliasAnalysis &AA);
+
+  //// @brief Drop all constant dimensions from statment schedules.
+  ///
+  ///  Schedule dimensions that are constant accross the scop do not carry
+  ///  any information, but would cost compile time due to the increased number
+  ///  of scheduling dimensions. To not pay this cost, we remove them.
+  void dropConstantScheduleDims();
+
+  /// @brief Return all alias groups for this SCoP.
+  const MinMaxVectorVectorTy &getAliasGroups() const {
+    return MinMaxAliasGroups;
+  }
+
+  /// @brief Get an isl string representing the context.
+  std::string getContextStr() const;
+
+  /// @brief Get an isl string representing the assumed context.
+  std::string getAssumedContextStr() const;
+
+  /// @brief Return the stmt for the given @p BB or nullptr if none.
+  ScopStmt *getStmtForBasicBlock(BasicBlock *BB) const;
+
+  /// @name Statements Iterators
+  ///
+  /// These iterators iterate over all statements of this Scop.
+  //@{
+  typedef StmtSet::iterator iterator;
+  typedef StmtSet::const_iterator const_iterator;
+
+  iterator begin() { return Stmts.begin(); }
+  iterator end() { return Stmts.end(); }
+  const_iterator begin() const { return Stmts.begin(); }
+  const_iterator end() const { return Stmts.end(); }
+
+  typedef StmtSet::reverse_iterator reverse_iterator;
+  typedef StmtSet::const_reverse_iterator const_reverse_iterator;
+
+  reverse_iterator rbegin() { return Stmts.rbegin(); }
+  reverse_iterator rend() { return Stmts.rend(); }
+  const_reverse_iterator rbegin() const { return Stmts.rbegin(); }
+  const_reverse_iterator rend() const { return Stmts.rend(); }
+  //@}
+
+  /// @brief Return the (possibly new) ScopArrayInfo object for @p Access.
+  const ScopArrayInfo *
+  getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType,
+                           const SmallVector<const SCEV *, 4> &Sizes);
+
+  /// @brief Return the cached ScopArrayInfo object for @p BasePtr.
+  const ScopArrayInfo *getScopArrayInfo(Value *BasePtr);
+
+  void setContext(isl_set *NewContext);
+
+  /// @brief Align the parameters in the statement to the scop context
+  void realignParams();
+
+  /// @brief Print the static control part.
+  ///
+  /// @param OS The output stream the static control part is printed to.
+  void print(raw_ostream &OS) const;
+
+  /// @brief Print the ScopStmt to stderr.
+  void dump() const;
+
+  /// @brief Get the isl context of this static control part.
+  ///
+  /// @return The isl context of this static control part.
+  isl_ctx *getIslCtx() const;
+
+  /// @brief Get a union set containing the iteration domains of all statements.
+  __isl_give isl_union_set *getDomains();
+
+  /// @brief Get a union map of all may-writes performed in the SCoP.
+  __isl_give isl_union_map *getMayWrites();
+
+  /// @brief Get a union map of all must-writes performed in the SCoP.
+  __isl_give isl_union_map *getMustWrites();
+
+  /// @brief Get a union map of all writes performed in the SCoP.
+  __isl_give isl_union_map *getWrites();
+
+  /// @brief Get a union map of all reads performed in the SCoP.
+  __isl_give isl_union_map *getReads();
+
+  /// @brief Get the schedule of all the statements in the SCoP.
+  __isl_give isl_union_map *getSchedule();
+
+  /// @brief Intersects the domains of all statements in the SCoP.
+  ///
+  /// @return true if a change was made
+  bool restrictDomains(__isl_take isl_union_set *Domain);
+};
+
+/// @brief Print Scop scop to raw_ostream O.
+static inline raw_ostream &operator<<(raw_ostream &O, const Scop &scop) {
+  scop.print(O);
+  return O;
+}
+
+///===---------------------------------------------------------------------===//
+/// @brief Build the Polly IR (Scop and ScopStmt) on a Region.
+///
+class ScopInfo : public RegionPass {
+  //===-------------------------------------------------------------------===//
+  ScopInfo(const ScopInfo &) LLVM_DELETED_FUNCTION;
+  const ScopInfo &operator=(const ScopInfo &) LLVM_DELETED_FUNCTION;
+
+  // The Scop
+  Scop *scop;
+  isl_ctx *ctx;
+
+  void clear() {
+    if (scop) {
+      delete scop;
+      scop = 0;
+    }
+  }
+
+public:
+  static char ID;
+  explicit ScopInfo();
+  ~ScopInfo();
+
+  /// @brief Try to build the Polly IR of static control part on the current
+  ///        SESE-Region.
+  ///
+  /// @return If the current region is a valid for a static control part,
+  ///         return the Polly IR representing this static control part,
+  ///         return null otherwise.
+  Scop *getScop() { return scop; }
+  const Scop *getScop() const { return scop; }
+
+  /// @name RegionPass interface
+  //@{
+  virtual bool runOnRegion(Region *R, RGPassManager &RGM);
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual void releaseMemory() { clear(); }
+  virtual void print(raw_ostream &OS, const Module *) const {
+    if (scop)
+      scop->print(OS);
+    else
+      OS << "Invalid Scop!\n";
+  }
+  //@}
+};
+
+} // end namespace polly
+
+namespace llvm {
+class PassRegistry;
+void initializeScopInfoPass(llvm::PassRegistry &);
+}
+
+#endif
diff --git a/final/include/polly/ScopPass.h b/final/include/polly/ScopPass.h
new file mode 100644
index 0000000..3d5373a
--- /dev/null
+++ b/final/include/polly/ScopPass.h
@@ -0,0 +1,63 @@
+//===--------- ScopPass.h - Pass for Static Control Parts --------*-C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ScopPass class.  ScopPasses are just RegionPasses,
+// except they operate on Polly IR (Scop and ScopStmt) built by ScopInfo Pass.
+// Because they operate on Polly IR, not the LLVM IR, ScopPasses are not allowed
+// to modify the LLVM IR. Due to this limitation, the ScopPass class takes
+// care of declaring that no LLVM passes are invalidated.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SCOP_PASS_H
+#define POLLY_SCOP_PASS_H
+
+#include "llvm/Analysis/RegionPass.h"
+
+using namespace llvm;
+
+struct isl_ctx;
+
+namespace polly {
+class Scop;
+
+/// ScopPass - This class adapts the RegionPass interface to allow convenient
+/// creation of passes that operate on the Polly IR. Instead of overriding
+/// runOnRegion, subclasses override runOnScop.
+class ScopPass : public RegionPass {
+  Scop *S;
+
+protected:
+  explicit ScopPass(char &ID) : RegionPass(ID), S(0) {}
+
+  /// runOnScop - This method must be overloaded to perform the
+  /// desired Polyhedral transformation or analysis.
+  ///
+  virtual bool runOnScop(Scop &S) = 0;
+
+  /// getAnalysisUsage - Subclasses that override getAnalysisUsage
+  /// must call this.
+  ///
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+
+public:
+  Scop &getCurScop() const {
+    assert(S && "Not on a Scop!");
+    return *S;
+  }
+
+private:
+  virtual bool runOnRegion(Region *R, RGPassManager &RGM);
+  void print(raw_ostream &OS, const Module *) const;
+  virtual void printScop(raw_ostream &OS) const {}
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/final/include/polly/Support/GICHelper.h b/final/include/polly/Support/GICHelper.h
new file mode 100644
index 0000000..c5fb4a1
--- /dev/null
+++ b/final/include/polly/Support/GICHelper.h
@@ -0,0 +1,80 @@
+//===- Support/GICHelper.h -- Helper functions for ISL --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Helper functions for isl objects.
+//
+//===----------------------------------------------------------------------===//
+//
+#ifndef POLLY_SUPPORT_GIC_HELPER_H
+#define POLLY_SUPPORT_GIC_HELPER_H
+
+#include "llvm/ADT/APInt.h"
+#include "isl/ctx.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <string>
+
+struct isl_map;
+struct isl_union_map;
+struct isl_set;
+struct isl_union_set;
+struct isl_schedule;
+struct isl_multi_aff;
+struct isl_pw_multi_aff;
+struct isl_aff;
+struct isl_pw_aff;
+struct isl_val;
+
+namespace llvm {
+class Value;
+}
+
+namespace polly {
+__isl_give isl_val *isl_valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
+                                     bool IsSigned);
+llvm::APInt APIntFromVal(__isl_take isl_val *Val);
+
+/// @brief Get c++ string from Isl objects.
+//@{
+std::string stringFromIslObj(__isl_keep isl_map *map);
+std::string stringFromIslObj(__isl_keep isl_union_map *umap);
+std::string stringFromIslObj(__isl_keep isl_set *set);
+std::string stringFromIslObj(__isl_keep isl_union_set *uset);
+std::string stringFromIslObj(__isl_keep isl_schedule *schedule);
+std::string stringFromIslObj(__isl_keep isl_multi_aff *maff);
+std::string stringFromIslObj(__isl_keep isl_pw_multi_aff *pma);
+std::string stringFromIslObj(__isl_keep isl_aff *aff);
+std::string stringFromIslObj(__isl_keep isl_pw_aff *pwaff);
+//@}
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                     __isl_keep isl_union_map *Map) {
+  OS << polly::stringFromIslObj(Map);
+  return OS;
+}
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                     __isl_keep isl_map *Map) {
+  OS << polly::stringFromIslObj(Map);
+  return OS;
+}
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                     __isl_keep isl_pw_multi_aff *PMA) {
+  OS << polly::stringFromIslObj(PMA);
+  return OS;
+}
+
+/// @brief Return @p Prefix + @p Val->getName() + @p Suffix but Isl compatible.
+std::string getIslCompatibleName(std::string Prefix, const llvm::Value *Val,
+                                 std::string Suffix);
+
+} // end namespace polly
+
+#endif
diff --git a/final/include/polly/Support/SCEVValidator.h b/final/include/polly/Support/SCEVValidator.h
new file mode 100644
index 0000000..17294ce
--- /dev/null
+++ b/final/include/polly/Support/SCEVValidator.h
@@ -0,0 +1,56 @@
+//===--- SCEVValidator.h - Detect Scops -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Checks if a SCEV expression represents a valid affine expression.
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SCEV_VALIDATOR_H
+#define POLLY_SCEV_VALIDATOR_H
+
+#include "llvm/ADT/SetVector.h"
+#include <vector>
+
+namespace llvm {
+class Region;
+class SCEV;
+class ScalarEvolution;
+class Value;
+class Loop;
+}
+
+namespace polly {
+/// @brief Find the loops referenced from a SCEV expression.
+///
+/// @param Expr The SCEV expression to scan for loops.
+/// @param Loops A vector into which the found loops are inserted.
+void findLoops(const llvm::SCEV *Expr,
+               llvm::SetVector<const llvm::Loop *> &Loops);
+
+/// @brief Find the values referenced by SCEVUnknowns in a given SCEV
+/// expression.
+///
+/// @param Expr The SCEV expression to scan for SCEVUnknowns.
+/// @param Expr A vector into which the found values are inserted.
+void findValues(const llvm::SCEV *Expr, llvm::SetVector<llvm::Value *> &Values);
+
+/// Returns true when the SCEV contains references to instructions within the
+/// region.
+///
+/// @param S The SCEV to analyze.
+/// @param R The region in which we look for dependences.
+bool hasScalarDepsInsideRegion(const llvm::SCEV *S, const llvm::Region *R);
+bool isAffineExpr(const llvm::Region *R, const llvm::SCEV *Expression,
+                  llvm::ScalarEvolution &SE,
+                  const llvm::Value *BaseAddress = 0);
+std::vector<const llvm::SCEV *>
+getParamsInAffineExpr(const llvm::Region *R, const llvm::SCEV *Expression,
+                      llvm::ScalarEvolution &SE,
+                      const llvm::Value *BaseAddress = 0);
+}
+
+#endif
diff --git a/final/include/polly/Support/ScopHelper.h b/final/include/polly/Support/ScopHelper.h
new file mode 100644
index 0000000..9277c22
--- /dev/null
+++ b/final/include/polly/Support/ScopHelper.h
@@ -0,0 +1,76 @@
+//===------ Support/ScopHelper.h -- Some Helper Functions for Scop. -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Small functions that help with LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_SUPPORT_IRHELPER_H
+#define POLLY_SUPPORT_IRHELPER_H
+
+namespace llvm {
+class Type;
+class Instruction;
+class LoopInfo;
+class Loop;
+class ScalarEvolution;
+class SCEV;
+class Value;
+class PHINode;
+class Region;
+class Pass;
+class BasicBlock;
+}
+
+namespace polly {
+class Scop;
+/// Temporary Hack for extended regiontree.
+///
+/// @brief Cast the region to loop.
+///
+/// @param R  The Region to be casted.
+/// @param LI The LoopInfo to help the casting.
+///
+/// @return If there is a a loop that has the same entry and exit as the region,
+///         return the loop, otherwise, return null.
+llvm::Loop *castToLoop(const llvm::Region &R, llvm::LoopInfo &LI);
+
+/// @brief Check if the PHINode has any incoming Invoke edge.
+///
+/// @param PN The PHINode to check.
+///
+/// @return If the PHINode has an incoming BB that jumps to the parent BB
+///         of the PHINode with an invoke instruction, return true,
+///         otherwise, return false.
+bool hasInvokeEdge(const llvm::PHINode *PN);
+
+llvm::Value *getPointerOperand(llvm::Instruction &Inst);
+llvm::BasicBlock *createSingleExitEdge(llvm::Region *R, llvm::Pass *P);
+
+/// @brief Return the type of the access.
+llvm::Type *getAccessInstType(llvm::Instruction *AccInst);
+
+/// @brief Simplify the region in a SCoP to have a single unconditional entry
+///        edge and a single exit edge.
+///
+/// @param S  The SCoP that is simplified.
+/// @param P  The pass that is currently running.
+///
+/// @return The unique entering block for the region.
+llvm::BasicBlock *simplifyRegion(polly::Scop *S, llvm::Pass *P);
+
+/// @brief Split the entry block of a function to store the newly inserted
+///        allocations outside of all Scops.
+///
+/// @param EntryBlock The entry block of the current function.
+/// @param P          The pass that currently running.
+///
+void splitEntryBlockForAlloca(llvm::BasicBlock *EntryBlock, llvm::Pass *P);
+}
+#endif
diff --git a/final/include/polly/TempScopInfo.h b/final/include/polly/TempScopInfo.h
new file mode 100644
index 0000000..cc23ccc
--- /dev/null
+++ b/final/include/polly/TempScopInfo.h
@@ -0,0 +1,302 @@
+//===-------- polly/TempScopInfo.h - Extract TempScops ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Collect information about the control flow regions detected by the Scop
+// detection, such that this information can be translated info its polyhedral
+// representation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_TEMP_SCOP_EXTRACTION_H
+#define POLLY_TEMP_SCOP_EXTRACTION_H
+
+#include "polly/ScopDetection.h"
+
+#include "llvm/Analysis/RegionPass.h"
+#include "llvm/IR/Instructions.h"
+
+namespace llvm {
+class DataLayout;
+}
+
+using namespace llvm;
+
+namespace polly {
+
+extern bool PollyDelinearize;
+
+//===---------------------------------------------------------------------===//
+/// @brief A memory access described by a SCEV expression and the access type.
+class IRAccess {
+public:
+  Value *BaseAddress;
+
+  const SCEV *Offset;
+
+  // The type of the scev affine function
+  enum TypeKind {
+    READ = 0x1,
+    MUST_WRITE = 0x2,
+    MAY_WRITE = 0x3,
+  };
+
+private:
+  unsigned ElemBytes;
+  TypeKind Type;
+  bool IsAffine;
+
+public:
+  SmallVector<const SCEV *, 4> Subscripts, Sizes;
+
+  explicit IRAccess(TypeKind Type, Value *BaseAddress, const SCEV *Offset,
+                    unsigned elemBytes, bool Affine,
+                    SmallVector<const SCEV *, 4> Subscripts,
+                    SmallVector<const SCEV *, 4> Sizes)
+      : BaseAddress(BaseAddress), Offset(Offset), ElemBytes(elemBytes),
+        Type(Type), IsAffine(Affine), Subscripts(Subscripts), Sizes(Sizes) {}
+
+  enum TypeKind getType() const { return Type; }
+
+  Value *getBase() const { return BaseAddress; }
+
+  const SCEV *getOffset() const { return Offset; }
+
+  unsigned getElemSizeInBytes() const { return ElemBytes; }
+
+  bool isAffine() const { return IsAffine; }
+
+  bool isRead() const { return Type == READ; }
+
+  bool isWrite() const { return Type == MUST_WRITE; }
+
+  bool isMayWrite() const { return Type == MAY_WRITE; }
+
+  bool isScalar() const { return Subscripts.size() == 0; }
+
+  void print(raw_ostream &OS) const;
+};
+
+class Comparison {
+  const SCEV *LHS;
+  const SCEV *RHS;
+
+  ICmpInst::Predicate Pred;
+
+public:
+  Comparison(const SCEV *LHS, const SCEV *RHS, ICmpInst::Predicate Pred)
+      : LHS(LHS), RHS(RHS), Pred(Pred) {}
+
+  const SCEV *getLHS() const { return LHS; }
+  const SCEV *getRHS() const { return RHS; }
+
+  ICmpInst::Predicate getPred() const { return Pred; }
+  void print(raw_ostream &OS) const;
+};
+
+//===---------------------------------------------------------------------===//
+/// Types
+// The condition of a Basicblock, combine brcond with "And" operator.
+typedef SmallVector<Comparison, 4> BBCond;
+
+/// Maps from a loop to the affine function expressing its backedge taken count.
+/// The backedge taken count already enough to express iteration domain as we
+/// only allow loops with canonical induction variable.
+/// A canonical induction variable is:
+/// an integer recurrence that starts at 0 and increments by one each time
+/// through the loop.
+typedef std::map<const Loop *, const SCEV *> LoopBoundMapType;
+
+/// Mapping BBs to its condition constrains
+typedef std::map<const BasicBlock *, BBCond> BBCondMapType;
+
+typedef std::vector<std::pair<IRAccess, Instruction *>> AccFuncSetType;
+typedef std::map<const BasicBlock *, AccFuncSetType> AccFuncMapType;
+
+//===---------------------------------------------------------------------===//
+/// @brief Scop represent with llvm objects.
+///
+/// A helper class for remembering the parameter number and the max depth in
+/// this Scop, and others context.
+class TempScop {
+  // The Region.
+  Region &R;
+
+  // Remember the bounds of loops, to help us build iteration domain of BBs.
+  const BBCondMapType &BBConds;
+
+  // Access function of bbs.
+  const AccFuncMapType &AccFuncMap;
+
+  friend class TempScopInfo;
+
+  explicit TempScop(Region &r, BBCondMapType &BBCmps,
+                    AccFuncMapType &accFuncMap)
+      : R(r), BBConds(BBCmps), AccFuncMap(accFuncMap) {}
+
+public:
+  ~TempScop();
+
+  /// @brief Get the maximum Region contained by this Scop.
+  ///
+  /// @return The maximum Region contained by this Scop.
+  Region &getMaxRegion() const { return R; }
+
+  /// @brief Get the condition from entry block of the Scop to a BasicBlock
+  ///
+  /// @param BB The BasicBlock
+  ///
+  /// @return The condition from entry block of the Scop to a BB
+  ///
+  const BBCond *getBBCond(const BasicBlock *BB) const {
+    BBCondMapType::const_iterator at = BBConds.find(BB);
+    return at != BBConds.end() ? &(at->second) : 0;
+  }
+
+  /// @brief Get all access functions in a BasicBlock
+  ///
+  /// @param  BB The BasicBlock that containing the access functions.
+  ///
+  /// @return All access functions in BB
+  ///
+  const AccFuncSetType *getAccessFunctions(const BasicBlock *BB) const {
+    AccFuncMapType::const_iterator at = AccFuncMap.find(BB);
+    return at != AccFuncMap.end() ? &(at->second) : 0;
+  }
+  //@}
+
+  /// @brief Print the Temporary Scop information.
+  ///
+  /// @param OS The output stream the access functions is printed to.
+  /// @param SE The ScalarEvolution that help printing Temporary Scop
+  ///           information.
+  /// @param LI The LoopInfo that help printing the access functions.
+  void print(raw_ostream &OS, ScalarEvolution *SE, LoopInfo *LI) const;
+
+  /// @brief Print the access functions and loop bounds in this Scop.
+  ///
+  /// @param OS The output stream the access functions is printed to.
+  /// @param SE The ScalarEvolution that help printing the access functions.
+  /// @param LI The LoopInfo that help printing the access functions.
+  void printDetail(raw_ostream &OS, ScalarEvolution *SE, LoopInfo *LI,
+                   const Region *Reg, unsigned ind) const;
+};
+
+typedef std::map<const Region *, TempScop *> TempScopMapType;
+//===----------------------------------------------------------------------===//
+/// @brief The Function Pass to extract temporary information for Static control
+///        part in llvm function.
+///
+class TempScopInfo : public FunctionPass {
+  //===-------------------------------------------------------------------===//
+  TempScopInfo(const TempScopInfo &) LLVM_DELETED_FUNCTION;
+  const TempScopInfo &operator=(const TempScopInfo &) LLVM_DELETED_FUNCTION;
+
+  // The ScalarEvolution to help building Scop.
+  ScalarEvolution *SE;
+
+  // LoopInfo for information about loops
+  LoopInfo *LI;
+
+  // The AliasAnalysis to build AliasSetTracker.
+  AliasAnalysis *AA;
+
+  // Valid Regions for Scop
+  ScopDetection *SD;
+
+  // For condition extraction support.
+  DominatorTree *DT;
+  PostDominatorTree *PDT;
+
+  // Target data for element size computing.
+  const DataLayout *TD;
+
+  // And also Remember the constrains for BBs
+  BBCondMapType BBConds;
+
+  // Access function of statements (currently BasicBlocks) .
+  AccFuncMapType AccFuncMap;
+
+  // Pre-created zero for the scalar accesses, with it we do not need create a
+  // zero scev every time when we need it.
+  const SCEV *ZeroOffset;
+
+  // Mapping regions to the corresponding Scop in current function.
+  TempScopMapType TempScops;
+
+  // Clear the context.
+  void clear();
+
+  /// @brief Build condition constrains to BBs in a valid Scop.
+  ///
+  /// @param BB           The BasicBlock to build condition constrains
+  /// @param RegionEntry  The entry block of the Smallest Region that containing
+  ///                     BB
+  void buildCondition(BasicBlock *BB, BasicBlock *RegionEntry);
+
+  // Build the affine function of the given condition
+  void buildAffineCondition(Value &V, bool inverted, Comparison **Comp) const;
+
+  // Return the temporary Scop information of Region R, where R must be a valid
+  // part of Scop
+  TempScop *getTempScop(Region &R);
+
+  // Build the temprory information of Region R, where R must be a valid part
+  // of Scop.
+  TempScop *buildTempScop(Region &R);
+
+  /// @brief Build an instance of IRAccess from the Load/Store instruction.
+  ///
+  /// @param Inst The Load/Store instruction that access the memory
+  /// @param L    The parent loop of the instruction
+  /// @param R    The region on which we are going to build a TempScop
+  ///
+  /// @return     The IRAccess to describe the access function of the
+  ///             instruction.
+  IRAccess buildIRAccess(Instruction *Inst, Loop *L, Region *R);
+
+  /// @brief Analyze and extract the cross-BB scalar dependences (or,
+  ///        dataflow dependencies) of an instruction.
+  ///
+  /// @param Inst The instruction to be analyzed
+  /// @param R    The SCoP region
+  ///
+  /// @return     True if the Instruction is used in other BB and a scalar write
+  ///             Access is required.
+  bool buildScalarDependences(Instruction *Inst, Region *R);
+
+  void buildAccessFunctions(Region &RefRegion, BasicBlock &BB);
+
+public:
+  static char ID;
+  explicit TempScopInfo() : FunctionPass(ID) {}
+  ~TempScopInfo();
+
+  /// @brief Get the temporay Scop information in LLVM IR represent
+  ///        for Region R.
+  ///
+  /// @return The Scop information in LLVM IR represent.
+  TempScop *getTempScop(const Region *R) const;
+
+  /// @name FunctionPass interface
+  //@{
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual void releaseMemory() { clear(); }
+  virtual bool runOnFunction(Function &F);
+  virtual void print(raw_ostream &OS, const Module *) const;
+  //@}
+};
+
+} // end namespace polly
+
+namespace llvm {
+class PassRegistry;
+void initializeTempScopInfoPass(llvm::PassRegistry &);
+}
+
+#endif
diff --git a/final/lib/Analysis/Dependences.cpp b/final/lib/Analysis/Dependences.cpp
new file mode 100644
index 0000000..d4d092a
--- /dev/null
+++ b/final/lib/Analysis/Dependences.cpp
@@ -0,0 +1,637 @@
+//===- Dependences.cpp - Calculate dependency information for a Scop. -----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Calculate the data dependency relations for a Scop using ISL.
+//
+// The integer set library (ISL) from Sven, has a integrated dependency analysis
+// to calculate data dependences. This pass takes advantage of this and
+// calculate those dependences a Scop.
+//
+// The dependences in this pass are exact in terms that for a specific read
+// statement instance only the last write statement instance is returned. In
+// case of may writes a set of possible write instances is returned. This
+// analysis will never produce redundant dependences.
+//
+//===----------------------------------------------------------------------===//
+//
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+#include "llvm/Support/Debug.h"
+
+#include <isl/aff.h>
+#include <isl/ctx.h>
+#include <isl/flow.h>
+#include <isl/map.h>
+#include <isl/options.h>
+#include <isl/set.h>
+
+using namespace polly;
+using namespace llvm;
+
+#define DEBUG_TYPE "polly-dependence"
+
+static cl::opt<int> OptComputeOut(
+    "polly-dependences-computeout",
+    cl::desc("Bound the dependence analysis by a maximal amount of "
+             "computational steps"),
+    cl::Hidden, cl::init(250000), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> LegalityCheckDisabled(
+    "disable-polly-legality", cl::desc("Disable polly legality check"),
+    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+enum AnalysisType { VALUE_BASED_ANALYSIS, MEMORY_BASED_ANALYSIS };
+
+static cl::opt<enum AnalysisType> OptAnalysisType(
+    "polly-dependences-analysis-type",
+    cl::desc("The kind of dependence analysis to use"),
+    cl::values(clEnumValN(VALUE_BASED_ANALYSIS, "value-based",
+                          "Exact dependences without transitive dependences"),
+               clEnumValN(MEMORY_BASED_ANALYSIS, "memory-based",
+                          "Overapproximation of dependences"),
+               clEnumValEnd),
+    cl::Hidden, cl::init(VALUE_BASED_ANALYSIS), cl::ZeroOrMore,
+    cl::cat(PollyCategory));
+
+//===----------------------------------------------------------------------===//
+Dependences::Dependences() : ScopPass(ID) { RAW = WAR = WAW = nullptr; }
+
+void Dependences::collectInfo(Scop &S, isl_union_map **Read,
+                              isl_union_map **Write, isl_union_map **MayWrite,
+                              isl_union_map **AccessSchedule,
+                              isl_union_map **StmtSchedule) {
+  isl_space *Space = S.getParamSpace();
+  *Read = isl_union_map_empty(isl_space_copy(Space));
+  *Write = isl_union_map_empty(isl_space_copy(Space));
+  *MayWrite = isl_union_map_empty(isl_space_copy(Space));
+  *AccessSchedule = isl_union_map_empty(isl_space_copy(Space));
+  *StmtSchedule = isl_union_map_empty(Space);
+
+  SmallPtrSet<const Value *, 8> ReductionBaseValues;
+  for (ScopStmt *Stmt : S)
+    for (MemoryAccess *MA : *Stmt)
+      if (MA->isReductionLike())
+        ReductionBaseValues.insert(MA->getBaseAddr());
+
+  for (ScopStmt *Stmt : S) {
+    for (MemoryAccess *MA : *Stmt) {
+      isl_set *domcp = Stmt->getDomain();
+      isl_map *accdom = MA->getAccessRelation();
+
+      accdom = isl_map_intersect_domain(accdom, domcp);
+
+      if (ReductionBaseValues.count(MA->getBaseAddr())) {
+        // Wrap the access domain and adjust the scattering accordingly.
+        //
+        // An access domain like
+        //   Stmt[i0, i1] -> MemAcc_A[i0 + i1]
+        // will be transformed into
+        //   [Stmt[i0, i1] -> MemAcc_A[i0 + i1]] -> MemAcc_A[i0 + i1]
+        //
+        // The original scattering looks like
+        //   Stmt[i0, i1] -> [0, i0, 2, i1, 0]
+        // but as we transformed the access domain we need the scattering
+        // to match the new access domains, thus we need
+        //   [Stmt[i0, i1] -> MemAcc_A[i0 + i1]] -> [0, i0, 2, i1, 0]
+        isl_map *Scatter = Stmt->getScattering();
+        Scatter = isl_map_apply_domain(
+            Scatter, isl_map_reverse(isl_map_domain_map(isl_map_copy(accdom))));
+        accdom = isl_map_range_map(accdom);
+        *AccessSchedule = isl_union_map_add_map(*AccessSchedule, Scatter);
+      }
+
+      if (MA->isRead())
+        *Read = isl_union_map_add_map(*Read, accdom);
+      else
+        *Write = isl_union_map_add_map(*Write, accdom);
+    }
+    *StmtSchedule = isl_union_map_add_map(*StmtSchedule, Stmt->getScattering());
+  }
+
+  *StmtSchedule =
+      isl_union_map_intersect_params(*StmtSchedule, S.getAssumedContext());
+}
+
+/// @brief Fix all dimension of @p Zero to 0 and add it to @p user
+static int fixSetToZero(__isl_take isl_set *Zero, void *user) {
+  isl_union_set **User = (isl_union_set **)user;
+  for (unsigned i = 0; i < isl_set_dim(Zero, isl_dim_set); i++)
+    Zero = isl_set_fix_si(Zero, isl_dim_set, i, 0);
+  *User = isl_union_set_add_set(*User, Zero);
+  return 0;
+}
+
+/// @brief Compute the privatization dependences for a given dependency @p Map
+///
+/// Privatization dependences are widened original dependences which originate
+/// or end in a reduction access. To compute them we apply the transitive close
+/// of the reduction dependences (which maps each iteration of a reduction
+/// statement to all following ones) on the RAW/WAR/WAW dependences. The
+/// dependences which start or end at a reduction statement will be extended to
+/// depend on all following reduction statement iterations as well.
+/// Note: "Following" here means according to the reduction dependences.
+///
+/// For the input:
+///
+///  S0:   *sum = 0;
+///        for (int i = 0; i < 1024; i++)
+///  S1:     *sum += i;
+///  S2:   *sum = *sum * 3;
+///
+/// we have the following dependences before we add privatization dependences:
+///
+///   RAW:
+///     { S0[] -> S1[0]; S1[1023] -> S2[] }
+///   WAR:
+///     {  }
+///   WAW:
+///     { S0[] -> S1[0]; S1[1024] -> S2[] }
+///   RED:
+///     { S1[i0] -> S1[1 + i0] : i0 >= 0 and i0 <= 1022 }
+///
+/// and afterwards:
+///
+///   RAW:
+///     { S0[] -> S1[i0] : i0 >= 0 and i0 <= 1023;
+///       S1[i0] -> S2[] : i0 >= 0 and i0 <= 1023}
+///   WAR:
+///     {  }
+///   WAW:
+///     { S0[] -> S1[i0] : i0 >= 0 and i0 <= 1023;
+///       S1[i0] -> S2[] : i0 >= 0 and i0 <= 1023}
+///   RED:
+///     { S1[i0] -> S1[1 + i0] : i0 >= 0 and i0 <= 1022 }
+///
+/// Note: This function also computes the (reverse) transitive closure of the
+///       reduction dependences.
+void Dependences::addPrivatizationDependences() {
+  isl_union_map *PrivRAW, *PrivWAW, *PrivWAR;
+
+  // The transitive closure might be over approximated, thus could lead to
+  // dependency cycles in the privatization dependences. To make sure this
+  // will not happen we remove all negative dependences after we computed
+  // the transitive closure.
+  TC_RED = isl_union_map_transitive_closure(isl_union_map_copy(RED), 0);
+
+  // FIXME: Apply the current schedule instead of assuming the identity schedule
+  //        here. The current approach is only valid as long as we compute the
+  //        dependences only with the initial (identity schedule). Any other
+  //        schedule could change "the direction of the backward dependences" we
+  //        want to eliminate here.
+  isl_union_set *UDeltas = isl_union_map_deltas(isl_union_map_copy(TC_RED));
+  isl_union_set *Universe = isl_union_set_universe(isl_union_set_copy(UDeltas));
+  isl_union_set *Zero = isl_union_set_empty(isl_union_set_get_space(Universe));
+  isl_union_set_foreach_set(Universe, fixSetToZero, &Zero);
+  isl_union_map *NonPositive = isl_union_set_lex_le_union_set(UDeltas, Zero);
+
+  TC_RED = isl_union_map_subtract(TC_RED, NonPositive);
+
+  TC_RED = isl_union_map_union(
+      TC_RED, isl_union_map_reverse(isl_union_map_copy(TC_RED)));
+  TC_RED = isl_union_map_coalesce(TC_RED);
+
+  isl_union_map **Maps[] = {&RAW, &WAW, &WAR};
+  isl_union_map **PrivMaps[] = {&PrivRAW, &PrivWAW, &PrivWAR};
+  for (unsigned u = 0; u < 3; u++) {
+    isl_union_map **Map = Maps[u], **PrivMap = PrivMaps[u];
+
+    *PrivMap = isl_union_map_apply_range(isl_union_map_copy(*Map),
+                                         isl_union_map_copy(TC_RED));
+    *PrivMap = isl_union_map_union(
+        *PrivMap, isl_union_map_apply_range(isl_union_map_copy(TC_RED),
+                                            isl_union_map_copy(*Map)));
+
+    *Map = isl_union_map_union(*Map, *PrivMap);
+  }
+
+  isl_union_set_free(Universe);
+}
+
+void Dependences::calculateDependences(Scop &S) {
+  isl_union_map *Read, *Write, *MayWrite, *AccessSchedule, *StmtSchedule,
+      *Schedule;
+
+  DEBUG(dbgs() << "Scop: \n" << S << "\n");
+
+  collectInfo(S, &Read, &Write, &MayWrite, &AccessSchedule, &StmtSchedule);
+
+  Schedule =
+      isl_union_map_union(AccessSchedule, isl_union_map_copy(StmtSchedule));
+
+  Read = isl_union_map_coalesce(Read);
+  Write = isl_union_map_coalesce(Write);
+  MayWrite = isl_union_map_coalesce(MayWrite);
+
+  long MaxOpsOld = isl_ctx_get_max_operations(S.getIslCtx());
+  isl_ctx_set_max_operations(S.getIslCtx(), OptComputeOut);
+  isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE);
+
+  DEBUG(dbgs() << "Read: " << Read << "\n";
+        dbgs() << "Write: " << Write << "\n";
+        dbgs() << "MayWrite: " << MayWrite << "\n";
+        dbgs() << "Schedule: " << Schedule << "\n");
+
+  // The pointers below will be set by the subsequent calls to
+  // isl_union_map_compute_flow.
+  RAW = WAW = WAR = RED = nullptr;
+
+  if (OptAnalysisType == VALUE_BASED_ANALYSIS) {
+    isl_union_map_compute_flow(
+        isl_union_map_copy(Read), isl_union_map_copy(Write),
+        isl_union_map_copy(MayWrite), isl_union_map_copy(Schedule), &RAW,
+        nullptr, nullptr, nullptr);
+
+    isl_union_map_compute_flow(
+        isl_union_map_copy(Write), isl_union_map_copy(Write),
+        isl_union_map_copy(Read), isl_union_map_copy(Schedule), &WAW, &WAR,
+        nullptr, nullptr);
+  } else {
+    isl_union_map *Empty;
+
+    Empty = isl_union_map_empty(isl_union_map_get_space(Write));
+    Write = isl_union_map_union(Write, isl_union_map_copy(MayWrite));
+
+    isl_union_map_compute_flow(
+        isl_union_map_copy(Read), isl_union_map_copy(Empty),
+        isl_union_map_copy(Write), isl_union_map_copy(Schedule), nullptr, &RAW,
+        nullptr, nullptr);
+
+    isl_union_map_compute_flow(
+        isl_union_map_copy(Write), isl_union_map_copy(Empty),
+        isl_union_map_copy(Read), isl_union_map_copy(Schedule), nullptr, &WAR,
+        nullptr, nullptr);
+
+    isl_union_map_compute_flow(
+        isl_union_map_copy(Write), isl_union_map_copy(Empty),
+        isl_union_map_copy(Write), isl_union_map_copy(Schedule), nullptr, &WAW,
+        nullptr, nullptr);
+    isl_union_map_free(Empty);
+  }
+
+  isl_union_map_free(MayWrite);
+  isl_union_map_free(Write);
+  isl_union_map_free(Read);
+  isl_union_map_free(Schedule);
+
+  RAW = isl_union_map_coalesce(RAW);
+  WAW = isl_union_map_coalesce(WAW);
+  WAR = isl_union_map_coalesce(WAR);
+
+  if (isl_ctx_last_error(S.getIslCtx()) == isl_error_quota) {
+    isl_union_map_free(RAW);
+    isl_union_map_free(WAW);
+    isl_union_map_free(WAR);
+    RAW = WAW = WAR = nullptr;
+    isl_ctx_reset_error(S.getIslCtx());
+  }
+  isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT);
+  isl_ctx_reset_operations(S.getIslCtx());
+  isl_ctx_set_max_operations(S.getIslCtx(), MaxOpsOld);
+
+  isl_union_map *STMT_RAW, *STMT_WAW, *STMT_WAR;
+  STMT_RAW = isl_union_map_intersect_domain(
+      isl_union_map_copy(RAW),
+      isl_union_map_domain(isl_union_map_copy(StmtSchedule)));
+  STMT_WAW = isl_union_map_intersect_domain(
+      isl_union_map_copy(WAW),
+      isl_union_map_domain(isl_union_map_copy(StmtSchedule)));
+  STMT_WAR = isl_union_map_intersect_domain(isl_union_map_copy(WAR),
+                                            isl_union_map_domain(StmtSchedule));
+  DEBUG({
+    dbgs() << "Wrapped Dependences:\n";
+    printScop(dbgs());
+    dbgs() << "\n";
+  });
+
+  // To handle reduction dependences we proceed as follows:
+  // 1) Aggregate all possible reduction dependences, namely all self
+  //    dependences on reduction like statements.
+  // 2) Intersect them with the actual RAW & WAW dependences to the get the
+  //    actual reduction dependences. This will ensure the load/store memory
+  //    addresses were __identical__ in the two iterations of the statement.
+  // 3) Relax the original RAW and WAW dependences by substracting the actual
+  //    reduction dependences. Binary reductions (sum += A[i]) cause both, and
+  //    the same, RAW and WAW dependences.
+  // 4) Add the privatization dependences which are widened versions of
+  //    already present dependences. They model the effect of manual
+  //    privatization at the outermost possible place (namely after the last
+  //    write and before the first access to a reduction location).
+
+  // Step 1)
+  RED = isl_union_map_empty(isl_union_map_get_space(RAW));
+  for (ScopStmt *Stmt : S) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isReductionLike())
+        continue;
+      isl_set *AccDomW = isl_map_wrap(MA->getAccessRelation());
+      isl_map *Identity =
+          isl_map_from_domain_and_range(isl_set_copy(AccDomW), AccDomW);
+      RED = isl_union_map_add_map(RED, Identity);
+    }
+  }
+
+  // Step 2)
+  RED = isl_union_map_intersect(RED, isl_union_map_copy(RAW));
+  RED = isl_union_map_intersect(RED, isl_union_map_copy(WAW));
+
+  if (!isl_union_map_is_empty(RED)) {
+
+    // Step 3)
+    RAW = isl_union_map_subtract(RAW, isl_union_map_copy(RED));
+    WAW = isl_union_map_subtract(WAW, isl_union_map_copy(RED));
+
+    // Step 4)
+    addPrivatizationDependences();
+  }
+
+  DEBUG({
+    dbgs() << "Final Wrapped Dependences:\n";
+    printScop(dbgs());
+    dbgs() << "\n";
+  });
+
+  // RED_SIN is used to collect all reduction dependences again after we
+  // split them according to the causing memory accesses. The current assumption
+  // is that our method of splitting will not have any leftovers. In the end
+  // we validate this assumption until we have more confidence in this method.
+  isl_union_map *RED_SIN = isl_union_map_empty(isl_union_map_get_space(RAW));
+
+  // For each reduction like memory access, check if there are reduction
+  // dependences with the access relation of the memory access as a domain
+  // (wrapped space!). If so these dependences are caused by this memory access.
+  // We then move this portion of reduction dependences back to the statement ->
+  // statement space and add a mapping from the memory access to these
+  // dependences.
+  for (ScopStmt *Stmt : S) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isReductionLike())
+        continue;
+
+      isl_set *AccDomW = isl_map_wrap(MA->getAccessRelation());
+      isl_union_map *AccRedDepU = isl_union_map_intersect_domain(
+          isl_union_map_copy(TC_RED), isl_union_set_from_set(AccDomW));
+      if (isl_union_map_is_empty(AccRedDepU) && !isl_union_map_free(AccRedDepU))
+        continue;
+
+      isl_map *AccRedDep = isl_map_from_union_map(AccRedDepU);
+      RED_SIN = isl_union_map_add_map(RED_SIN, isl_map_copy(AccRedDep));
+      AccRedDep = isl_map_zip(AccRedDep);
+      AccRedDep = isl_set_unwrap(isl_map_domain(AccRedDep));
+      setReductionDependences(MA, AccRedDep);
+    }
+  }
+
+  assert(isl_union_map_is_equal(RED_SIN, TC_RED) &&
+         "Intersecting the reduction dependence domain with the wrapped access "
+         "relation is not enough, we need to loosen the access relation also");
+  isl_union_map_free(RED_SIN);
+
+  RAW = isl_union_map_zip(RAW);
+  WAW = isl_union_map_zip(WAW);
+  WAR = isl_union_map_zip(WAR);
+  RED = isl_union_map_zip(RED);
+  TC_RED = isl_union_map_zip(TC_RED);
+
+  DEBUG({
+    dbgs() << "Zipped Dependences:\n";
+    printScop(dbgs());
+    dbgs() << "\n";
+  });
+
+  RAW = isl_union_set_unwrap(isl_union_map_domain(RAW));
+  WAW = isl_union_set_unwrap(isl_union_map_domain(WAW));
+  WAR = isl_union_set_unwrap(isl_union_map_domain(WAR));
+  RED = isl_union_set_unwrap(isl_union_map_domain(RED));
+  TC_RED = isl_union_set_unwrap(isl_union_map_domain(TC_RED));
+
+  DEBUG({
+    dbgs() << "Unwrapped Dependences:\n";
+    printScop(dbgs());
+    dbgs() << "\n";
+  });
+
+  RAW = isl_union_map_union(RAW, STMT_RAW);
+  WAW = isl_union_map_union(WAW, STMT_WAW);
+  WAR = isl_union_map_union(WAR, STMT_WAR);
+
+  RAW = isl_union_map_coalesce(RAW);
+  WAW = isl_union_map_coalesce(WAW);
+  WAR = isl_union_map_coalesce(WAR);
+  RED = isl_union_map_coalesce(RED);
+  TC_RED = isl_union_map_coalesce(TC_RED);
+
+  DEBUG(printScop(dbgs()));
+}
+
+void Dependences::recomputeDependences() {
+  releaseMemory();
+  calculateDependences(*S);
+}
+
+bool Dependences::runOnScop(Scop &ScopVar) {
+  S = &ScopVar;
+  recomputeDependences();
+  return false;
+}
+
+bool Dependences::isValidScattering(StatementToIslMapTy *NewScattering) {
+  Scop &S = getCurScop();
+
+  if (LegalityCheckDisabled)
+    return true;
+
+  isl_union_map *Dependences = getDependences(TYPE_RAW | TYPE_WAW | TYPE_WAR);
+  isl_space *Space = S.getParamSpace();
+  isl_union_map *Scattering = isl_union_map_empty(Space);
+
+  isl_space *ScatteringSpace = nullptr;
+
+  for (ScopStmt *Stmt : S) {
+    isl_map *StmtScat;
+
+    if (NewScattering->find(Stmt) == NewScattering->end())
+      StmtScat = Stmt->getScattering();
+    else
+      StmtScat = isl_map_copy((*NewScattering)[Stmt]);
+
+    if (!ScatteringSpace)
+      ScatteringSpace = isl_space_range(isl_map_get_space(StmtScat));
+
+    Scattering = isl_union_map_add_map(Scattering, StmtScat);
+  }
+
+  Dependences =
+      isl_union_map_apply_domain(Dependences, isl_union_map_copy(Scattering));
+  Dependences = isl_union_map_apply_range(Dependences, Scattering);
+
+  isl_set *Zero = isl_set_universe(isl_space_copy(ScatteringSpace));
+  for (unsigned i = 0; i < isl_set_dim(Zero, isl_dim_set); i++)
+    Zero = isl_set_fix_si(Zero, isl_dim_set, i, 0);
+
+  isl_union_set *UDeltas = isl_union_map_deltas(Dependences);
+  isl_set *Deltas = isl_union_set_extract_set(UDeltas, ScatteringSpace);
+  isl_union_set_free(UDeltas);
+
+  isl_map *NonPositive = isl_set_lex_le_set(Deltas, Zero);
+  bool IsValid = isl_map_is_empty(NonPositive);
+  isl_map_free(NonPositive);
+
+  return IsValid;
+}
+
+// Check if the current scheduling dimension is parallel.
+//
+// We check for parallelism by verifying that the loop does not carry any
+// dependences.
+//
+// Parallelism test: if the distance is zero in all outer dimensions, then it
+// has to be zero in the current dimension as well.
+//
+// Implementation: first, translate dependences into time space, then force
+// outer dimensions to be equal. If the distance is zero in the current
+// dimension, then the loop is parallel. The distance is zero in the current
+// dimension if it is a subset of a map with equal values for the current
+// dimension.
+bool Dependences::isParallel(isl_union_map *Schedule, isl_union_map *Deps,
+                             isl_pw_aff **MinDistancePtr) {
+  isl_set *Deltas, *Distance;
+  isl_map *ScheduleDeps;
+  unsigned Dimension;
+  bool IsParallel;
+
+  Deps = isl_union_map_apply_range(Deps, isl_union_map_copy(Schedule));
+  Deps = isl_union_map_apply_domain(Deps, isl_union_map_copy(Schedule));
+
+  if (isl_union_map_is_empty(Deps)) {
+    isl_union_map_free(Deps);
+    return true;
+  }
+
+  ScheduleDeps = isl_map_from_union_map(Deps);
+  Dimension = isl_map_dim(ScheduleDeps, isl_dim_out) - 1;
+
+  for (unsigned i = 0; i < Dimension; i++)
+    ScheduleDeps = isl_map_equate(ScheduleDeps, isl_dim_out, i, isl_dim_in, i);
+
+  Deltas = isl_map_deltas(ScheduleDeps);
+  Distance = isl_set_universe(isl_set_get_space(Deltas));
+
+  // [0, ..., 0, +] - All zeros and last dimension larger than zero
+  for (unsigned i = 0; i < Dimension; i++)
+    Distance = isl_set_fix_si(Distance, isl_dim_set, i, 0);
+
+  Distance = isl_set_lower_bound_si(Distance, isl_dim_set, Dimension, 1);
+  Distance = isl_set_intersect(Distance, Deltas);
+
+  IsParallel = isl_set_is_empty(Distance);
+  if (IsParallel || !MinDistancePtr) {
+    isl_set_free(Distance);
+    return IsParallel;
+  }
+
+  Distance = isl_set_project_out(Distance, isl_dim_set, 0, Dimension);
+  Distance = isl_set_coalesce(Distance);
+
+  // This last step will compute a expression for the minimal value in the
+  // distance polyhedron Distance with regards to the first (outer most)
+  // dimension.
+  *MinDistancePtr = isl_pw_aff_coalesce(isl_set_dim_min(Distance, 0));
+
+  return false;
+}
+
+static void printDependencyMap(raw_ostream &OS, __isl_keep isl_union_map *DM) {
+  if (DM)
+    OS << DM << "\n";
+  else
+    OS << "n/a\n";
+}
+
+void Dependences::printScop(raw_ostream &OS) const {
+  OS << "\tRAW dependences:\n\t\t";
+  printDependencyMap(OS, RAW);
+  OS << "\tWAR dependences:\n\t\t";
+  printDependencyMap(OS, WAR);
+  OS << "\tWAW dependences:\n\t\t";
+  printDependencyMap(OS, WAW);
+  OS << "\tReduction dependences:\n\t\t";
+  printDependencyMap(OS, RED);
+  OS << "\tTransitive closure of reduction dependences:\n\t\t";
+  printDependencyMap(OS, TC_RED);
+}
+
+void Dependences::releaseMemory() {
+  isl_union_map_free(RAW);
+  isl_union_map_free(WAR);
+  isl_union_map_free(WAW);
+  isl_union_map_free(RED);
+  isl_union_map_free(TC_RED);
+
+  RED = RAW = WAR = WAW = TC_RED = nullptr;
+
+  for (auto &ReductionDeps : ReductionDependences)
+    isl_map_free(ReductionDeps.second);
+  ReductionDependences.clear();
+}
+
+isl_union_map *Dependences::getDependences(int Kinds) {
+  assert(hasValidDependences() && "No valid dependences available");
+  isl_space *Space = isl_union_map_get_space(RAW);
+  isl_union_map *Deps = isl_union_map_empty(Space);
+
+  if (Kinds & TYPE_RAW)
+    Deps = isl_union_map_union(Deps, isl_union_map_copy(RAW));
+
+  if (Kinds & TYPE_WAR)
+    Deps = isl_union_map_union(Deps, isl_union_map_copy(WAR));
+
+  if (Kinds & TYPE_WAW)
+    Deps = isl_union_map_union(Deps, isl_union_map_copy(WAW));
+
+  if (Kinds & TYPE_RED)
+    Deps = isl_union_map_union(Deps, isl_union_map_copy(RED));
+
+  if (Kinds & TYPE_TC_RED)
+    Deps = isl_union_map_union(Deps, isl_union_map_copy(TC_RED));
+
+  Deps = isl_union_map_coalesce(Deps);
+  Deps = isl_union_map_detect_equalities(Deps);
+  return Deps;
+}
+
+bool Dependences::hasValidDependences() {
+  return (RAW != nullptr) && (WAR != nullptr) && (WAW != nullptr);
+}
+
+isl_map *Dependences::getReductionDependences(MemoryAccess *MA) {
+  return isl_map_copy(ReductionDependences[MA]);
+}
+
+void Dependences::setReductionDependences(MemoryAccess *MA, isl_map *D) {
+  assert(ReductionDependences.count(MA) == 0 &&
+         "Reduction dependences set twice!");
+  ReductionDependences[MA] = D;
+}
+
+void Dependences::getAnalysisUsage(AnalysisUsage &AU) const {
+  ScopPass::getAnalysisUsage(AU);
+}
+
+char Dependences::ID = 0;
+
+Pass *polly::createDependencesPass() { return new Dependences(); }
+
+INITIALIZE_PASS_BEGIN(Dependences, "polly-dependences",
+                      "Polly - Calculate dependences", false, false);
+INITIALIZE_PASS_DEPENDENCY(ScopInfo);
+INITIALIZE_PASS_END(Dependences, "polly-dependences",
+                    "Polly - Calculate dependences", false, false)
diff --git a/final/lib/Analysis/ScopDetection.cpp b/final/lib/Analysis/ScopDetection.cpp
new file mode 100644
index 0000000..abcf2c1
--- /dev/null
+++ b/final/lib/Analysis/ScopDetection.cpp
@@ -0,0 +1,979 @@
+//===----- ScopDetection.cpp  - Detect Scops --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Detect the maximal Scops of a function.
+//
+// A static control part (Scop) is a subgraph of the control flow graph (CFG)
+// that only has statically known control flow and can therefore be described
+// within the polyhedral model.
+//
+// Every Scop fullfills these restrictions:
+//
+// * It is a single entry single exit region
+//
+// * Only affine linear bounds in the loops
+//
+// Every natural loop in a Scop must have a number of loop iterations that can
+// be described as an affine linear function in surrounding loop iterators or
+// parameters. (A parameter is a scalar that does not change its value during
+// execution of the Scop).
+//
+// * Only comparisons of affine linear expressions in conditions
+//
+// * All loops and conditions perfectly nested
+//
+// The control flow needs to be structured such that it could be written using
+// just 'for' and 'if' statements, without the need for any 'goto', 'break' or
+// 'continue'.
+//
+// * Side effect free functions call
+//
+// Only function calls and intrinsics that do not have side effects are allowed
+// (readnone).
+//
+// The Scop detection finds the largest Scops by checking if the largest
+// region is a Scop. If this is not the case, its canonical subregions are
+// checked until a region is a Scop. It is now tried to extend this Scop by
+// creating a larger non canonical region.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/BlockGenerators.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/ScopDetectionDiagnostic.h"
+#include "polly/ScopDetection.h"
+#include "polly/Support/SCEVValidator.h"
+#include "polly/Support/ScopHelper.h"
+#include "polly/CodeGen/CodeGeneration.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/RegionIterator.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/Debug.h"
+#include <set>
+
+using namespace llvm;
+using namespace polly;
+
+#define DEBUG_TYPE "polly-detect"
+
+static cl::opt<bool>
+    DetectScopsWithoutLoops("polly-detect-scops-in-functions-without-loops",
+                            cl::desc("Detect scops in functions without loops"),
+                            cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                            cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    DetectRegionsWithoutLoops("polly-detect-scops-in-regions-without-loops",
+                              cl::desc("Detect scops in regions without loops"),
+                              cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                              cl::cat(PollyCategory));
+
+static cl::opt<std::string> OnlyFunction(
+    "polly-only-func",
+    cl::desc("Only run on functions that contain a certain string"),
+    cl::value_desc("string"), cl::ValueRequired, cl::init(""),
+    cl::cat(PollyCategory));
+
+static cl::opt<std::string> OnlyRegion(
+    "polly-only-region",
+    cl::desc("Only run on certain regions (The provided identifier must "
+             "appear in the name of the region's entry block"),
+    cl::value_desc("identifier"), cl::ValueRequired, cl::init(""),
+    cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    IgnoreAliasing("polly-ignore-aliasing",
+                   cl::desc("Ignore possible aliasing of the array bases"),
+                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                   cl::cat(PollyCategory));
+
+bool polly::PollyUseRuntimeAliasChecks;
+static cl::opt<bool, true> XPollyUseRuntimeAliasChecks(
+    "polly-use-runtime-alias-checks",
+    cl::desc("Use runtime alias checks to resolve possible aliasing."),
+    cl::location(PollyUseRuntimeAliasChecks), cl::Hidden, cl::ZeroOrMore,
+    cl::init(true), cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    ReportLevel("polly-report",
+                cl::desc("Print information about the activities of Polly"),
+                cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    AllowNonAffine("polly-allow-nonaffine",
+                   cl::desc("Allow non affine access functions in arrays"),
+                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                   cl::cat(PollyCategory));
+
+static cl::opt<bool> AllowUnsigned("polly-allow-unsigned",
+                                   cl::desc("Allow unsigned expressions"),
+                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                   cl::cat(PollyCategory));
+
+static cl::opt<bool, true>
+    TrackFailures("polly-detect-track-failures",
+                  cl::desc("Track failure strings in detecting scop regions"),
+                  cl::location(PollyTrackFailures), cl::Hidden, cl::ZeroOrMore,
+                  cl::init(true), cl::cat(PollyCategory));
+
+static cl::opt<bool> KeepGoing("polly-detect-keep-going",
+                               cl::desc("Do not fail on the first error."),
+                               cl::Hidden, cl::ZeroOrMore, cl::init(false),
+                               cl::cat(PollyCategory));
+
+static cl::opt<bool, true>
+    PollyDelinearizeX("polly-delinearize",
+                      cl::desc("Delinearize array access functions"),
+                      cl::location(PollyDelinearize), cl::Hidden,
+                      cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    VerifyScops("polly-detect-verify",
+                cl::desc("Verify the detected SCoPs after each transformation"),
+                cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                cl::cat(PollyCategory));
+
+bool polly::PollyTrackFailures = false;
+bool polly::PollyDelinearize = false;
+StringRef polly::PollySkipFnAttr = "polly.skip.fn";
+
+//===----------------------------------------------------------------------===//
+// Statistics.
+
+STATISTIC(ValidRegion, "Number of regions that a valid part of Scop");
+
+class DiagnosticScopFound : public DiagnosticInfo {
+private:
+  static int PluginDiagnosticKind;
+
+  Function &F;
+  std::string FileName;
+  unsigned EntryLine, ExitLine;
+
+public:
+  DiagnosticScopFound(Function &F, std::string FileName, unsigned EntryLine,
+                      unsigned ExitLine)
+      : DiagnosticInfo(PluginDiagnosticKind, DS_Note), F(F), FileName(FileName),
+        EntryLine(EntryLine), ExitLine(ExitLine) {}
+
+  virtual void print(DiagnosticPrinter &DP) const;
+
+  static bool classof(const DiagnosticInfo *DI) {
+    return DI->getKind() == PluginDiagnosticKind;
+  }
+};
+
+int DiagnosticScopFound::PluginDiagnosticKind = 10;
+
+void DiagnosticScopFound::print(DiagnosticPrinter &DP) const {
+  DP << "Polly detected an optimizable loop region (scop) in function '" << F
+     << "'\n";
+
+  if (FileName.empty()) {
+    DP << "Scop location is unknown. Compile with debug info "
+          "(-g) to get more precise information. ";
+    return;
+  }
+
+  DP << FileName << ":" << EntryLine << ": Start of scop\n";
+  DP << FileName << ":" << ExitLine << ": End of scop";
+}
+
+//===----------------------------------------------------------------------===//
+// ScopDetection.
+
+ScopDetection::ScopDetection() : FunctionPass(ID) {
+  if (!PollyUseRuntimeAliasChecks)
+    return;
+
+  // Disable runtime alias checks if we ignore aliasing all together.
+  if (IgnoreAliasing) {
+    PollyUseRuntimeAliasChecks = false;
+    return;
+  }
+
+  if (AllowNonAffine) {
+    DEBUG(errs() << "WARNING: We disable runtime alias checks as non affine "
+                    "accesses are enabled.\n");
+    PollyUseRuntimeAliasChecks = false;
+  }
+}
+
+template <class RR, typename... Args>
+inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert,
+                                   Args &&... Arguments) const {
+
+  if (!Context.Verifying) {
+    RejectLog &Log = Context.Log;
+    std::shared_ptr<RR> RejectReason = std::make_shared<RR>(Arguments...);
+
+    if (PollyTrackFailures)
+      Log.report(RejectReason);
+
+    DEBUG(dbgs() << RejectReason->getMessage());
+    DEBUG(dbgs() << "\n");
+  } else {
+    assert(!Assert && "Verification of detected scop failed");
+  }
+
+  return false;
+}
+
+bool ScopDetection::isMaxRegionInScop(const Region &R, bool Verify) const {
+  if (!ValidRegions.count(&R))
+    return false;
+
+  if (Verify)
+    return isValidRegion(const_cast<Region &>(R));
+
+  return true;
+}
+
+std::string ScopDetection::regionIsInvalidBecause(const Region *R) const {
+  if (!RejectLogs.count(R))
+    return "";
+
+  // Get the first error we found. Even in keep-going mode, this is the first
+  // reason that caused the candidate to be rejected.
+  RejectLog Errors = RejectLogs.at(R);
+
+  // This can happen when we marked a region invalid, but didn't track
+  // an error for it.
+  if (Errors.size() == 0)
+    return "";
+
+  RejectReasonPtr RR = *Errors.begin();
+  return RR->getMessage();
+}
+
+bool ScopDetection::isValidCFG(BasicBlock &BB,
+                               DetectionContext &Context) const {
+  Region &RefRegion = Context.CurRegion;
+  TerminatorInst *TI = BB.getTerminator();
+
+  // Return instructions are only valid if the region is the top level region.
+  if (isa<ReturnInst>(TI) && !RefRegion.getExit() && TI->getNumOperands() == 0)
+    return true;
+
+  BranchInst *Br = dyn_cast<BranchInst>(TI);
+
+  if (!Br)
+    return invalid<ReportNonBranchTerminator>(Context, /*Assert=*/true, &BB);
+
+  if (Br->isUnconditional())
+    return true;
+
+  Value *Condition = Br->getCondition();
+
+  // UndefValue is not allowed as condition.
+  if (isa<UndefValue>(Condition))
+    return invalid<ReportUndefCond>(Context, /*Assert=*/true, Br, &BB);
+
+  // Only Constant and ICmpInst are allowed as condition.
+  if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition)))
+    return invalid<ReportInvalidCond>(Context, /*Assert=*/true, Br, &BB);
+
+  // Allow perfectly nested conditions.
+  assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors");
+
+  if (ICmpInst *ICmp = dyn_cast<ICmpInst>(Condition)) {
+    // Unsigned comparisons are not allowed. They trigger overflow problems
+    // in the code generation.
+    //
+    // TODO: This is not sufficient and just hides bugs. However it does pretty
+    // well.
+    if (ICmp->isUnsigned() && !AllowUnsigned)
+      return false;
+
+    // Are both operands of the ICmp affine?
+    if (isa<UndefValue>(ICmp->getOperand(0)) ||
+        isa<UndefValue>(ICmp->getOperand(1)))
+      return invalid<ReportUndefOperand>(Context, /*Assert=*/true, &BB, ICmp);
+
+    Loop *L = LI->getLoopFor(ICmp->getParent());
+    const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
+    const SCEV *RHS = SE->getSCEVAtScope(ICmp->getOperand(1), L);
+
+    if (!isAffineExpr(&Context.CurRegion, LHS, *SE) ||
+        !isAffineExpr(&Context.CurRegion, RHS, *SE))
+      return invalid<ReportNonAffBranch>(Context, /*Assert=*/true, &BB, LHS,
+                                         RHS, ICmp);
+  }
+
+  // Allow loop exit conditions.
+  Loop *L = LI->getLoopFor(&BB);
+  if (L && L->getExitingBlock() == &BB)
+    return true;
+
+  // Allow perfectly nested conditions.
+  Region *R = RI->getRegionFor(&BB);
+  if (R->getEntry() != &BB)
+    return invalid<ReportCondition>(Context, /*Assert=*/true, &BB);
+
+  return true;
+}
+
+bool ScopDetection::isValidCallInst(CallInst &CI) {
+  if (CI.mayHaveSideEffects() || CI.doesNotReturn())
+    return false;
+
+  if (CI.doesNotAccessMemory())
+    return true;
+
+  Function *CalledFunction = CI.getCalledFunction();
+
+  // Indirect calls are not supported.
+  if (CalledFunction == 0)
+    return false;
+
+  // TODO: Intrinsics.
+  return false;
+}
+
+bool ScopDetection::isInvariant(const Value &Val, const Region &Reg) const {
+  // A reference to function argument or constant value is invariant.
+  if (isa<Argument>(Val) || isa<Constant>(Val))
+    return true;
+
+  const Instruction *I = dyn_cast<Instruction>(&Val);
+  if (!I)
+    return false;
+
+  if (!Reg.contains(I))
+    return true;
+
+  if (I->mayHaveSideEffects())
+    return false;
+
+  // When Val is a Phi node, it is likely not invariant. We do not check whether
+  // Phi nodes are actually invariant, we assume that Phi nodes are usually not
+  // invariant. Recursively checking the operators of Phi nodes would lead to
+  // infinite recursion.
+  if (isa<PHINode>(*I))
+    return false;
+
+  for (const Use &Operand : I->operands())
+    if (!isInvariant(*Operand, Reg))
+      return false;
+
+  // When the instruction is a load instruction, check that no write to memory
+  // in the region aliases with the load.
+  if (const LoadInst *LI = dyn_cast<LoadInst>(I)) {
+    AliasAnalysis::Location Loc = AA->getLocation(LI);
+    const Region::const_block_iterator BE = Reg.block_end();
+    // Check if any basic block in the region can modify the location pointed to
+    // by 'Loc'.  If so, 'Val' is (likely) not invariant in the region.
+    for (const BasicBlock *BB : Reg.blocks())
+      if (AA->canBasicBlockModify(*BB, Loc))
+        return false;
+  }
+
+  return true;
+}
+
+MapInsnToMemAcc InsnToMemAcc;
+
+bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
+  for (const SCEVUnknown *BasePointer : Context.NonAffineAccesses) {
+    Value *BaseValue = BasePointer->getValue();
+    ArrayShape *Shape = new ArrayShape(BasePointer);
+    bool BasePtrHasNonAffine = false;
+
+    // First step: collect parametric terms in all array references.
+    SmallVector<const SCEV *, 4> Terms;
+    for (const auto &Pair : Context.Accesses[BasePointer]) {
+      const SCEVAddRecExpr *AccessFunction =
+          dyn_cast<SCEVAddRecExpr>(Pair.second);
+
+      if (AccessFunction)
+        AccessFunction->collectParametricTerms(*SE, Terms);
+    }
+
+    // Second step: find array shape.
+    SE->findArrayDimensions(Terms, Shape->DelinearizedSizes,
+                            Context.ElementSize[BasePointer]);
+
+    // No array shape derived.
+    if (Shape->DelinearizedSizes.empty()) {
+      if (AllowNonAffine)
+        continue;
+
+      for (const auto &Pair : Context.Accesses[BasePointer]) {
+        const Instruction *Insn = Pair.first;
+        const SCEV *AF = Pair.second;
+
+        if (!isAffineExpr(&Context.CurRegion, AF, *SE, BaseValue)) {
+          invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF, Insn,
+                                         BaseValue);
+          if (!KeepGoing)
+            return false;
+        }
+      }
+      continue;
+    }
+
+    // Third step: compute the access functions for each subscript.
+    //
+    // We first store the resulting memory accesses in TempMemoryAccesses. Only
+    // if the access functions for all memory accesses have been successfully
+    // delinearized we continue. Otherwise, we either report a failure or, if
+    // non-affine accesses are allowed, we drop the information. In case the
+    // information is dropped the memory accesses need to be overapproximated
+    // when translated to a polyhedral representation.
+    MapInsnToMemAcc TempMemoryAccesses;
+    for (const auto &Pair : Context.Accesses[BasePointer]) {
+      const Instruction *Insn = Pair.first;
+      const SCEVAddRecExpr *AF = dyn_cast<SCEVAddRecExpr>(Pair.second);
+      bool IsNonAffine = false;
+      MemAcc *Acc = new MemAcc(Insn, Shape);
+      TempMemoryAccesses.insert({Insn, Acc});
+
+      if (!AF) {
+        if (isAffineExpr(&Context.CurRegion, Pair.second, *SE, BaseValue))
+          Acc->DelinearizedSubscripts.push_back(Pair.second);
+        else
+          IsNonAffine = true;
+      } else {
+        AF->computeAccessFunctions(*SE, Acc->DelinearizedSubscripts,
+                                   Shape->DelinearizedSizes);
+        if (Acc->DelinearizedSubscripts.size() == 0)
+          IsNonAffine = true;
+        for (const SCEV *S : Acc->DelinearizedSubscripts)
+          if (!isAffineExpr(&Context.CurRegion, S, *SE, BaseValue))
+            IsNonAffine = true;
+      }
+
+      // (Possibly) report non affine access
+      if (IsNonAffine) {
+        BasePtrHasNonAffine = true;
+        if (!AllowNonAffine)
+          invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, Pair.second,
+                                         Insn, BaseValue);
+        if (!KeepGoing && !AllowNonAffine)
+          return false;
+      }
+    }
+
+    if (!BasePtrHasNonAffine)
+      InsnToMemAcc.insert(TempMemoryAccesses.begin(), TempMemoryAccesses.end());
+  }
+  return true;
+}
+
+bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
+                                        DetectionContext &Context) const {
+  Value *Ptr = getPointerOperand(Inst);
+  Loop *L = LI->getLoopFor(Inst.getParent());
+  const SCEV *AccessFunction = SE->getSCEVAtScope(Ptr, L);
+  const SCEVUnknown *BasePointer;
+  Value *BaseValue;
+
+  BasePointer = dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
+
+  if (!BasePointer)
+    return invalid<ReportNoBasePtr>(Context, /*Assert=*/true, &Inst);
+
+  BaseValue = BasePointer->getValue();
+
+  if (isa<UndefValue>(BaseValue))
+    return invalid<ReportUndefBasePtr>(Context, /*Assert=*/true, &Inst);
+
+  // Check that the base address of the access is invariant in the current
+  // region.
+  if (!isInvariant(*BaseValue, Context.CurRegion))
+    // Verification of this property is difficult as the independent blocks
+    // pass may introduce aliasing that we did not have when running the
+    // scop detection.
+    return invalid<ReportVariantBasePtr>(Context, /*Assert=*/false, BaseValue,
+                                         &Inst);
+
+  AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
+
+  const SCEV *Size = SE->getElementSize(&Inst);
+  if (Context.ElementSize.count(BasePointer)) {
+    if (Context.ElementSize[BasePointer] != Size)
+      return invalid<ReportDifferentArrayElementSize>(Context, /*Assert=*/true,
+                                                      &Inst, BaseValue);
+  } else {
+    Context.ElementSize[BasePointer] = Size;
+  }
+
+  if (PollyDelinearize) {
+    Context.Accesses[BasePointer].push_back({&Inst, AccessFunction});
+
+    if (!isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue))
+      Context.NonAffineAccesses.insert(BasePointer);
+  } else if (!AllowNonAffine) {
+    if (!isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue))
+      return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
+                                            AccessFunction, &Inst, BaseValue);
+  }
+
+  // FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions
+  // created by IndependentBlocks Pass.
+  if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BaseValue))
+    return invalid<ReportIntToPtr>(Context, /*Assert=*/true, Inst);
+
+  if (IgnoreAliasing)
+    return true;
+
+  // Check if the base pointer of the memory access does alias with
+  // any other pointer. This cannot be handled at the moment.
+  AAMDNodes AATags;
+  Inst.getAAMetadata(AATags);
+  AliasSet &AS = Context.AST.getAliasSetForPointer(
+      BaseValue, AliasAnalysis::UnknownSize, AATags);
+
+  // INVALID triggers an assertion in verifying mode, if it detects that a
+  // SCoP was detected by SCoP detection and that this SCoP was invalidated by
+  // a pass that stated it would preserve the SCoPs. We disable this check as
+  // the independent blocks pass may create memory references which seem to
+  // alias, if -basicaa is not available. They actually do not, but as we can
+  // not proof this without -basicaa we would fail. We disable this check to
+  // not cause irrelevant verification failures.
+  if (!AS.isMustAlias()) {
+    if (PollyUseRuntimeAliasChecks) {
+      bool CanBuildRunTimeCheck = true;
+      // The run-time alias check places code that involves the base pointer at
+      // the beginning of the SCoP. This breaks if the base pointer is defined
+      // inside the scop. Hence, we can only create a run-time check if we are
+      // sure the base pointer is not an instruction defined inside the scop.
+      for (const auto &Ptr : AS) {
+        Instruction *Inst = dyn_cast<Instruction>(Ptr.getValue());
+        if (Inst && Context.CurRegion.contains(Inst)) {
+          CanBuildRunTimeCheck = false;
+          break;
+        }
+      }
+
+      if (CanBuildRunTimeCheck)
+        return true;
+    }
+    return invalid<ReportAlias>(Context, /*Assert=*/false, &Inst, AS);
+  }
+
+  return true;
+}
+
+bool ScopDetection::isValidInstruction(Instruction &Inst,
+                                       DetectionContext &Context) const {
+  if (PHINode *PN = dyn_cast<PHINode>(&Inst))
+    if (!canSynthesize(PN, LI, SE, &Context.CurRegion)) {
+      return invalid<ReportPhiNodeRefInRegion>(Context, /*Assert=*/true, &Inst);
+    }
+
+  // We only check the call instruction but not invoke instruction.
+  if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
+    if (isValidCallInst(*CI))
+      return true;
+
+    return invalid<ReportFuncCall>(Context, /*Assert=*/true, &Inst);
+  }
+
+  if (!Inst.mayWriteToMemory() && !Inst.mayReadFromMemory()) {
+    if (!isa<AllocaInst>(Inst))
+      return true;
+
+    return invalid<ReportAlloca>(Context, /*Assert=*/true, &Inst);
+  }
+
+  // Check the access function.
+  if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
+    return isValidMemoryAccess(Inst, Context);
+
+  // We do not know this instruction, therefore we assume it is invalid.
+  return invalid<ReportUnknownInst>(Context, /*Assert=*/true, &Inst);
+}
+
+bool ScopDetection::isValidLoop(Loop *L, DetectionContext &Context) const {
+  // Is the loop count affine?
+  const SCEV *LoopCount = SE->getBackedgeTakenCount(L);
+  if (!isAffineExpr(&Context.CurRegion, LoopCount, *SE))
+    return invalid<ReportLoopBound>(Context, /*Assert=*/true, L, LoopCount);
+
+  return true;
+}
+
+Region *ScopDetection::expandRegion(Region &R) {
+  // Initial no valid region was found (greater than R)
+  Region *LastValidRegion = nullptr;
+  Region *ExpandedRegion = R.getExpandedRegion();
+
+  DEBUG(dbgs() << "\tExpanding " << R.getNameStr() << "\n");
+
+  while (ExpandedRegion) {
+    DetectionContext Context(*ExpandedRegion, *AA, false /* verifying */);
+    DEBUG(dbgs() << "\t\tTrying " << ExpandedRegion->getNameStr() << "\n");
+    // Only expand when we did not collect errors.
+
+    // Check the exit first (cheap)
+    if (isValidExit(Context) && !Context.Log.hasErrors()) {
+      // If the exit is valid check all blocks
+      //  - if true, a valid region was found => store it + keep expanding
+      //  - if false, .tbd. => stop  (should this really end the loop?)
+      if (!allBlocksValid(Context) || Context.Log.hasErrors())
+        break;
+
+      if (Context.Log.hasErrors())
+        break;
+
+      // Delete unnecessary regions (allocated by getExpandedRegion)
+      if (LastValidRegion)
+        delete LastValidRegion;
+
+      // Store this region, because it is the greatest valid (encountered so
+      // far).
+      LastValidRegion = ExpandedRegion;
+
+      // Create and test the next greater region (if any)
+      ExpandedRegion = ExpandedRegion->getExpandedRegion();
+
+    } else {
+      // Create and test the next greater region (if any)
+      Region *TmpRegion = ExpandedRegion->getExpandedRegion();
+
+      // Delete unnecessary regions (allocated by getExpandedRegion)
+      delete ExpandedRegion;
+
+      ExpandedRegion = TmpRegion;
+    }
+  }
+
+  DEBUG({
+    if (LastValidRegion)
+      dbgs() << "\tto " << LastValidRegion->getNameStr() << "\n";
+    else
+      dbgs() << "\tExpanding " << R.getNameStr() << " failed\n";
+  });
+
+  return LastValidRegion;
+}
+static bool regionWithoutLoops(Region &R, LoopInfo *LI) {
+  for (const BasicBlock *BB : R.blocks())
+    if (R.contains(LI->getLoopFor(BB)))
+      return false;
+
+  return true;
+}
+
+// Remove all direct and indirect children of region R from the region set Regs,
+// but do not recurse further if the first child has been found.
+//
+// Return the number of regions erased from Regs.
+static unsigned eraseAllChildren(ScopDetection::RegionSet &Regs,
+                                 const Region &R) {
+  unsigned Count = 0;
+  for (auto &SubRegion : R) {
+    if (Regs.count(SubRegion.get())) {
+      ++Count;
+      Regs.remove(SubRegion.get());
+    } else {
+      Count += eraseAllChildren(Regs, *SubRegion);
+    }
+  }
+  return Count;
+}
+
+void ScopDetection::findScops(Region &R) {
+  if (!DetectRegionsWithoutLoops && regionWithoutLoops(R, LI))
+    return;
+
+  bool IsValidRegion = isValidRegion(R);
+  bool HasErrors = RejectLogs.count(&R) > 0;
+
+  if (IsValidRegion && !HasErrors) {
+    ++ValidRegion;
+    ValidRegions.insert(&R);
+    return;
+  }
+
+  for (auto &SubRegion : R)
+    findScops(*SubRegion);
+
+  // Try to expand regions.
+  //
+  // As the region tree normally only contains canonical regions, non canonical
+  // regions that form a Scop are not found. Therefore, those non canonical
+  // regions are checked by expanding the canonical ones.
+
+  std::vector<Region *> ToExpand;
+
+  for (auto &SubRegion : R)
+    ToExpand.push_back(SubRegion.get());
+
+  for (Region *CurrentRegion : ToExpand) {
+    // Skip regions that had errors.
+    bool HadErrors = RejectLogs.hasErrors(CurrentRegion);
+    if (HadErrors)
+      continue;
+
+    // Skip invalid regions. Regions may become invalid, if they are element of
+    // an already expanded region.
+    if (!ValidRegions.count(CurrentRegion))
+      continue;
+
+    Region *ExpandedR = expandRegion(*CurrentRegion);
+
+    if (!ExpandedR)
+      continue;
+
+    R.addSubRegion(ExpandedR, true);
+    ValidRegions.insert(ExpandedR);
+    ValidRegions.remove(CurrentRegion);
+
+    // Erase all (direct and indirect) children of ExpandedR from the valid
+    // regions and update the number of valid regions.
+    ValidRegion -= eraseAllChildren(ValidRegions, *ExpandedR);
+  }
+}
+
+bool ScopDetection::allBlocksValid(DetectionContext &Context) const {
+  Region &R = Context.CurRegion;
+
+  for (const BasicBlock *BB : R.blocks()) {
+    Loop *L = LI->getLoopFor(BB);
+    if (L && L->getHeader() == BB && (!isValidLoop(L, Context) && !KeepGoing))
+      return false;
+  }
+
+  for (BasicBlock *BB : R.blocks())
+    if (!isValidCFG(*BB, Context) && !KeepGoing)
+      return false;
+
+  for (BasicBlock *BB : R.blocks())
+    for (BasicBlock::iterator I = BB->begin(), E = --BB->end(); I != E; ++I)
+      if (!isValidInstruction(*I, Context) && !KeepGoing)
+        return false;
+
+  if (!hasAffineMemoryAccesses(Context))
+    return false;
+
+  return true;
+}
+
+bool ScopDetection::isValidExit(DetectionContext &Context) const {
+  Region &R = Context.CurRegion;
+
+  // PHI nodes are not allowed in the exit basic block.
+  if (BasicBlock *Exit = R.getExit()) {
+    BasicBlock::iterator I = Exit->begin();
+    if (I != Exit->end() && isa<PHINode>(*I))
+      return invalid<ReportPHIinExit>(Context, /*Assert=*/true, I);
+  }
+
+  return true;
+}
+
+bool ScopDetection::isValidRegion(Region &R) const {
+  DetectionContext Context(R, *AA, false /*verifying*/);
+
+  bool RegionIsValid = isValidRegion(Context);
+  bool HasErrors = !RegionIsValid || Context.Log.size() > 0;
+
+  if (PollyTrackFailures && HasErrors)
+    RejectLogs.insert(std::make_pair(&R, Context.Log));
+
+  return RegionIsValid;
+}
+
+bool ScopDetection::isValidRegion(DetectionContext &Context) const {
+  Region &R = Context.CurRegion;
+
+  DEBUG(dbgs() << "Checking region: " << R.getNameStr() << "\n\t");
+
+  if (R.isTopLevelRegion()) {
+    DEBUG(dbgs() << "Top level region is invalid\n");
+    return false;
+  }
+
+  if (!R.getEntry()->getName().count(OnlyRegion)) {
+    DEBUG({
+      dbgs() << "Region entry does not match -polly-region-only";
+      dbgs() << "\n";
+    });
+    return false;
+  }
+
+  if (!R.getEnteringBlock()) {
+    BasicBlock *entry = R.getEntry();
+    Loop *L = LI->getLoopFor(entry);
+
+    if (L) {
+      if (!L->isLoopSimplifyForm())
+        return invalid<ReportSimpleLoop>(Context, /*Assert=*/true);
+
+      for (pred_iterator PI = pred_begin(entry), PE = pred_end(entry); PI != PE;
+           ++PI) {
+        // Region entering edges come from the same loop but outside the region
+        // are not allowed.
+        if (L->contains(*PI) && !R.contains(*PI))
+          return invalid<ReportIndEdge>(Context, /*Assert=*/true, *PI);
+      }
+    }
+  }
+
+  // SCoP cannot contain the entry block of the function, because we need
+  // to insert alloca instruction there when translate scalar to array.
+  if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock()))
+    return invalid<ReportEntry>(Context, /*Assert=*/true, R.getEntry());
+
+  if (!isValidExit(Context))
+    return false;
+
+  if (!allBlocksValid(Context))
+    return false;
+
+  DEBUG(dbgs() << "OK\n");
+  return true;
+}
+
+void ScopDetection::markFunctionAsInvalid(Function *F) const {
+  F->addFnAttr(PollySkipFnAttr);
+}
+
+bool ScopDetection::isValidFunction(llvm::Function &F) {
+  return !F.hasFnAttribute(PollySkipFnAttr);
+}
+
+void ScopDetection::printLocations(llvm::Function &F) {
+  for (const Region *R : *this) {
+    unsigned LineEntry, LineExit;
+    std::string FileName;
+
+    getDebugLocation(R, LineEntry, LineExit, FileName);
+    DiagnosticScopFound Diagnostic(F, FileName, LineEntry, LineExit);
+    F.getContext().diagnose(Diagnostic);
+  }
+}
+
+void ScopDetection::emitMissedRemarksForValidRegions(
+    const Function &F, const RegionSet &ValidRegions) {
+  for (const Region *R : ValidRegions) {
+    const Region *Parent = R->getParent();
+    if (Parent && !Parent->isTopLevelRegion() && RejectLogs.count(Parent))
+      emitRejectionRemarks(F, RejectLogs.at(Parent));
+  }
+}
+
+void ScopDetection::emitMissedRemarksForLeaves(const Function &F,
+                                               const Region *R) {
+  for (const std::unique_ptr<Region> &Child : *R) {
+    bool IsValid = ValidRegions.count(Child.get());
+    if (IsValid)
+      continue;
+
+    bool IsLeaf = Child->begin() == Child->end();
+    if (!IsLeaf)
+      emitMissedRemarksForLeaves(F, Child.get());
+    else {
+      if (RejectLogs.count(Child.get())) {
+        emitRejectionRemarks(F, RejectLogs.at(Child.get()));
+      }
+    }
+  }
+}
+
+bool ScopDetection::runOnFunction(llvm::Function &F) {
+  LI = &getAnalysis<LoopInfo>();
+  RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
+  if (!DetectScopsWithoutLoops && LI->empty())
+    return false;
+
+  AA = &getAnalysis<AliasAnalysis>();
+  SE = &getAnalysis<ScalarEvolution>();
+  Region *TopRegion = RI->getTopLevelRegion();
+
+  releaseMemory();
+
+  if (OnlyFunction != "" && !F.getName().count(OnlyFunction))
+    return false;
+
+  if (!isValidFunction(F))
+    return false;
+
+  findScops(*TopRegion);
+
+  // Only makes sense when we tracked errors.
+  if (PollyTrackFailures) {
+    emitMissedRemarksForValidRegions(F, ValidRegions);
+    emitMissedRemarksForLeaves(F, TopRegion);
+  }
+
+  for (const Region *R : ValidRegions)
+    emitValidRemarks(F, R);
+
+  if (ReportLevel)
+    printLocations(F);
+
+  return false;
+}
+
+void polly::ScopDetection::verifyRegion(const Region &R) const {
+  assert(isMaxRegionInScop(R) && "Expect R is a valid region.");
+  DetectionContext Context(const_cast<Region &>(R), *AA, true /*verifying*/);
+  isValidRegion(Context);
+}
+
+void polly::ScopDetection::verifyAnalysis() const {
+  if (!VerifyScops)
+    return;
+
+  for (const Region *R : ValidRegions)
+    verifyRegion(*R);
+}
+
+void ScopDetection::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<DominatorTreeWrapperPass>();
+  AU.addRequired<PostDominatorTree>();
+  AU.addRequired<LoopInfo>();
+  AU.addRequired<ScalarEvolution>();
+  // We also need AA and RegionInfo when we are verifying analysis.
+  AU.addRequiredTransitive<AliasAnalysis>();
+  AU.addRequiredTransitive<RegionInfoPass>();
+  AU.setPreservesAll();
+}
+
+void ScopDetection::print(raw_ostream &OS, const Module *) const {
+  for (const Region *R : ValidRegions)
+    OS << "Valid Region for Scop: " << R->getNameStr() << '\n';
+
+  OS << "\n";
+}
+
+void ScopDetection::releaseMemory() {
+  ValidRegions.clear();
+  RejectLogs.clear();
+
+  // Do not clear the invalid function set.
+}
+
+char ScopDetection::ID = 0;
+
+Pass *polly::createScopDetectionPass() { return new ScopDetection(); }
+
+INITIALIZE_PASS_BEGIN(ScopDetection, "polly-detect",
+                      "Polly - Detect static control parts (SCoPs)", false,
+                      false);
+INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
+INITIALIZE_PASS_DEPENDENCY(LoopInfo);
+INITIALIZE_PASS_DEPENDENCY(PostDominatorTree);
+INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_END(ScopDetection, "polly-detect",
+                    "Polly - Detect static control parts (SCoPs)", false, false)
diff --git a/final/lib/Analysis/ScopDetectionDiagnostic.cpp b/final/lib/Analysis/ScopDetectionDiagnostic.cpp
new file mode 100644
index 0000000..fef69b3
--- /dev/null
+++ b/final/lib/Analysis/ScopDetectionDiagnostic.cpp
@@ -0,0 +1,594 @@
+//=== ScopDetectionDiagnostic.cpp - Error diagnostics --------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Small set of diagnostic helper classes to encapsulate any errors occurred
+// during the detection of Scops.
+//
+// The ScopDetection defines a set of error classes (via Statistic variables)
+// that groups a number of individual errors into a group, e.g. non-affinity
+// related errors.
+// On error we generate an object that carries enough additional information
+// to diagnose the error and generate a helpful error message.
+//
+//===----------------------------------------------------------------------===//
+#include "polly/ScopDetectionDiagnostic.h"
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/AliasSetTracker.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Value.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+
+#include "llvm/Analysis/RegionInfo.h"
+
+#define DEBUG_TYPE "polly-detect"
+#include "llvm/Support/Debug.h"
+
+#include <string>
+
+#define BADSCOP_STAT(NAME, DESC)                                               \
+  STATISTIC(Bad##NAME##ForScop, "Number of bad regions for Scop: " DESC)
+
+BADSCOP_STAT(CFG, "CFG too complex");
+BADSCOP_STAT(IndVar, "Non canonical induction variable in loop");
+BADSCOP_STAT(IndEdge, "Found invalid region entering edges");
+BADSCOP_STAT(LoopBound, "Loop bounds can not be computed");
+BADSCOP_STAT(FuncCall, "Function call with side effects appeared");
+BADSCOP_STAT(AffFunc, "Expression not affine");
+BADSCOP_STAT(Alias, "Found base address alias");
+BADSCOP_STAT(SimpleLoop, "Loop not in -loop-simplify form");
+BADSCOP_STAT(Other, "Others");
+
+namespace polly {
+/// @brief Small string conversion via raw_string_stream.
+template <typename T> std::string operator+(Twine LHS, const T &RHS) {
+  std::string Buf;
+  raw_string_ostream fmt(Buf);
+  fmt << RHS;
+  fmt.flush();
+
+  return LHS.concat(Buf).str();
+}
+
+void getDebugLocation(const Region *R, unsigned &LineBegin, unsigned &LineEnd,
+                      std::string &FileName) {
+  LineBegin = -1;
+  LineEnd = 0;
+
+  for (const BasicBlock *BB : R->blocks())
+    for (const Instruction &Inst : *BB) {
+      DebugLoc DL = Inst.getDebugLoc();
+      if (DL.isUnknown())
+        continue;
+
+      DIScope Scope(DL.getScope(Inst.getContext()));
+
+      if (FileName.empty())
+        FileName = Scope.getFilename();
+
+      unsigned NewLine = DL.getLine();
+
+      LineBegin = std::min(LineBegin, NewLine);
+      LineEnd = std::max(LineEnd, NewLine);
+    }
+}
+}
+
+namespace llvm {
+// @brief Lexicographic order on (line, col) of our debug locations.
+static bool operator<(const llvm::DebugLoc &LHS, const llvm::DebugLoc &RHS) {
+  return LHS.getLine() < RHS.getLine() ||
+         (LHS.getLine() == RHS.getLine() && LHS.getCol() < RHS.getCol());
+}
+}
+
+namespace polly {
+static void getDebugLocations(const Region *R, DebugLoc &Begin, DebugLoc &End) {
+  for (const BasicBlock *BB : R->blocks())
+    for (const Instruction &Inst : *BB) {
+      DebugLoc DL = Inst.getDebugLoc();
+      if (DL.isUnknown())
+        continue;
+
+      Begin = Begin.isUnknown() ? DL : std::min(Begin, DL);
+      End = End.isUnknown() ? DL : std::max(End, DL);
+    }
+}
+
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log) {
+  LLVMContext &Ctx = F.getContext();
+
+  const Region *R = Log.region();
+  DebugLoc Begin, End;
+
+  getDebugLocations(R, Begin, End);
+
+  emitOptimizationRemarkMissed(
+      Ctx, DEBUG_TYPE, F, Begin,
+      "The following errors keep this region from being a Scop.");
+
+  for (RejectReasonPtr RR : Log) {
+    const DebugLoc &Loc = RR->getDebugLoc();
+    if (!Loc.isUnknown())
+      emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc,
+                                   RR->getEndUserMessage());
+  }
+
+  emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, End,
+                               "Invalid Scop candidate ends here.");
+}
+
+void emitValidRemarks(const llvm::Function &F, const Region *R) {
+  LLVMContext &Ctx = F.getContext();
+
+  DebugLoc Begin, End;
+  getDebugLocations(R, Begin, End);
+
+  emitOptimizationRemark(Ctx, DEBUG_TYPE, F, Begin,
+                         "A valid Scop begins here.");
+  emitOptimizationRemark(Ctx, DEBUG_TYPE, F, End, "A valid Scop ends here.");
+}
+
+//===----------------------------------------------------------------------===//
+// RejectReason.
+const DebugLoc RejectReason::Unknown = DebugLoc();
+
+const llvm::DebugLoc &RejectReason::getDebugLoc() const {
+  // Allocate an empty DebugLoc and return it a reference to it.
+  return Unknown;
+}
+
+// RejectLog.
+void RejectLog::print(raw_ostream &OS, int level) const {
+  int j = 0;
+  for (auto Reason : ErrorReports)
+    OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n";
+}
+
+//===----------------------------------------------------------------------===//
+// ReportCFG.
+
+ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {
+  ++BadCFGForScop;
+}
+
+bool ReportCFG::classof(const RejectReason *RR) {
+  return RR->getKind() >= rrkCFG && RR->getKind() <= rrkLastCFG;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportNonBranchTerminator.
+
+std::string ReportNonBranchTerminator::getMessage() const {
+  return ("Non branch instruction terminates BB: " + BB->getName()).str();
+}
+
+const DebugLoc &ReportNonBranchTerminator::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+bool ReportNonBranchTerminator::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkNonBranchTerminator;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportCondition.
+
+std::string ReportCondition::getMessage() const {
+  return ("Not well structured condition at BB: " + BB->getName()).str();
+}
+
+const DebugLoc &ReportCondition::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+bool ReportCondition::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkCondition;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAffFunc.
+
+ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst)
+    : RejectReason(K), Inst(Inst) {
+  ++BadAffFuncForScop;
+}
+
+bool ReportAffFunc::classof(const RejectReason *RR) {
+  return RR->getKind() >= rrkAffFunc && RR->getKind() <= rrkLastAffFunc;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUndefCond.
+
+std::string ReportUndefCond::getMessage() const {
+  return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
+}
+
+bool ReportUndefCond::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkUndefCond;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportInvalidCond.
+
+std::string ReportInvalidCond::getMessage() const {
+  return ("Condition in BB '" + BB->getName()).str() +
+         "' neither constant nor an icmp instruction";
+}
+
+bool ReportInvalidCond::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkInvalidCond;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUndefOperand.
+
+std::string ReportUndefOperand::getMessage() const {
+  return ("undef operand in branch at BB: " + BB->getName()).str();
+}
+
+bool ReportUndefOperand::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkUndefOperand;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportNonAffBranch.
+
+std::string ReportNonAffBranch::getMessage() const {
+  return ("Non affine branch in BB '" + BB->getName()).str() + "' with LHS: " +
+         *LHS + " and RHS: " + *RHS;
+}
+
+bool ReportNonAffBranch::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkNonAffBranch;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportNoBasePtr.
+
+std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
+
+bool ReportNoBasePtr::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkNoBasePtr;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUndefBasePtr.
+
+std::string ReportUndefBasePtr::getMessage() const {
+  return "Undefined base pointer";
+}
+
+bool ReportUndefBasePtr::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkUndefBasePtr;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportVariantBasePtr.
+
+std::string ReportVariantBasePtr::getMessage() const {
+  return "Base address not invariant in current region:" + *BaseValue;
+}
+
+std::string ReportVariantBasePtr::getEndUserMessage() const {
+  return "The base address of this array is not invariant inside the loop";
+}
+
+bool ReportVariantBasePtr::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkVariantBasePtr;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportDifferentArrayElementSize
+
+std::string ReportDifferentArrayElementSize::getMessage() const {
+  return "Access to one array through data types of different size";
+}
+
+bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkDifferentElementSize;
+}
+
+std::string ReportDifferentArrayElementSize::getEndUserMessage() const {
+  llvm::StringRef BaseName = BaseValue->getName();
+  std::string Name = (BaseName.size() > 0) ? BaseName : "UNKNOWN";
+  return "The array \"" + Name + "\" is accessed through elements that differ "
+                                 "in size";
+}
+
+//===----------------------------------------------------------------------===//
+// ReportNonAffineAccess.
+
+std::string ReportNonAffineAccess::getMessage() const {
+  return "Non affine access function: " + *AccessFunction;
+}
+
+bool ReportNonAffineAccess::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkNonAffineAccess;
+}
+
+std::string ReportNonAffineAccess::getEndUserMessage() const {
+  llvm::StringRef BaseName = BaseValue->getName();
+  std::string Name = (BaseName.size() > 0) ? BaseName : "UNKNOWN";
+  return "The array subscript of \"" + Name + "\" is not affine";
+}
+
+//===----------------------------------------------------------------------===//
+// ReportIndVar.
+
+ReportIndVar::ReportIndVar(const RejectReasonKind K) : RejectReason(K) {
+  ++BadIndVarForScop;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportPhiNodeRefInRegion.
+
+ReportPhiNodeRefInRegion::ReportPhiNodeRefInRegion(Instruction *Inst)
+    : ReportIndVar(rrkPhiNodeRefInRegion), Inst(Inst) {}
+
+std::string ReportPhiNodeRefInRegion::getMessage() const {
+  return "SCEV of PHI node refers to SSA names in region: " + *Inst;
+}
+
+const DebugLoc &ReportPhiNodeRefInRegion::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+bool ReportPhiNodeRefInRegion::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkPhiNodeRefInRegion;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportIndEdge.
+
+ReportIndEdge::ReportIndEdge(BasicBlock *BB)
+    : RejectReason(rrkIndEdge), BB(BB) {
+  ++BadIndEdgeForScop;
+}
+
+std::string ReportIndEdge::getMessage() const {
+  return "Region has invalid entering edges!";
+}
+
+const DebugLoc &ReportIndEdge::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+bool ReportIndEdge::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkIndEdge;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportLoopBound.
+
+ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
+    : RejectReason(rrkLoopBound), L(L), LoopCount(LoopCount),
+      Loc(L->getStartLoc()) {
+  ++BadLoopBoundForScop;
+}
+
+std::string ReportLoopBound::getMessage() const {
+  return "Non affine loop bound '" + *LoopCount + "' in loop: " +
+         L->getHeader()->getName();
+}
+
+const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; }
+
+bool ReportLoopBound::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkLoopBound;
+}
+
+std::string ReportLoopBound::getEndUserMessage() const {
+  return "Failed to derive an affine function from the loop bounds.";
+}
+
+//===----------------------------------------------------------------------===//
+// ReportFuncCall.
+
+ReportFuncCall::ReportFuncCall(Instruction *Inst)
+    : RejectReason(rrkFuncCall), Inst(Inst) {
+  ++BadFuncCallForScop;
+}
+
+std::string ReportFuncCall::getMessage() const {
+  return "Call instruction: " + *Inst;
+}
+
+const DebugLoc &ReportFuncCall::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+std::string ReportFuncCall::getEndUserMessage() const {
+  return "This function call cannot be handled. "
+         "Try to inline it.";
+}
+
+bool ReportFuncCall::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkFuncCall;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlias.
+
+ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS)
+    : RejectReason(rrkAlias), Inst(Inst) {
+
+  for (const auto &I : AS)
+    Pointers.push_back(I.getValue());
+
+  ++BadAliasForScop;
+}
+
+std::string ReportAlias::formatInvalidAlias(std::string Prefix,
+                                            std::string Suffix) const {
+  std::string Message;
+  raw_string_ostream OS(Message);
+
+  OS << Prefix;
+
+  for (PointerSnapshotTy::const_iterator PI = Pointers.begin(),
+                                         PE = Pointers.end();
+       ;) {
+    const Value *V = *PI;
+    assert(V && "Diagnostic info does not match found LLVM-IR anymore.");
+
+    if (V->getName().size() == 0)
+      OS << "\"" << *V << "\"";
+    else
+      OS << "\"" << V->getName() << "\"";
+
+    ++PI;
+
+    if (PI != PE)
+      OS << ", ";
+    else
+      break;
+  }
+
+  OS << Suffix;
+
+  return OS.str();
+}
+
+std::string ReportAlias::getMessage() const {
+  return formatInvalidAlias("Possible aliasing: ");
+}
+
+std::string ReportAlias::getEndUserMessage() const {
+  return formatInvalidAlias("Accesses to the arrays ",
+                            " may access the same memory.");
+}
+
+const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
+
+bool ReportAlias::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkAlias;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportSimpleLoop.
+
+ReportSimpleLoop::ReportSimpleLoop() : RejectReason(rrkSimpleLoop) {
+  ++BadSimpleLoopForScop;
+}
+
+std::string ReportSimpleLoop::getMessage() const {
+  return "Loop not in simplify form is invalid!";
+}
+
+bool ReportSimpleLoop::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkSimpleLoop;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportOther.
+
+std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
+
+ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {
+  ++BadOtherForScop;
+}
+
+bool ReportOther::classof(const RejectReason *RR) {
+  return RR->getKind() >= rrkOther && RR->getKind() <= rrkLastOther;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportIntToPtr.
+ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
+    : ReportOther(rrkIntToPtr), BaseValue(BaseValue) {}
+
+std::string ReportIntToPtr::getMessage() const {
+  return "Find bad intToptr prt: " + *BaseValue;
+}
+
+const DebugLoc &ReportIntToPtr::getDebugLoc() const {
+  return BaseValue->getDebugLoc();
+}
+
+bool ReportIntToPtr::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkIntToPtr;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlloca.
+
+ReportAlloca::ReportAlloca(Instruction *Inst)
+    : ReportOther(rrkAlloca), Inst(Inst) {}
+
+std::string ReportAlloca::getMessage() const {
+  return "Alloca instruction: " + *Inst;
+}
+
+const DebugLoc &ReportAlloca::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+bool ReportAlloca::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkAlloca;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUnknownInst.
+
+ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
+    : ReportOther(rrkUnknownInst), Inst(Inst) {}
+
+std::string ReportUnknownInst::getMessage() const {
+  return "Unknown instruction: " + *Inst;
+}
+
+const DebugLoc &ReportUnknownInst::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+bool ReportUnknownInst::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkUnknownInst;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportPHIinExit.
+
+ReportPHIinExit::ReportPHIinExit(Instruction *Inst)
+    : ReportOther(rrkPHIinExit), Inst(Inst) {}
+
+std::string ReportPHIinExit::getMessage() const {
+  return "PHI node in exit BB";
+}
+
+const DebugLoc &ReportPHIinExit::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+bool ReportPHIinExit::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkPHIinExit;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportEntry.
+ReportEntry::ReportEntry(BasicBlock *BB) : ReportOther(rrkEntry), BB(BB) {}
+
+std::string ReportEntry::getMessage() const {
+  return "Region containing entry block of function is invalid!";
+}
+
+const DebugLoc &ReportEntry::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+bool ReportEntry::classof(const RejectReason *RR) {
+  return RR->getKind() == rrkEntry;
+}
+} // namespace polly
diff --git a/final/lib/Analysis/ScopGraphPrinter.cpp b/final/lib/Analysis/ScopGraphPrinter.cpp
new file mode 100644
index 0000000..740e122
--- /dev/null
+++ b/final/lib/Analysis/ScopGraphPrinter.cpp
@@ -0,0 +1,206 @@
+//===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Create a DOT output describing the Scop.
+//
+// For each function a dot file is created that shows the control flow graph of
+// the function and highlights the detected Scops.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/LinkAllPasses.h"
+#include "polly/ScopDetection.h"
+#include "llvm/Analysis/DOTGraphTraitsPass.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/Analysis/RegionIterator.h"
+
+using namespace polly;
+using namespace llvm;
+
+namespace llvm {
+template <>
+struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> {
+  static NodeType *getEntryNode(ScopDetection *SD) {
+    return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI());
+  }
+  static nodes_iterator nodes_begin(ScopDetection *SD) {
+    return nodes_iterator::begin(getEntryNode(SD));
+  }
+  static nodes_iterator nodes_end(ScopDetection *SD) {
+    return nodes_iterator::end(getEntryNode(SD));
+  }
+};
+
+template <> struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits {
+  DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
+
+  std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
+    if (!Node->isSubRegion()) {
+      BasicBlock *BB = Node->getNodeAs<BasicBlock>();
+
+      if (isSimple())
+        return DOTGraphTraits<const Function *>::getSimpleNodeLabel(
+            BB, BB->getParent());
+      else
+        return DOTGraphTraits<const Function *>::getCompleteNodeLabel(
+            BB, BB->getParent());
+    }
+
+    return "Not implemented";
+  }
+};
+
+template <>
+struct DOTGraphTraits<ScopDetection *> : public DOTGraphTraits<RegionNode *> {
+  DOTGraphTraits(bool isSimple = false)
+      : DOTGraphTraits<RegionNode *>(isSimple) {}
+  static std::string getGraphName(ScopDetection *SD) { return "Scop Graph"; }
+
+  std::string getEdgeAttributes(RegionNode *srcNode,
+                                GraphTraits<RegionInfo *>::ChildIteratorType CI,
+                                ScopDetection *SD) {
+    RegionNode *destNode = *CI;
+
+    if (srcNode->isSubRegion() || destNode->isSubRegion())
+      return "";
+
+    // In case of a backedge, do not use it to define the layout of the nodes.
+    BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
+    BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
+
+    RegionInfo *RI = SD->getRI();
+    Region *R = RI->getRegionFor(destBB);
+
+    while (R && R->getParent())
+      if (R->getParent()->getEntry() == destBB)
+        R = R->getParent();
+      else
+        break;
+
+    if (R->getEntry() == destBB && R->contains(srcBB))
+      return "constraint=false";
+
+    return "";
+  }
+
+  std::string getNodeLabel(RegionNode *Node, ScopDetection *SD) {
+    return DOTGraphTraits<RegionNode *>::getNodeLabel(
+        Node, reinterpret_cast<RegionNode *>(SD->getRI()->getTopLevelRegion()));
+  }
+
+  static std::string escapeString(std::string String) {
+    std::string Escaped;
+
+    for (const auto &C : String) {
+      if (C == '"')
+        Escaped += '\\';
+
+      Escaped += C;
+    }
+    return Escaped;
+  }
+
+  // Print the cluster of the subregions. This groups the single basic blocks
+  // and adds a different background color for each group.
+  static void printRegionCluster(const ScopDetection *SD, const Region *R,
+                                 raw_ostream &O, unsigned depth = 0) {
+    O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
+                        << " {\n";
+    std::string ErrorMessage = SD->regionIsInvalidBecause(R);
+    ErrorMessage = escapeString(ErrorMessage);
+    O.indent(2 * (depth + 1)) << "label = \"" << ErrorMessage << "\";\n";
+
+    if (SD->isMaxRegionInScop(*R)) {
+      O.indent(2 * (depth + 1)) << "style = filled;\n";
+
+      // Set color to green.
+      O.indent(2 * (depth + 1)) << "color = 3";
+    } else {
+      O.indent(2 * (depth + 1)) << "style = solid;\n";
+
+      int color = (R->getDepth() * 2 % 12) + 1;
+
+      // We do not want green again.
+      if (color == 3)
+        color = 6;
+
+      O.indent(2 * (depth + 1)) << "color = " << color << "\n";
+    }
+
+    for (const auto &SubRegion : *R)
+      printRegionCluster(SD, SubRegion.get(), O, depth + 1);
+
+    RegionInfo *RI = R->getRegionInfo();
+
+    for (const auto &BB : R->blocks())
+      if (RI->getRegionFor(BB) == R)
+        O.indent(2 * (depth + 1))
+            << "Node"
+            << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
+            << ";\n";
+
+    O.indent(2 * depth) << "}\n";
+  }
+  static void addCustomGraphFeatures(const ScopDetection *SD,
+                                     GraphWriter<ScopDetection *> &GW) {
+    raw_ostream &O = GW.getOStream();
+    O << "\tcolorscheme = \"paired12\"\n";
+    printRegionCluster(SD, SD->getRI()->getTopLevelRegion(), O, 4);
+  }
+};
+
+} // end namespace llvm
+
+struct ScopViewer : public DOTGraphTraitsViewer<ScopDetection, false> {
+  static char ID;
+  ScopViewer() : DOTGraphTraitsViewer<ScopDetection, false>("scops", ID) {}
+};
+char ScopViewer::ID = 0;
+
+struct ScopOnlyViewer : public DOTGraphTraitsViewer<ScopDetection, true> {
+  static char ID;
+  ScopOnlyViewer()
+      : DOTGraphTraitsViewer<ScopDetection, true>("scopsonly", ID) {}
+};
+char ScopOnlyViewer::ID = 0;
+
+struct ScopPrinter : public DOTGraphTraitsPrinter<ScopDetection, false> {
+  static char ID;
+  ScopPrinter() : DOTGraphTraitsPrinter<ScopDetection, false>("scops", ID) {}
+};
+char ScopPrinter::ID = 0;
+
+struct ScopOnlyPrinter : public DOTGraphTraitsPrinter<ScopDetection, true> {
+  static char ID;
+  ScopOnlyPrinter()
+      : DOTGraphTraitsPrinter<ScopDetection, true>("scopsonly", ID) {}
+};
+char ScopOnlyPrinter::ID = 0;
+
+static RegisterPass<ScopViewer> X("view-scops",
+                                  "Polly - View Scops of function");
+
+static RegisterPass<ScopOnlyViewer>
+    Y("view-scops-only",
+      "Polly - View Scops of function (with no function bodies)");
+
+static RegisterPass<ScopPrinter> M("dot-scops",
+                                   "Polly - Print Scops of function");
+
+static RegisterPass<ScopOnlyPrinter>
+    N("dot-scops-only",
+      "Polly - Print Scops of function (with no function bodies)");
+
+Pass *polly::createDOTViewerPass() { return new ScopViewer(); }
+
+Pass *polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); }
+
+Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); }
+
+Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); }
diff --git a/final/lib/Analysis/ScopInfo.cpp b/final/lib/Analysis/ScopInfo.cpp
new file mode 100644
index 0000000..b130099
--- /dev/null
+++ b/final/lib/Analysis/ScopInfo.cpp
@@ -0,0 +1,1937 @@
+//===--------- ScopInfo.cpp  - Create Scops from LLVM IR ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Create a polyhedral description for a static control flow region.
+//
+// The pass creates a polyhedral description of the Scops detected by the Scop
+// detection derived from their LLVM-IR code.
+//
+// This representation is shared among several tools in the polyhedral
+// community, which are e.g. Cloog, Pluto, Loopo, Graphite.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/LinkAllPasses.h"
+#include "polly/ScopInfo.h"
+#include "polly/Options.h"
+#include "polly/Support/GICHelper.h"
+#include "polly/Support/SCEVValidator.h"
+#include "polly/Support/ScopHelper.h"
+#include "polly/TempScopInfo.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/RegionIterator.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Support/Debug.h"
+
+#include "isl/constraint.h"
+#include "isl/set.h"
+#include "isl/map.h"
+#include "isl/union_map.h"
+#include "isl/aff.h"
+#include "isl/printer.h"
+#include "isl/local_space.h"
+#include "isl/options.h"
+#include "isl/val.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace polly;
+
+#define DEBUG_TYPE "polly-scops"
+
+STATISTIC(ScopFound, "Number of valid Scops");
+STATISTIC(RichScopFound, "Number of Scops containing a loop");
+
+// Multiplicative reductions can be disabled separately as these kind of
+// operations can overflow easily. Additive reductions and bit operations
+// are in contrast pretty stable.
+static cl::opt<bool> DisableMultiplicativeReductions(
+    "polly-disable-multiplicative-reductions",
+    cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::ZeroOrMore,
+    cl::init(false), cl::cat(PollyCategory));
+
+static cl::opt<unsigned> RunTimeChecksMaxParameters(
+    "polly-rtc-max-parameters",
+    cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden,
+    cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory));
+
+/// Translate a 'const SCEV *' expression in an isl_pw_aff.
+struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff *> {
+public:
+  /// @brief Translate a 'const SCEV *' to an isl_pw_aff.
+  ///
+  /// @param Stmt The location at which the scalar evolution expression
+  ///             is evaluated.
+  /// @param Expr The expression that is translated.
+  static __isl_give isl_pw_aff *getPwAff(ScopStmt *Stmt, const SCEV *Expr);
+
+private:
+  isl_ctx *Ctx;
+  int NbLoopSpaces;
+  const Scop *S;
+
+  SCEVAffinator(const ScopStmt *Stmt);
+  int getLoopDepth(const Loop *L);
+
+  __isl_give isl_pw_aff *visit(const SCEV *Expr);
+  __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Expr);
+  __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr *Expr);
+  __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr);
+  __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr *Expr);
+  __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr *Expr);
+  __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr *Expr);
+  __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr *Expr);
+  __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr *Expr);
+  __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr *Expr);
+  __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr *Expr);
+  __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown *Expr);
+
+  friend struct SCEVVisitor<SCEVAffinator, isl_pw_aff *>;
+};
+
+SCEVAffinator::SCEVAffinator(const ScopStmt *Stmt)
+    : Ctx(Stmt->getIslCtx()), NbLoopSpaces(Stmt->getNumIterators()),
+      S(Stmt->getParent()) {}
+
+__isl_give isl_pw_aff *SCEVAffinator::getPwAff(ScopStmt *Stmt,
+                                               const SCEV *Scev) {
+  Scop *S = Stmt->getParent();
+  const Region *Reg = &S->getRegion();
+
+  S->addParams(getParamsInAffineExpr(Reg, Scev, *S->getSE()));
+
+  SCEVAffinator Affinator(Stmt);
+  return Affinator.visit(Scev);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) {
+  // In case the scev is a valid parameter, we do not further analyze this
+  // expression, but create a new parameter in the isl_pw_aff. This allows us
+  // to treat subexpressions that we cannot translate into an piecewise affine
+  // expression, as constant parameters of the piecewise affine expression.
+  if (isl_id *Id = S->getIdForParam(Expr)) {
+    isl_space *Space = isl_space_set_alloc(Ctx, 1, NbLoopSpaces);
+    Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id);
+
+    isl_set *Domain = isl_set_universe(isl_space_copy(Space));
+    isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space));
+    Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
+
+    return isl_pw_aff_alloc(Domain, Affine);
+  }
+
+  return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
+  ConstantInt *Value = Expr->getValue();
+  isl_val *v;
+
+  // LLVM does not define if an integer value is interpreted as a signed or
+  // unsigned value. Hence, without further information, it is unknown how
+  // this value needs to be converted to GMP. At the moment, we only support
+  // signed operations. So we just interpret it as signed. Later, there are
+  // two options:
+  //
+  // 1. We always interpret any value as signed and convert the values on
+  //    demand.
+  // 2. We pass down the signedness of the calculation and use it to interpret
+  //    this constant correctly.
+  v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true);
+
+  isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
+  isl_local_space *ls = isl_local_space_from_space(Space);
+  return isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v));
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
+  llvm_unreachable("SCEVTruncateExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+  llvm_unreachable("SCEVZeroExtendExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
+  // Assuming the value is signed, a sign extension is basically a noop.
+  // TODO: Reconsider this as soon as we support unsigned values.
+  return visit(Expr->getOperand());
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) {
+  isl_pw_aff *Sum = visit(Expr->getOperand(0));
+
+  for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
+    isl_pw_aff *NextSummand = visit(Expr->getOperand(i));
+    Sum = isl_pw_aff_add(Sum, NextSummand);
+  }
+
+  // TODO: Check for NSW and NUW.
+
+  return Sum;
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
+  isl_pw_aff *Product = visit(Expr->getOperand(0));
+
+  for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
+    isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
+
+    if (!isl_pw_aff_is_cst(Product) && !isl_pw_aff_is_cst(NextOperand)) {
+      isl_pw_aff_free(Product);
+      isl_pw_aff_free(NextOperand);
+      return nullptr;
+    }
+
+    Product = isl_pw_aff_mul(Product, NextOperand);
+  }
+
+  // TODO: Check for NSW and NUW.
+  return Product;
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
+  llvm_unreachable("SCEVUDivExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *
+SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+  assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
+
+  // Directly generate isl_pw_aff for Expr if 'start' is zero.
+  if (Expr->getStart()->isZero()) {
+    assert(S->getRegion().contains(Expr->getLoop()) &&
+           "Scop does not contain the loop referenced in this AddRec");
+
+    isl_pw_aff *Start = visit(Expr->getStart());
+    isl_pw_aff *Step = visit(Expr->getOperand(1));
+    isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
+    isl_local_space *LocalSpace = isl_local_space_from_space(Space);
+
+    int loopDimension = getLoopDepth(Expr->getLoop());
+
+    isl_aff *LAff = isl_aff_set_coefficient_si(
+        isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1);
+    isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff);
+
+    // TODO: Do we need to check for NSW and NUW?
+    return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff));
+  }
+
+  // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
+  // if 'start' is not zero.
+  ScalarEvolution &SE = *S->getSE();
+  const SCEV *ZeroStartExpr = SE.getAddRecExpr(
+      SE.getConstant(Expr->getStart()->getType(), 0),
+      Expr->getStepRecurrence(SE), Expr->getLoop(), SCEV::FlagAnyWrap);
+
+  isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr);
+  isl_pw_aff *Start = visit(Expr->getStart());
+
+  return isl_pw_aff_add(ZeroStartResult, Start);
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) {
+  isl_pw_aff *Max = visit(Expr->getOperand(0));
+
+  for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
+    isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
+    Max = isl_pw_aff_max(Max, NextOperand);
+  }
+
+  return Max;
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
+  llvm_unreachable("SCEVUMaxExpr not yet supported");
+}
+
+__isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
+  llvm_unreachable("Unknowns are always parameters");
+}
+
+int SCEVAffinator::getLoopDepth(const Loop *L) {
+  Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L));
+  assert(outerLoop && "Scop does not contain this loop");
+  return L->getLoopDepth() - outerLoop->getLoopDepth();
+}
+
+ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *AccessType, isl_ctx *Ctx,
+                             const SmallVector<const SCEV *, 4> &DimensionSizes)
+    : BasePtr(BasePtr), AccessType(AccessType), DimensionSizes(DimensionSizes) {
+  const std::string BasePtrName = getIslCompatibleName("MemRef_", BasePtr, "");
+  Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
+}
+
+ScopArrayInfo::~ScopArrayInfo() { isl_id_free(Id); }
+
+isl_id *ScopArrayInfo::getBasePtrId() const { return isl_id_copy(Id); }
+
+void ScopArrayInfo::dump() const { print(errs()); }
+
+void ScopArrayInfo::print(raw_ostream &OS) const {
+  OS << "ScopArrayInfo:\n";
+  OS << "  Base: " << *getBasePtr() << "\n";
+  OS << "  Type: " << *getType() << "\n";
+  OS << "  Dimension Sizes:\n";
+  for (unsigned u = 0; u < getNumberOfDimensions(); u++)
+    OS << "    " << u << ") " << *DimensionSizes[u] << "\n";
+  OS << "\n";
+}
+
+const ScopArrayInfo *
+ScopArrayInfo::getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA) {
+  isl_id *Id = isl_pw_multi_aff_get_tuple_id(PMA, isl_dim_out);
+  assert(Id && "Output dimension didn't have an ID");
+  return getFromId(Id);
+}
+
+const ScopArrayInfo *ScopArrayInfo::getFromId(isl_id *Id) {
+  void *User = isl_id_get_user(Id);
+  const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
+  isl_id_free(Id);
+  return SAI;
+}
+
+const std::string
+MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
+  switch (RT) {
+  case MemoryAccess::RT_NONE:
+    llvm_unreachable("Requested a reduction operator string for a memory "
+                     "access which isn't a reduction");
+  case MemoryAccess::RT_ADD:
+    return "+";
+  case MemoryAccess::RT_MUL:
+    return "*";
+  case MemoryAccess::RT_BOR:
+    return "|";
+  case MemoryAccess::RT_BXOR:
+    return "^";
+  case MemoryAccess::RT_BAND:
+    return "&";
+  }
+  llvm_unreachable("Unknown reduction type");
+  return "";
+}
+
+/// @brief Return the reduction type for a given binary operator
+static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp,
+                                                    const Instruction *Load) {
+  if (!BinOp)
+    return MemoryAccess::RT_NONE;
+  switch (BinOp->getOpcode()) {
+  case Instruction::FAdd:
+    if (!BinOp->hasUnsafeAlgebra())
+      return MemoryAccess::RT_NONE;
+  // Fall through
+  case Instruction::Add:
+    return MemoryAccess::RT_ADD;
+  case Instruction::Or:
+    return MemoryAccess::RT_BOR;
+  case Instruction::Xor:
+    return MemoryAccess::RT_BXOR;
+  case Instruction::And:
+    return MemoryAccess::RT_BAND;
+  case Instruction::FMul:
+    if (!BinOp->hasUnsafeAlgebra())
+      return MemoryAccess::RT_NONE;
+  // Fall through
+  case Instruction::Mul:
+    if (DisableMultiplicativeReductions)
+      return MemoryAccess::RT_NONE;
+    return MemoryAccess::RT_MUL;
+  default:
+    return MemoryAccess::RT_NONE;
+  }
+}
+//===----------------------------------------------------------------------===//
+
+MemoryAccess::~MemoryAccess() {
+  isl_map_free(AccessRelation);
+  isl_map_free(newAccessRelation);
+}
+
+static MemoryAccess::AccessType getMemoryAccessType(const IRAccess &Access) {
+  switch (Access.getType()) {
+  case IRAccess::READ:
+    return MemoryAccess::READ;
+  case IRAccess::MUST_WRITE:
+    return MemoryAccess::MUST_WRITE;
+  case IRAccess::MAY_WRITE:
+    return MemoryAccess::MAY_WRITE;
+  }
+  llvm_unreachable("Unknown IRAccess type!");
+}
+
+const ScopArrayInfo *MemoryAccess::getScopArrayInfo() const {
+  isl_id *ArrayId = getArrayId();
+  void *User = isl_id_get_user(ArrayId);
+  const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
+  isl_id_free(ArrayId);
+  return SAI;
+}
+
+isl_id *MemoryAccess::getArrayId() const {
+  return isl_map_get_tuple_id(AccessRelation, isl_dim_out);
+}
+
+isl_pw_multi_aff *
+MemoryAccess::applyScheduleToAccessRelation(isl_union_map *USchedule) const {
+  isl_map *Schedule, *ScheduledAccRel;
+  isl_union_set *UDomain;
+
+  UDomain = isl_union_set_from_set(getStatement()->getDomain());
+  USchedule = isl_union_map_intersect_domain(USchedule, UDomain);
+  Schedule = isl_map_from_union_map(USchedule);
+  ScheduledAccRel = isl_map_apply_domain(getAccessRelation(), Schedule);
+  return isl_pw_multi_aff_from_map(ScheduledAccRel);
+}
+
+isl_map *MemoryAccess::getOriginalAccessRelation() const {
+  return isl_map_copy(AccessRelation);
+}
+
+std::string MemoryAccess::getOriginalAccessRelationStr() const {
+  return stringFromIslObj(AccessRelation);
+}
+
+__isl_give isl_space *MemoryAccess::getOriginalAccessRelationSpace() const {
+  return isl_map_get_space(AccessRelation);
+}
+
+isl_map *MemoryAccess::getNewAccessRelation() const {
+  return isl_map_copy(newAccessRelation);
+}
+
+isl_basic_map *MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
+  isl_space *Space = isl_space_set_alloc(Statement->getIslCtx(), 0, 1);
+  Space = isl_space_align_params(Space, Statement->getDomainSpace());
+
+  return isl_basic_map_from_domain_and_range(
+      isl_basic_set_universe(Statement->getDomainSpace()),
+      isl_basic_set_universe(Space));
+}
+
+// Formalize no out-of-bound access assumption
+//
+// When delinearizing array accesses we optimistically assume that the
+// delinearized accesses do not access out of bound locations (the subscript
+// expression of each array evaluates for each statement instance that is
+// executed to a value that is larger than zero and strictly smaller than the
+// size of the corresponding dimension). The only exception is the outermost
+// dimension for which we do not need to assume any upper bound.  At this point
+// we formalize this assumption to ensure that at code generation time the
+// relevant run-time checks can be generated.
+//
+// To find the set of constraints necessary to avoid out of bound accesses, we
+// first build the set of data locations that are not within array bounds. We
+// then apply the reverse access relation to obtain the set of iterations that
+// may contain invalid accesses and reduce this set of iterations to the ones
+// that are actually executed by intersecting them with the domain of the
+// statement. If we now project out all loop dimensions, we obtain a set of
+// parameters that may cause statement instances to be executed that may
+// possibly yield out of bound memory accesses. The complement of these
+// constraints is the set of constraints that needs to be assumed to ensure such
+// statement instances are never executed.
+void MemoryAccess::assumeNoOutOfBound(const IRAccess &Access) {
+  isl_space *Space = isl_space_range(getOriginalAccessRelationSpace());
+  isl_set *Outside = isl_set_empty(isl_space_copy(Space));
+  for (int i = 1, Size = Access.Subscripts.size(); i < Size; ++i) {
+    isl_local_space *LS = isl_local_space_from_space(isl_space_copy(Space));
+    isl_pw_aff *Var =
+        isl_pw_aff_var_on_domain(isl_local_space_copy(LS), isl_dim_set, i);
+    isl_pw_aff *Zero = isl_pw_aff_zero_on_domain(LS);
+
+    isl_set *DimOutside;
+
+    DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero);
+    isl_pw_aff *SizeE = SCEVAffinator::getPwAff(Statement, Access.Sizes[i - 1]);
+
+    SizeE = isl_pw_aff_drop_dims(SizeE, isl_dim_in, 0,
+                                 Statement->getNumIterators());
+    SizeE = isl_pw_aff_add_dims(SizeE, isl_dim_in,
+                                isl_space_dim(Space, isl_dim_set));
+    SizeE = isl_pw_aff_set_tuple_id(SizeE, isl_dim_in,
+                                    isl_space_get_tuple_id(Space, isl_dim_set));
+
+    DimOutside = isl_set_union(DimOutside, isl_pw_aff_le_set(SizeE, Var));
+
+    Outside = isl_set_union(Outside, DimOutside);
+  }
+
+  Outside = isl_set_apply(Outside, isl_map_reverse(getAccessRelation()));
+  Outside = isl_set_intersect(Outside, Statement->getDomain());
+  Outside = isl_set_params(Outside);
+  Outside = isl_set_complement(Outside);
+  Statement->getParent()->addAssumption(Outside);
+  isl_space_free(Space);
+}
+
+MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst,
+                           ScopStmt *Statement, const ScopArrayInfo *SAI)
+    : AccType(getMemoryAccessType(Access)), Statement(Statement), Inst(AccInst),
+      newAccessRelation(nullptr) {
+
+  isl_ctx *Ctx = Statement->getIslCtx();
+  BaseAddr = Access.getBase();
+  BaseName = getIslCompatibleName("MemRef_", getBaseAddr(), "");
+
+  isl_id *BaseAddrId = SAI->getBasePtrId();
+
+  if (!Access.isAffine()) {
+    // We overapproximate non-affine accesses with a possible access to the
+    // whole array. For read accesses it does not make a difference, if an
+    // access must or may happen. However, for write accesses it is important to
+    // differentiate between writes that must happen and writes that may happen.
+    AccessRelation = isl_map_from_basic_map(createBasicAccessMap(Statement));
+    AccessRelation =
+        isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId);
+    return;
+  }
+
+  isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0);
+  AccessRelation = isl_map_universe(Space);
+
+  for (int i = 0, Size = Access.Subscripts.size(); i < Size; ++i) {
+    isl_pw_aff *Affine =
+        SCEVAffinator::getPwAff(Statement, Access.Subscripts[i]);
+
+    if (Size == 1) {
+      // For the non delinearized arrays, divide the access function of the last
+      // subscript by the size of the elements in the array.
+      //
+      // A stride one array access in C expressed as A[i] is expressed in
+      // LLVM-IR as something like A[i * elementsize]. This hides the fact that
+      // two subsequent values of 'i' index two values that are stored next to
+      // each other in memory. By this division we make this characteristic
+      // obvious again.
+      isl_val *v = isl_val_int_from_si(Ctx, Access.getElemSizeInBytes());
+      Affine = isl_pw_aff_scale_down_val(Affine, v);
+    }
+
+    isl_map *SubscriptMap = isl_map_from_pw_aff(Affine);
+
+    AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap);
+  }
+
+  Space = Statement->getDomainSpace();
+  AccessRelation = isl_map_set_tuple_id(
+      AccessRelation, isl_dim_in, isl_space_get_tuple_id(Space, isl_dim_set));
+  AccessRelation =
+      isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId);
+
+  assumeNoOutOfBound(Access);
+  isl_space_free(Space);
+}
+
+void MemoryAccess::realignParams() {
+  isl_space *ParamSpace = Statement->getParent()->getParamSpace();
+  AccessRelation = isl_map_align_params(AccessRelation, ParamSpace);
+}
+
+const std::string MemoryAccess::getReductionOperatorStr() const {
+  return MemoryAccess::getReductionOperatorStr(getReductionType());
+}
+
+raw_ostream &polly::operator<<(raw_ostream &OS,
+                               MemoryAccess::ReductionType RT) {
+  if (RT == MemoryAccess::RT_NONE)
+    OS << "NONE";
+  else
+    OS << MemoryAccess::getReductionOperatorStr(RT);
+  return OS;
+}
+
+void MemoryAccess::print(raw_ostream &OS) const {
+  switch (AccType) {
+  case READ:
+    OS.indent(12) << "ReadAccess :=\t";
+    break;
+  case MUST_WRITE:
+    OS.indent(12) << "MustWriteAccess :=\t";
+    break;
+  case MAY_WRITE:
+    OS.indent(12) << "MayWriteAccess :=\t";
+    break;
+  }
+  OS << "[Reduction Type: " << getReductionType() << "]\n";
+  OS.indent(16) << getOriginalAccessRelationStr() << ";\n";
+}
+
+void MemoryAccess::dump() const { print(errs()); }
+
+// Create a map in the size of the provided set domain, that maps from the
+// one element of the provided set domain to another element of the provided
+// set domain.
+// The mapping is limited to all points that are equal in all but the last
+// dimension and for which the last dimension of the input is strict smaller
+// than the last dimension of the output.
+//
+//   getEqualAndLarger(set[i0, i1, ..., iX]):
+//
+//   set[i0, i1, ..., iX] -> set[o0, o1, ..., oX]
+//     : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX
+//
+static isl_map *getEqualAndLarger(isl_space *setDomain) {
+  isl_space *Space = isl_space_map_from_set(setDomain);
+  isl_map *Map = isl_map_universe(isl_space_copy(Space));
+  isl_local_space *MapLocalSpace = isl_local_space_from_space(Space);
+  unsigned lastDimension = isl_map_dim(Map, isl_dim_in) - 1;
+
+  // Set all but the last dimension to be equal for the input and output
+  //
+  //   input[i0, i1, ..., iX] -> output[o0, o1, ..., oX]
+  //     : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1)
+  for (unsigned i = 0; i < lastDimension; ++i)
+    Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
+
+  // Set the last dimension of the input to be strict smaller than the
+  // last dimension of the output.
+  //
+  //   input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX
+  //
+  isl_val *v;
+  isl_ctx *Ctx = isl_map_get_ctx(Map);
+  isl_constraint *c = isl_inequality_alloc(isl_local_space_copy(MapLocalSpace));
+  v = isl_val_int_from_si(Ctx, -1);
+  c = isl_constraint_set_coefficient_val(c, isl_dim_in, lastDimension, v);
+  v = isl_val_int_from_si(Ctx, 1);
+  c = isl_constraint_set_coefficient_val(c, isl_dim_out, lastDimension, v);
+  v = isl_val_int_from_si(Ctx, -1);
+  c = isl_constraint_set_constant_val(c, v);
+
+  Map = isl_map_add_constraint(Map, c);
+
+  isl_local_space_free(MapLocalSpace);
+  return Map;
+}
+
+isl_set *MemoryAccess::getStride(__isl_take const isl_map *Schedule) const {
+  isl_map *S = const_cast<isl_map *>(Schedule);
+  isl_map *AccessRelation = getAccessRelation();
+  isl_space *Space = isl_space_range(isl_map_get_space(S));
+  isl_map *NextScatt = getEqualAndLarger(Space);
+
+  S = isl_map_reverse(S);
+  NextScatt = isl_map_lexmin(NextScatt);
+
+  NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S));
+  NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation));
+  NextScatt = isl_map_apply_domain(NextScatt, S);
+  NextScatt = isl_map_apply_domain(NextScatt, AccessRelation);
+
+  isl_set *Deltas = isl_map_deltas(NextScatt);
+  return Deltas;
+}
+
+bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule,
+                             int StrideWidth) const {
+  isl_set *Stride, *StrideX;
+  bool IsStrideX;
+
+  Stride = getStride(Schedule);
+  StrideX = isl_set_universe(isl_set_get_space(Stride));
+  StrideX = isl_set_fix_si(StrideX, isl_dim_set, 0, StrideWidth);
+  IsStrideX = isl_set_is_equal(Stride, StrideX);
+
+  isl_set_free(StrideX);
+  isl_set_free(Stride);
+
+  return IsStrideX;
+}
+
+bool MemoryAccess::isStrideZero(const isl_map *Schedule) const {
+  return isStrideX(Schedule, 0);
+}
+
+bool MemoryAccess::isScalar() const {
+  return isl_map_n_out(AccessRelation) == 0;
+}
+
+bool MemoryAccess::isStrideOne(const isl_map *Schedule) const {
+  return isStrideX(Schedule, 1);
+}
+
+void MemoryAccess::setNewAccessRelation(isl_map *newAccess) {
+  isl_map_free(newAccessRelation);
+  newAccessRelation = newAccess;
+}
+
+//===----------------------------------------------------------------------===//
+
+isl_map *ScopStmt::getScattering() const { return isl_map_copy(Scattering); }
+
+void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) {
+  assert(isl_set_is_subset(NewDomain, Domain) &&
+         "New domain is not a subset of old domain!");
+  isl_set_free(Domain);
+  Domain = NewDomain;
+  Scattering = isl_map_intersect_domain(Scattering, isl_set_copy(Domain));
+}
+
+void ScopStmt::setScattering(isl_map *NewScattering) {
+  assert(NewScattering && "New scattering is nullptr");
+  isl_map_free(Scattering);
+  Scattering = NewScattering;
+}
+
+void ScopStmt::buildScattering(SmallVectorImpl<unsigned> &Scatter) {
+  unsigned NbIterators = getNumIterators();
+  unsigned NbScatteringDims = Parent.getMaxLoopDepth() * 2 + 1;
+
+  isl_space *Space = isl_space_set_alloc(getIslCtx(), 0, NbScatteringDims);
+  Space = isl_space_set_tuple_name(Space, isl_dim_out, "scattering");
+
+  Scattering = isl_map_from_domain_and_range(isl_set_universe(getDomainSpace()),
+                                             isl_set_universe(Space));
+
+  // Loop dimensions.
+  for (unsigned i = 0; i < NbIterators; ++i)
+    Scattering =
+        isl_map_equate(Scattering, isl_dim_out, 2 * i + 1, isl_dim_in, i);
+
+  // Constant dimensions
+  for (unsigned i = 0; i < NbIterators + 1; ++i)
+    Scattering = isl_map_fix_si(Scattering, isl_dim_out, 2 * i, Scatter[i]);
+
+  // Fill scattering dimensions.
+  for (unsigned i = 2 * NbIterators + 1; i < NbScatteringDims; ++i)
+    Scattering = isl_map_fix_si(Scattering, isl_dim_out, i, 0);
+
+  Scattering = isl_map_align_params(Scattering, Parent.getParamSpace());
+}
+
+void ScopStmt::buildAccesses(TempScop &tempScop) {
+  for (const auto &AccessPair : *tempScop.getAccessFunctions(BB)) {
+    const IRAccess &Access = AccessPair.first;
+    Instruction *AccessInst = AccessPair.second;
+
+    Type *AccessType = getAccessInstType(AccessInst)->getPointerTo();
+    const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
+        Access.getBase(), AccessType, Access.Sizes);
+
+    MemAccs.push_back(new MemoryAccess(Access, AccessInst, this, SAI));
+
+    // We do not track locations for scalar memory accesses at the moment.
+    //
+    // We do not have a use for this information at the moment. If we need this
+    // at some point, the "instruction -> access" mapping needs to be enhanced
+    // as a single instruction could then possibly perform multiple accesses.
+    if (!Access.isScalar()) {
+      assert(!InstructionToAccess.count(AccessInst) &&
+             "Unexpected 1-to-N mapping on instruction to access map!");
+      InstructionToAccess[AccessInst] = MemAccs.back();
+    }
+  }
+}
+
+void ScopStmt::realignParams() {
+  for (MemoryAccess *MA : *this)
+    MA->realignParams();
+
+  Domain = isl_set_align_params(Domain, Parent.getParamSpace());
+  Scattering = isl_map_align_params(Scattering, Parent.getParamSpace());
+}
+
+__isl_give isl_set *ScopStmt::buildConditionSet(const Comparison &Comp) {
+  isl_pw_aff *L = SCEVAffinator::getPwAff(this, Comp.getLHS());
+  isl_pw_aff *R = SCEVAffinator::getPwAff(this, Comp.getRHS());
+
+  switch (Comp.getPred()) {
+  case ICmpInst::ICMP_EQ:
+    return isl_pw_aff_eq_set(L, R);
+  case ICmpInst::ICMP_NE:
+    return isl_pw_aff_ne_set(L, R);
+  case ICmpInst::ICMP_SLT:
+    return isl_pw_aff_lt_set(L, R);
+  case ICmpInst::ICMP_SLE:
+    return isl_pw_aff_le_set(L, R);
+  case ICmpInst::ICMP_SGT:
+    return isl_pw_aff_gt_set(L, R);
+  case ICmpInst::ICMP_SGE:
+    return isl_pw_aff_ge_set(L, R);
+  case ICmpInst::ICMP_ULT:
+    return isl_pw_aff_lt_set(L, R);
+  case ICmpInst::ICMP_UGT:
+    return isl_pw_aff_gt_set(L, R);
+  case ICmpInst::ICMP_ULE:
+    return isl_pw_aff_le_set(L, R);
+  case ICmpInst::ICMP_UGE:
+    return isl_pw_aff_ge_set(L, R);
+  default:
+    llvm_unreachable("Non integer predicate not supported");
+  }
+}
+
+__isl_give isl_set *ScopStmt::addLoopBoundsToDomain(__isl_take isl_set *Domain,
+                                                    TempScop &tempScop) {
+  isl_space *Space;
+  isl_local_space *LocalSpace;
+
+  Space = isl_set_get_space(Domain);
+  LocalSpace = isl_local_space_from_space(Space);
+
+  ScalarEvolution *SE = getParent()->getSE();
+  for (int i = 0, e = getNumIterators(); i != e; ++i) {
+    isl_aff *Zero = isl_aff_zero_on_domain(isl_local_space_copy(LocalSpace));
+    isl_pw_aff *IV =
+        isl_pw_aff_from_aff(isl_aff_set_coefficient_si(Zero, isl_dim_in, i, 1));
+
+    // 0 <= IV.
+    isl_set *LowerBound = isl_pw_aff_nonneg_set(isl_pw_aff_copy(IV));
+    Domain = isl_set_intersect(Domain, LowerBound);
+
+    // IV <= LatchExecutions.
+    const Loop *L = getLoopForDimension(i);
+    const SCEV *LatchExecutions = SE->getBackedgeTakenCount(L);
+    isl_pw_aff *UpperBound = SCEVAffinator::getPwAff(this, LatchExecutions);
+    isl_set *UpperBoundSet = isl_pw_aff_le_set(IV, UpperBound);
+    Domain = isl_set_intersect(Domain, UpperBoundSet);
+  }
+
+  isl_local_space_free(LocalSpace);
+  return Domain;
+}
+
+__isl_give isl_set *ScopStmt::addConditionsToDomain(__isl_take isl_set *Domain,
+                                                    TempScop &tempScop,
+                                                    const Region &CurRegion) {
+  const Region *TopRegion = tempScop.getMaxRegion().getParent(),
+               *CurrentRegion = &CurRegion;
+  const BasicBlock *BranchingBB = BB;
+
+  do {
+    if (BranchingBB != CurrentRegion->getEntry()) {
+      if (const BBCond *Condition = tempScop.getBBCond(BranchingBB))
+        for (const auto &C : *Condition) {
+          isl_set *ConditionSet = buildConditionSet(C);
+          Domain = isl_set_intersect(Domain, ConditionSet);
+        }
+    }
+    BranchingBB = CurrentRegion->getEntry();
+    CurrentRegion = CurrentRegion->getParent();
+  } while (TopRegion != CurrentRegion);
+
+  return Domain;
+}
+
+__isl_give isl_set *ScopStmt::buildDomain(TempScop &tempScop,
+                                          const Region &CurRegion) {
+  isl_space *Space;
+  isl_set *Domain;
+  isl_id *Id;
+
+  Space = isl_space_set_alloc(getIslCtx(), 0, getNumIterators());
+
+  Id = isl_id_alloc(getIslCtx(), getBaseName(), this);
+
+  Domain = isl_set_universe(Space);
+  Domain = addLoopBoundsToDomain(Domain, tempScop);
+  Domain = addConditionsToDomain(Domain, tempScop, CurRegion);
+  Domain = isl_set_set_tuple_id(Domain, Id);
+
+  return Domain;
+}
+
+void ScopStmt::deriveAssumptionsFromGEP(GetElementPtrInst *GEP) {
+  int Dimension = 0;
+  isl_ctx *Ctx = Parent.getIslCtx();
+  isl_local_space *LSpace = isl_local_space_from_space(getDomainSpace());
+  Type *Ty = GEP->getPointerOperandType();
+  ScalarEvolution &SE = *Parent.getSE();
+
+  if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
+    Dimension = 1;
+    Ty = PtrTy->getElementType();
+  }
+
+  while (auto ArrayTy = dyn_cast<ArrayType>(Ty)) {
+    unsigned int Operand = 1 + Dimension;
+
+    if (GEP->getNumOperands() <= Operand)
+      break;
+
+    const SCEV *Expr = SE.getSCEV(GEP->getOperand(Operand));
+
+    if (isAffineExpr(&Parent.getRegion(), Expr, SE)) {
+      isl_pw_aff *AccessOffset = SCEVAffinator::getPwAff(this, Expr);
+      AccessOffset =
+          isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId());
+
+      isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain(
+          isl_local_space_copy(LSpace),
+          isl_val_int_from_si(Ctx, ArrayTy->getNumElements())));
+
+      isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize);
+      OutOfBound = isl_set_intersect(getDomain(), OutOfBound);
+      OutOfBound = isl_set_params(OutOfBound);
+      isl_set *InBound = isl_set_complement(OutOfBound);
+      isl_set *Executed = isl_set_params(getDomain());
+
+      // A => B == !A or B
+      isl_set *InBoundIfExecuted =
+          isl_set_union(isl_set_complement(Executed), InBound);
+
+      Parent.addAssumption(InBoundIfExecuted);
+    }
+
+    Dimension += 1;
+    Ty = ArrayTy->getElementType();
+  }
+
+  isl_local_space_free(LSpace);
+}
+
+void ScopStmt::deriveAssumptions() {
+  for (Instruction &Inst : *BB)
+    if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst))
+      deriveAssumptionsFromGEP(GEP);
+}
+
+ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
+                   BasicBlock &bb, SmallVectorImpl<Loop *> &Nest,
+                   SmallVectorImpl<unsigned> &Scatter)
+    : Parent(parent), BB(&bb), NestLoops(Nest.size()) {
+  // Setup the induction variables.
+  for (unsigned i = 0, e = Nest.size(); i < e; ++i)
+    NestLoops[i] = Nest[i];
+
+  BaseName = getIslCompatibleName("Stmt_", &bb, "");
+
+  Domain = buildDomain(tempScop, CurRegion);
+  buildScattering(Scatter);
+  buildAccesses(tempScop);
+  checkForReductions();
+  deriveAssumptions();
+}
+
+/// @brief Collect loads which might form a reduction chain with @p StoreMA
+///
+/// Check if the stored value for @p StoreMA is a binary operator with one or
+/// two loads as operands. If the binary operand is commutative & associative,
+/// used only once (by @p StoreMA) and its load operands are also used only
+/// once, we have found a possible reduction chain. It starts at an operand
+/// load and includes the binary operator and @p StoreMA.
+///
+/// Note: We allow only one use to ensure the load and binary operator cannot
+///       escape this block or into any other store except @p StoreMA.
+void ScopStmt::collectCandiateReductionLoads(
+    MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) {
+  auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction());
+  if (!Store)
+    return;
+
+  // Skip if there is not one binary operator between the load and the store
+  auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand());
+  if (!BinOp)
+    return;
+
+  // Skip if the binary operators has multiple uses
+  if (BinOp->getNumUses() != 1)
+    return;
+
+  // Skip if the opcode of the binary operator is not commutative/associative
+  if (!BinOp->isCommutative() || !BinOp->isAssociative())
+    return;
+
+  // Skip if the binary operator is outside the current SCoP
+  if (BinOp->getParent() != Store->getParent())
+    return;
+
+  // Skip if it is a multiplicative reduction and we disabled them
+  if (DisableMultiplicativeReductions &&
+      (BinOp->getOpcode() == Instruction::Mul ||
+       BinOp->getOpcode() == Instruction::FMul))
+    return;
+
+  // Check the binary operator operands for a candidate load
+  auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0));
+  auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1));
+  if (!PossibleLoad0 && !PossibleLoad1)
+    return;
+
+  // A load is only a candidate if it cannot escape (thus has only this use)
+  if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1)
+    if (PossibleLoad0->getParent() == Store->getParent())
+      Loads.push_back(lookupAccessFor(PossibleLoad0));
+  if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1)
+    if (PossibleLoad1->getParent() == Store->getParent())
+      Loads.push_back(lookupAccessFor(PossibleLoad1));
+}
+
+/// @brief Check for reductions in this ScopStmt
+///
+/// Iterate over all store memory accesses and check for valid binary reduction
+/// like chains. For all candidates we check if they have the same base address
+/// and there are no other accesses which overlap with them. The base address
+/// check rules out impossible reductions candidates early. The overlap check,
+/// together with the "only one user" check in collectCandiateReductionLoads,
+/// guarantees that none of the intermediate results will escape during
+/// execution of the loop nest. We basically check here that no other memory
+/// access can access the same memory as the potential reduction.
+void ScopStmt::checkForReductions() {
+  SmallVector<MemoryAccess *, 2> Loads;
+  SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates;
+
+  // First collect candidate load-store reduction chains by iterating over all
+  // stores and collecting possible reduction loads.
+  for (MemoryAccess *StoreMA : MemAccs) {
+    if (StoreMA->isRead())
+      continue;
+
+    Loads.clear();
+    collectCandiateReductionLoads(StoreMA, Loads);
+    for (MemoryAccess *LoadMA : Loads)
+      Candidates.push_back(std::make_pair(LoadMA, StoreMA));
+  }
+
+  // Then check each possible candidate pair.
+  for (const auto &CandidatePair : Candidates) {
+    bool Valid = true;
+    isl_map *LoadAccs = CandidatePair.first->getAccessRelation();
+    isl_map *StoreAccs = CandidatePair.second->getAccessRelation();
+
+    // Skip those with obviously unequal base addresses.
+    if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) {
+      isl_map_free(LoadAccs);
+      isl_map_free(StoreAccs);
+      continue;
+    }
+
+    // And check if the remaining for overlap with other memory accesses.
+    isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs);
+    AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain());
+    isl_set *AllAccs = isl_map_range(AllAccsRel);
+
+    for (MemoryAccess *MA : MemAccs) {
+      if (MA == CandidatePair.first || MA == CandidatePair.second)
+        continue;
+
+      isl_map *AccRel =
+          isl_map_intersect_domain(MA->getAccessRelation(), getDomain());
+      isl_set *Accs = isl_map_range(AccRel);
+
+      if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) {
+        isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs));
+        Valid = Valid && isl_set_is_empty(OverlapAccs);
+        isl_set_free(OverlapAccs);
+      }
+    }
+
+    isl_set_free(AllAccs);
+    if (!Valid)
+      continue;
+
+    const LoadInst *Load =
+        dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction());
+    MemoryAccess::ReductionType RT =
+        getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load);
+
+    // If no overlapping access was found we mark the load and store as
+    // reduction like.
+    CandidatePair.first->markAsReductionLike(RT);
+    CandidatePair.second->markAsReductionLike(RT);
+  }
+}
+
+std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); }
+
+std::string ScopStmt::getScatteringStr() const {
+  return stringFromIslObj(Scattering);
+}
+
+unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); }
+
+unsigned ScopStmt::getNumIterators() const {
+  // The final read has one dimension with one element.
+  if (!BB)
+    return 1;
+
+  return NestLoops.size();
+}
+
+unsigned ScopStmt::getNumScattering() const {
+  return isl_map_dim(Scattering, isl_dim_out);
+}
+
+const char *ScopStmt::getBaseName() const { return BaseName.c_str(); }
+
+const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const {
+  return NestLoops[Dimension];
+}
+
+isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); }
+
+isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); }
+
+isl_space *ScopStmt::getDomainSpace() const {
+  return isl_set_get_space(Domain);
+}
+
+isl_id *ScopStmt::getDomainId() const { return isl_set_get_tuple_id(Domain); }
+
+ScopStmt::~ScopStmt() {
+  while (!MemAccs.empty()) {
+    delete MemAccs.back();
+    MemAccs.pop_back();
+  }
+
+  isl_set_free(Domain);
+  isl_map_free(Scattering);
+}
+
+void ScopStmt::print(raw_ostream &OS) const {
+  OS << "\t" << getBaseName() << "\n";
+  OS.indent(12) << "Domain :=\n";
+
+  if (Domain) {
+    OS.indent(16) << getDomainStr() << ";\n";
+  } else
+    OS.indent(16) << "n/a\n";
+
+  OS.indent(12) << "Scattering :=\n";
+
+  if (Domain) {
+    OS.indent(16) << getScatteringStr() << ";\n";
+  } else
+    OS.indent(16) << "n/a\n";
+
+  for (MemoryAccess *Access : MemAccs)
+    Access->print(OS);
+}
+
+void ScopStmt::dump() const { print(dbgs()); }
+
+//===----------------------------------------------------------------------===//
+/// Scop class implement
+
+void Scop::setContext(__isl_take isl_set *NewContext) {
+  NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context));
+  isl_set_free(Context);
+  Context = NewContext;
+}
+
+void Scop::addParams(std::vector<const SCEV *> NewParameters) {
+  for (const SCEV *Parameter : NewParameters) {
+    if (ParameterIds.find(Parameter) != ParameterIds.end())
+      continue;
+
+    int dimension = Parameters.size();
+
+    Parameters.push_back(Parameter);
+    ParameterIds[Parameter] = dimension;
+  }
+}
+
+__isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) const {
+  ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter);
+
+  if (IdIter == ParameterIds.end())
+    return nullptr;
+
+  std::string ParameterName;
+
+  if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
+    Value *Val = ValueParameter->getValue();
+    ParameterName = Val->getName();
+  }
+
+  if (ParameterName == "" || ParameterName.substr(0, 2) == "p_")
+    ParameterName = "p_" + utostr_32(IdIter->second);
+
+  return isl_id_alloc(getIslCtx(), ParameterName.c_str(),
+                      const_cast<void *>((const void *)Parameter));
+}
+
+void Scop::buildContext() {
+  isl_space *Space = isl_space_params_alloc(IslCtx, 0);
+  Context = isl_set_universe(isl_space_copy(Space));
+  AssumedContext = isl_set_universe(Space);
+}
+
+void Scop::addParameterBounds() {
+  for (unsigned i = 0; i < isl_set_dim(Context, isl_dim_param); ++i) {
+    isl_val *V;
+    isl_id *Id;
+    const SCEV *Scev;
+    const IntegerType *T;
+
+    Id = isl_set_get_dim_id(Context, isl_dim_param, i);
+    Scev = (const SCEV *)isl_id_get_user(Id);
+    T = dyn_cast<IntegerType>(Scev->getType());
+    isl_id_free(Id);
+
+    assert(T && "Not an integer type");
+    int Width = T->getBitWidth();
+
+    V = isl_val_int_from_si(IslCtx, Width - 1);
+    V = isl_val_2exp(V);
+    V = isl_val_neg(V);
+    Context = isl_set_lower_bound_val(Context, isl_dim_param, i, V);
+
+    V = isl_val_int_from_si(IslCtx, Width - 1);
+    V = isl_val_2exp(V);
+    V = isl_val_sub_ui(V, 1);
+    Context = isl_set_upper_bound_val(Context, isl_dim_param, i, V);
+  }
+}
+
+void Scop::realignParams() {
+  // Add all parameters into a common model.
+  isl_space *Space = isl_space_params_alloc(IslCtx, ParameterIds.size());
+
+  for (const auto &ParamID : ParameterIds) {
+    const SCEV *Parameter = ParamID.first;
+    isl_id *id = getIdForParam(Parameter);
+    Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id);
+  }
+
+  // Align the parameters of all data structures to the model.
+  Context = isl_set_align_params(Context, Space);
+
+  for (ScopStmt *Stmt : *this)
+    Stmt->realignParams();
+}
+
+void Scop::simplifyAssumedContext() {
+  // The parameter constraints of the iteration domains give us a set of
+  // constraints that need to hold for all cases where at least a single
+  // statement iteration is executed in the whole scop. We now simplify the
+  // assumed context under the assumption that such constraints hold and at
+  // least a single statement iteration is executed. For cases where no
+  // statement instances are executed, the assumptions we have taken about
+  // the executed code do not matter and can be changed.
+  //
+  // WARNING: This only holds if the assumptions we have taken do not reduce
+  //          the set of statement instances that are executed. Otherwise we
+  //          may run into a case where the iteration domains suggest that
+  //          for a certain set of parameter constraints no code is executed,
+  //          but in the original program some computation would have been
+  //          performed. In such a case, modifying the run-time conditions and
+  //          possibly influencing the run-time check may cause certain scops
+  //          to not be executed.
+  //
+  // Example:
+  //
+  //   When delinearizing the following code:
+  //
+  //     for (long i = 0; i < 100; i++)
+  //       for (long j = 0; j < m; j++)
+  //         A[i+p][j] = 1.0;
+  //
+  //   we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
+  //   otherwise we would access out of bound data. Now, knowing that code is
+  //   only executed for the case m >= 0, it is sufficient to assume p >= 0.
+  AssumedContext =
+      isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains()));
+}
+
+/// @brief Add the minimal/maximal access in @p Set to @p User.
+static int buildMinMaxAccess(__isl_take isl_set *Set, void *User) {
+  Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User;
+  isl_pw_multi_aff *MinPMA, *MaxPMA;
+  isl_pw_aff *LastDimAff;
+  isl_aff *OneAff;
+  unsigned Pos;
+
+  // Restrict the number of parameters involved in the access as the lexmin/
+  // lexmax computation will take too long if this number is high.
+  //
+  // Experiments with a simple test case using an i7 4800MQ:
+  //
+  //  #Parameters involved | Time (in sec)
+  //            6          |     0.01
+  //            7          |     0.04
+  //            8          |     0.12
+  //            9          |     0.40
+  //           10          |     1.54
+  //           11          |     6.78
+  //           12          |    30.38
+  //
+  if (isl_set_n_param(Set) > RunTimeChecksMaxParameters) {
+    unsigned InvolvedParams = 0;
+    for (unsigned u = 0, e = isl_set_n_param(Set); u < e; u++)
+      if (isl_set_involves_dims(Set, isl_dim_param, u, 1))
+        InvolvedParams++;
+
+    if (InvolvedParams > RunTimeChecksMaxParameters) {
+      isl_set_free(Set);
+      return -1;
+    }
+  }
+
+  MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set));
+  MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set));
+
+  MinPMA = isl_pw_multi_aff_coalesce(MinPMA);
+  MaxPMA = isl_pw_multi_aff_coalesce(MaxPMA);
+
+  // Adjust the last dimension of the maximal access by one as we want to
+  // enclose the accessed memory region by MinPMA and MaxPMA. The pointer
+  // we test during code generation might now point after the end of the
+  // allocated array but we will never dereference it anyway.
+  assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) &&
+         "Assumed at least one output dimension");
+  Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1;
+  LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos);
+  OneAff = isl_aff_zero_on_domain(
+      isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff)));
+  OneAff = isl_aff_add_constant_si(OneAff, 1);
+  LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff));
+  MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff);
+
+  MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA));
+
+  isl_set_free(Set);
+  return 0;
+}
+
+static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) {
+  isl_set *Domain = MA->getStatement()->getDomain();
+  Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain));
+  return isl_set_reset_tuple_id(Domain);
+}
+
+bool Scop::buildAliasGroups(AliasAnalysis &AA) {
+  // To create sound alias checks we perform the following steps:
+  //   o) Use the alias analysis and an alias set tracker to build alias sets
+  //      for all memory accesses inside the SCoP.
+  //   o) For each alias set we then map the aliasing pointers back to the
+  //      memory accesses we know, thus obtain groups of memory accesses which
+  //      might alias.
+  //   o) We divide each group based on the domains of the minimal/maximal
+  //      accesses. That means two minimal/maximal accesses are only in a group
+  //      if their access domains intersect, otherwise they are in different
+  //      ones.
+  //   o) We split groups such that they contain at most one read only base
+  //      address.
+  //   o) For each group with more than one base pointer we then compute minimal
+  //      and maximal accesses to each array in this group.
+  using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
+
+  AliasSetTracker AST(AA);
+
+  DenseMap<Value *, MemoryAccess *> PtrToAcc;
+  DenseSet<Value *> HasWriteAccess;
+  for (ScopStmt *Stmt : *this) {
+
+    // Skip statements with an empty domain as they will never be executed.
+    isl_set *StmtDomain = Stmt->getDomain();
+    bool StmtDomainEmpty = isl_set_is_empty(StmtDomain);
+    isl_set_free(StmtDomain);
+    if (StmtDomainEmpty)
+      continue;
+
+    for (MemoryAccess *MA : *Stmt) {
+      if (MA->isScalar())
+        continue;
+      if (!MA->isRead())
+        HasWriteAccess.insert(MA->getBaseAddr());
+      Instruction *Acc = MA->getAccessInstruction();
+      PtrToAcc[getPointerOperand(*Acc)] = MA;
+      AST.add(Acc);
+    }
+  }
+
+  SmallVector<AliasGroupTy, 4> AliasGroups;
+  for (AliasSet &AS : AST) {
+    if (AS.isMustAlias() || AS.isForwardingAliasSet())
+      continue;
+    AliasGroupTy AG;
+    for (auto PR : AS)
+      AG.push_back(PtrToAcc[PR.getValue()]);
+    assert(AG.size() > 1 &&
+           "Alias groups should contain at least two accesses");
+    AliasGroups.push_back(std::move(AG));
+  }
+
+  // Split the alias groups based on their domain.
+  for (unsigned u = 0; u < AliasGroups.size(); u++) {
+    AliasGroupTy NewAG;
+    AliasGroupTy &AG = AliasGroups[u];
+    AliasGroupTy::iterator AGI = AG.begin();
+    isl_set *AGDomain = getAccessDomain(*AGI);
+    while (AGI != AG.end()) {
+      MemoryAccess *MA = *AGI;
+      isl_set *MADomain = getAccessDomain(MA);
+      if (isl_set_is_disjoint(AGDomain, MADomain)) {
+        NewAG.push_back(MA);
+        AGI = AG.erase(AGI);
+        isl_set_free(MADomain);
+      } else {
+        AGDomain = isl_set_union(AGDomain, MADomain);
+        AGI++;
+      }
+    }
+    if (NewAG.size() > 1)
+      AliasGroups.push_back(std::move(NewAG));
+    isl_set_free(AGDomain);
+  }
+
+  DenseMap<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs;
+  SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues;
+  for (AliasGroupTy &AG : AliasGroups) {
+    NonReadOnlyBaseValues.clear();
+    ReadOnlyPairs.clear();
+
+    if (AG.size() < 2) {
+      AG.clear();
+      continue;
+    }
+
+    for (auto II = AG.begin(); II != AG.end();) {
+      Value *BaseAddr = (*II)->getBaseAddr();
+      if (HasWriteAccess.count(BaseAddr)) {
+        NonReadOnlyBaseValues.insert(BaseAddr);
+        II++;
+      } else {
+        ReadOnlyPairs[BaseAddr].insert(*II);
+        II = AG.erase(II);
+      }
+    }
+
+    // If we don't have read only pointers check if there are at least two
+    // non read only pointers, otherwise clear the alias group.
+    if (ReadOnlyPairs.empty()) {
+      if (NonReadOnlyBaseValues.size() <= 1)
+        AG.clear();
+      continue;
+    }
+
+    // If we don't have non read only pointers clear the alias group.
+    if (NonReadOnlyBaseValues.empty()) {
+      AG.clear();
+      continue;
+    }
+
+    // If we have both read only and non read only base pointers we combine
+    // the non read only ones with exactly one read only one at a time into a
+    // new alias group and clear the old alias group in the end.
+    for (const auto &ReadOnlyPair : ReadOnlyPairs) {
+      AliasGroupTy AGNonReadOnly = AG;
+      for (MemoryAccess *MA : ReadOnlyPair.second)
+        AGNonReadOnly.push_back(MA);
+      AliasGroups.push_back(std::move(AGNonReadOnly));
+    }
+    AG.clear();
+  }
+
+  bool Valid = true;
+  for (AliasGroupTy &AG : AliasGroups) {
+    if (AG.empty())
+      continue;
+
+    MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy();
+    MinMaxAccesses->reserve(AG.size());
+
+    isl_union_map *Accesses = isl_union_map_empty(getParamSpace());
+    for (MemoryAccess *MA : AG)
+      Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation());
+    Accesses = isl_union_map_intersect_domain(Accesses, getDomains());
+
+    isl_union_set *Locations = isl_union_map_range(Accesses);
+    Locations = isl_union_set_intersect_params(Locations, getAssumedContext());
+    Locations = isl_union_set_coalesce(Locations);
+    Locations = isl_union_set_detect_equalities(Locations);
+    Valid = (0 == isl_union_set_foreach_set(Locations, buildMinMaxAccess,
+                                            MinMaxAccesses));
+    isl_union_set_free(Locations);
+    MinMaxAliasGroups.push_back(MinMaxAccesses);
+
+    if (!Valid)
+      break;
+  }
+
+  return Valid;
+}
+
+static unsigned getMaxLoopDepthInRegion(const Region &R, LoopInfo &LI) {
+  unsigned MinLD = INT_MAX, MaxLD = 0;
+  for (BasicBlock *BB : R.blocks()) {
+    if (Loop *L = LI.getLoopFor(BB)) {
+      if (!R.contains(L))
+        continue;
+      unsigned LD = L->getLoopDepth();
+      MinLD = std::min(MinLD, LD);
+      MaxLD = std::max(MaxLD, LD);
+    }
+  }
+
+  // Handle the case that there is no loop in the SCoP first.
+  if (MaxLD == 0)
+    return 1;
+
+  assert(MinLD >= 1 && "Minimal loop depth should be at least one");
+  assert(MaxLD >= MinLD &&
+         "Maximal loop depth was smaller than mininaml loop depth?");
+  return MaxLD - MinLD + 1;
+}
+
+void Scop::dropConstantScheduleDims() {
+  isl_union_map *FullSchedule = getSchedule();
+
+  if (isl_union_map_n_map(FullSchedule) == 0) {
+    isl_union_map_free(FullSchedule);
+    return;
+  }
+
+  isl_set *ScheduleSpace =
+      isl_set_from_union_set(isl_union_map_range(FullSchedule));
+  isl_map *DropDimMap = isl_set_identity(isl_set_copy(ScheduleSpace));
+
+  int NumDimsDropped = 0;
+  for (unsigned i = 0; i < isl_set_dim(ScheduleSpace, isl_dim_set); i++)
+    if (i % 2 == 0) {
+      isl_val *FixedVal =
+          isl_set_plain_get_val_if_fixed(ScheduleSpace, isl_dim_set, i);
+      if (isl_val_is_int(FixedVal)) {
+        DropDimMap =
+            isl_map_project_out(DropDimMap, isl_dim_out, i - NumDimsDropped, 1);
+        NumDimsDropped++;
+      }
+      isl_val_free(FixedVal);
+    }
+
+  DropDimMap = isl_map_set_tuple_id(
+      DropDimMap, isl_dim_out, isl_map_get_tuple_id(DropDimMap, isl_dim_in));
+  for (auto *S : *this) {
+    isl_map *Schedule = S->getScattering();
+    Schedule = isl_map_apply_range(Schedule, isl_map_copy(DropDimMap));
+    S->setScattering(Schedule);
+  }
+  isl_set_free(ScheduleSpace);
+  isl_map_free(DropDimMap);
+}
+
+Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution,
+           isl_ctx *Context)
+    : SE(&ScalarEvolution), R(tempScop.getMaxRegion()),
+      MaxLoopDepth(getMaxLoopDepthInRegion(tempScop.getMaxRegion(), LI)) {
+  IslCtx = Context;
+  buildContext();
+
+  SmallVector<Loop *, 8> NestLoops;
+  SmallVector<unsigned, 8> Scatter;
+
+  Scatter.assign(MaxLoopDepth + 1, 0);
+
+  // Build the iteration domain, access functions and scattering functions
+  // traversing the region tree.
+  buildScop(tempScop, getRegion(), NestLoops, Scatter, LI);
+
+  realignParams();
+  addParameterBounds();
+  simplifyAssumedContext();
+  dropConstantScheduleDims();
+
+  assert(NestLoops.empty() && "NestLoops not empty at top level!");
+}
+
+Scop::~Scop() {
+  isl_set_free(Context);
+  isl_set_free(AssumedContext);
+
+  // Free the statements;
+  for (ScopStmt *Stmt : *this)
+    delete Stmt;
+
+  // Free the ScopArrayInfo objects.
+  for (auto &ScopArrayInfoPair : ScopArrayInfoMap)
+    delete ScopArrayInfoPair.second;
+
+  // Free the alias groups
+  for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
+    for (MinMaxAccessTy &MMA : *MinMaxAccesses) {
+      isl_pw_multi_aff_free(MMA.first);
+      isl_pw_multi_aff_free(MMA.second);
+    }
+    delete MinMaxAccesses;
+  }
+}
+
+const ScopArrayInfo *
+Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType,
+                               const SmallVector<const SCEV *, 4> &Sizes) {
+  const ScopArrayInfo *&SAI = ScopArrayInfoMap[BasePtr];
+  if (!SAI)
+    SAI = new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Sizes);
+  return SAI;
+}
+
+const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr) {
+  const SCEV *PtrSCEV = SE->getSCEV(BasePtr);
+  const SCEVUnknown *PtrBaseSCEV =
+      cast<SCEVUnknown>(SE->getPointerBase(PtrSCEV));
+  const ScopArrayInfo *SAI = ScopArrayInfoMap[PtrBaseSCEV->getValue()];
+  assert(SAI && "No ScopArrayInfo available for this base pointer");
+  return SAI;
+}
+
+std::string Scop::getContextStr() const { return stringFromIslObj(Context); }
+std::string Scop::getAssumedContextStr() const {
+  return stringFromIslObj(AssumedContext);
+}
+
+std::string Scop::getNameStr() const {
+  std::string ExitName, EntryName;
+  raw_string_ostream ExitStr(ExitName);
+  raw_string_ostream EntryStr(EntryName);
+
+  R.getEntry()->printAsOperand(EntryStr, false);
+  EntryStr.str();
+
+  if (R.getExit()) {
+    R.getExit()->printAsOperand(ExitStr, false);
+    ExitStr.str();
+  } else
+    ExitName = "FunctionExit";
+
+  return EntryName + "---" + ExitName;
+}
+
+__isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); }
+__isl_give isl_space *Scop::getParamSpace() const {
+  return isl_set_get_space(this->Context);
+}
+
+__isl_give isl_set *Scop::getAssumedContext() const {
+  return isl_set_copy(AssumedContext);
+}
+
+void Scop::addAssumption(__isl_take isl_set *Set) {
+  AssumedContext = isl_set_intersect(AssumedContext, Set);
+  AssumedContext = isl_set_coalesce(AssumedContext);
+}
+
+void Scop::printContext(raw_ostream &OS) const {
+  OS << "Context:\n";
+
+  if (!Context) {
+    OS.indent(4) << "n/a\n\n";
+    return;
+  }
+
+  OS.indent(4) << getContextStr() << "\n";
+
+  OS.indent(4) << "Assumed Context:\n";
+  if (!AssumedContext) {
+    OS.indent(4) << "n/a\n\n";
+    return;
+  }
+
+  OS.indent(4) << getAssumedContextStr() << "\n";
+
+  for (const SCEV *Parameter : Parameters) {
+    int Dim = ParameterIds.find(Parameter)->second;
+    OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n";
+  }
+}
+
+void Scop::printAliasAssumptions(raw_ostream &OS) const {
+  OS.indent(4) << "Alias Groups (" << MinMaxAliasGroups.size() << "):\n";
+  if (MinMaxAliasGroups.empty()) {
+    OS.indent(8) << "n/a\n";
+    return;
+  }
+  for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
+    OS.indent(8) << "[[";
+    for (MinMaxAccessTy &MinMacAccess : *MinMaxAccesses)
+      OS << " <" << MinMacAccess.first << ", " << MinMacAccess.second << ">";
+    OS << " ]]\n";
+  }
+}
+
+void Scop::printStatements(raw_ostream &OS) const {
+  OS << "Statements {\n";
+
+  for (ScopStmt *Stmt : *this)
+    OS.indent(4) << *Stmt;
+
+  OS.indent(4) << "}\n";
+}
+
+void Scop::print(raw_ostream &OS) const {
+  OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName()
+               << "\n";
+  OS.indent(4) << "Region: " << getNameStr() << "\n";
+  OS.indent(4) << "Max Loop Depth:  " << getMaxLoopDepth() << "\n";
+  printContext(OS.indent(4));
+  printAliasAssumptions(OS);
+  printStatements(OS.indent(4));
+}
+
+void Scop::dump() const { print(dbgs()); }
+
+isl_ctx *Scop::getIslCtx() const { return IslCtx; }
+
+__isl_give isl_union_set *Scop::getDomains() {
+  isl_union_set *Domain = isl_union_set_empty(getParamSpace());
+
+  for (ScopStmt *Stmt : *this)
+    Domain = isl_union_set_add_set(Domain, Stmt->getDomain());
+
+  return Domain;
+}
+
+__isl_give isl_union_map *Scop::getMustWrites() {
+  isl_union_map *Write = isl_union_map_empty(this->getParamSpace());
+
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isMustWrite())
+        continue;
+
+      isl_set *Domain = Stmt->getDomain();
+      isl_map *AccessDomain = MA->getAccessRelation();
+      AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
+      Write = isl_union_map_add_map(Write, AccessDomain);
+    }
+  }
+  return isl_union_map_coalesce(Write);
+}
+
+__isl_give isl_union_map *Scop::getMayWrites() {
+  isl_union_map *Write = isl_union_map_empty(this->getParamSpace());
+
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isMayWrite())
+        continue;
+
+      isl_set *Domain = Stmt->getDomain();
+      isl_map *AccessDomain = MA->getAccessRelation();
+      AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
+      Write = isl_union_map_add_map(Write, AccessDomain);
+    }
+  }
+  return isl_union_map_coalesce(Write);
+}
+
+__isl_give isl_union_map *Scop::getWrites() {
+  isl_union_map *Write = isl_union_map_empty(this->getParamSpace());
+
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isWrite())
+        continue;
+
+      isl_set *Domain = Stmt->getDomain();
+      isl_map *AccessDomain = MA->getAccessRelation();
+      AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
+      Write = isl_union_map_add_map(Write, AccessDomain);
+    }
+  }
+  return isl_union_map_coalesce(Write);
+}
+
+__isl_give isl_union_map *Scop::getReads() {
+  isl_union_map *Read = isl_union_map_empty(getParamSpace());
+
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isRead())
+        continue;
+
+      isl_set *Domain = Stmt->getDomain();
+      isl_map *AccessDomain = MA->getAccessRelation();
+
+      AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
+      Read = isl_union_map_add_map(Read, AccessDomain);
+    }
+  }
+  return isl_union_map_coalesce(Read);
+}
+
+__isl_give isl_union_map *Scop::getSchedule() {
+  isl_union_map *Schedule = isl_union_map_empty(getParamSpace());
+
+  for (ScopStmt *Stmt : *this)
+    Schedule = isl_union_map_add_map(Schedule, Stmt->getScattering());
+
+  return isl_union_map_coalesce(Schedule);
+}
+
+bool Scop::restrictDomains(__isl_take isl_union_set *Domain) {
+  bool Changed = false;
+  for (ScopStmt *Stmt : *this) {
+    isl_union_set *StmtDomain = isl_union_set_from_set(Stmt->getDomain());
+    isl_union_set *NewStmtDomain = isl_union_set_intersect(
+        isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain));
+
+    if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) {
+      isl_union_set_free(StmtDomain);
+      isl_union_set_free(NewStmtDomain);
+      continue;
+    }
+
+    Changed = true;
+
+    isl_union_set_free(StmtDomain);
+    NewStmtDomain = isl_union_set_coalesce(NewStmtDomain);
+
+    if (isl_union_set_is_empty(NewStmtDomain)) {
+      Stmt->restrictDomain(isl_set_empty(Stmt->getDomainSpace()));
+      isl_union_set_free(NewStmtDomain);
+    } else
+      Stmt->restrictDomain(isl_set_from_union_set(NewStmtDomain));
+  }
+  isl_union_set_free(Domain);
+  return Changed;
+}
+
+ScalarEvolution *Scop::getSE() const { return SE; }
+
+bool Scop::isTrivialBB(BasicBlock *BB, TempScop &tempScop) {
+  if (tempScop.getAccessFunctions(BB))
+    return false;
+
+  return true;
+}
+
+void Scop::buildScop(TempScop &tempScop, const Region &CurRegion,
+                     SmallVectorImpl<Loop *> &NestLoops,
+                     SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI) {
+  Loop *L = castToLoop(CurRegion, LI);
+
+  if (L)
+    NestLoops.push_back(L);
+
+  unsigned loopDepth = NestLoops.size();
+  assert(Scatter.size() > loopDepth && "Scatter not big enough!");
+
+  for (Region::const_element_iterator I = CurRegion.element_begin(),
+                                      E = CurRegion.element_end();
+       I != E; ++I)
+    if (I->isSubRegion())
+      buildScop(tempScop, *(I->getNodeAs<Region>()), NestLoops, Scatter, LI);
+    else {
+      BasicBlock *BB = I->getNodeAs<BasicBlock>();
+
+      if (isTrivialBB(BB, tempScop))
+        continue;
+
+      ScopStmt *Stmt =
+          new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter);
+
+      // Insert all statements into the statement map and the statement vector.
+      StmtMap[BB] = Stmt;
+      Stmts.push_back(Stmt);
+
+      // Increasing the Scattering function is OK for the moment, because
+      // we are using a depth first iterator and the program is well structured.
+      ++Scatter[loopDepth];
+    }
+
+  if (!L)
+    return;
+
+  // Exiting a loop region.
+  Scatter[loopDepth] = 0;
+  NestLoops.pop_back();
+  ++Scatter[loopDepth - 1];
+}
+
+ScopStmt *Scop::getStmtForBasicBlock(BasicBlock *BB) const {
+  const auto &StmtMapIt = StmtMap.find(BB);
+  if (StmtMapIt == StmtMap.end())
+    return nullptr;
+  return StmtMapIt->second;
+}
+
+//===----------------------------------------------------------------------===//
+ScopInfo::ScopInfo() : RegionPass(ID), scop(0) {
+  ctx = isl_ctx_alloc();
+  isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
+}
+
+ScopInfo::~ScopInfo() {
+  clear();
+  isl_ctx_free(ctx);
+}
+
+void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<LoopInfo>();
+  AU.addRequired<RegionInfoPass>();
+  AU.addRequired<ScalarEvolution>();
+  AU.addRequired<TempScopInfo>();
+  AU.addRequired<AliasAnalysis>();
+  AU.setPreservesAll();
+}
+
+bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
+  LoopInfo &LI = getAnalysis<LoopInfo>();
+  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
+  ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
+
+  TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
+
+  // This region is no Scop.
+  if (!tempScop) {
+    scop = nullptr;
+    return false;
+  }
+
+  scop = new Scop(*tempScop, LI, SE, ctx);
+
+  if (!PollyUseRuntimeAliasChecks) {
+    // Statistics.
+    ++ScopFound;
+    if (scop->getMaxLoopDepth() > 0)
+      ++RichScopFound;
+    return false;
+  }
+
+  // If a problem occurs while building the alias groups we need to delete
+  // this SCoP and pretend it wasn't valid in the first place.
+  if (scop->buildAliasGroups(AA)) {
+    // Statistics.
+    ++ScopFound;
+    if (scop->getMaxLoopDepth() > 0)
+      ++RichScopFound;
+    return false;
+  }
+
+  DEBUG(dbgs()
+        << "\n\nNOTE: Run time checks for " << scop->getNameStr()
+        << " could not be created as the number of parameters involved is too "
+           "high. The SCoP will be "
+           "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust the "
+           "maximal number of parameters but be advised that the compile time "
+           "might increase exponentially.\n\n");
+
+  delete scop;
+  scop = nullptr;
+  return false;
+}
+
+char ScopInfo::ID = 0;
+
+Pass *polly::createScopInfoPass() { return new ScopInfo(); }
+
+INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops",
+                      "Polly - Create polyhedral description of Scops", false,
+                      false);
+INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
+INITIALIZE_PASS_DEPENDENCY(LoopInfo);
+INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_DEPENDENCY(TempScopInfo);
+INITIALIZE_PASS_END(ScopInfo, "polly-scops",
+                    "Polly - Create polyhedral description of Scops", false,
+                    false)
diff --git a/final/lib/Analysis/ScopPass.cpp b/final/lib/Analysis/ScopPass.cpp
new file mode 100644
index 0000000..053f3d1
--- /dev/null
+++ b/final/lib/Analysis/ScopPass.cpp
@@ -0,0 +1,37 @@
+//===- ScopPass.cpp - The base class of Passes that operate on Polly IR ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the definitions of the ScopPass members.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/ScopPass.h"
+#include "polly/ScopInfo.h"
+
+using namespace llvm;
+using namespace polly;
+
+bool ScopPass::runOnRegion(Region *R, RGPassManager &RGM) {
+  S = nullptr;
+
+  if ((S = getAnalysis<ScopInfo>().getScop()))
+    return runOnScop(*S);
+
+  return false;
+}
+
+void ScopPass::print(raw_ostream &OS, const Module *M) const {
+  if (S)
+    printScop(OS);
+}
+
+void ScopPass::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<ScopInfo>();
+  AU.setPreservesAll();
+}
diff --git a/final/lib/Analysis/TempScopInfo.cpp b/final/lib/Analysis/TempScopInfo.cpp
new file mode 100644
index 0000000..6f7a9d9
--- /dev/null
+++ b/final/lib/Analysis/TempScopInfo.cpp
@@ -0,0 +1,394 @@
+//===---------- TempScopInfo.cpp  - Extract TempScops ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Collect information about the control flow regions detected by the Scop
+// detection, such that this information can be translated info its polyhedral
+// representation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/TempScopInfo.h"
+#include "polly/ScopDetection.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/CodeGen/BlockGenerators.h"
+#include "polly/Support/GICHelper.h"
+#include "polly/Support/SCEVValidator.h"
+#include "polly/Support/ScopHelper.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/RegionIterator.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+using namespace polly;
+
+#define DEBUG_TYPE "polly-analyze-ir"
+
+//===----------------------------------------------------------------------===//
+/// Helper Classes
+
+void IRAccess::print(raw_ostream &OS) const {
+  if (isRead())
+    OS << "Read ";
+  else {
+    if (isMayWrite())
+      OS << "May";
+    OS << "Write ";
+  }
+  OS << BaseAddress->getName() << '[' << *Offset << "]\n";
+}
+
+void Comparison::print(raw_ostream &OS) const {
+  // Not yet implemented.
+}
+
+/// Helper function to print the condition
+static void printBBCond(raw_ostream &OS, const BBCond &Cond) {
+  assert(!Cond.empty() && "Unexpected empty condition!");
+  Cond[0].print(OS);
+  for (unsigned i = 1, e = Cond.size(); i != e; ++i) {
+    OS << " && ";
+    Cond[i].print(OS);
+  }
+}
+
+inline raw_ostream &operator<<(raw_ostream &OS, const BBCond &Cond) {
+  printBBCond(OS, Cond);
+  return OS;
+}
+
+//===----------------------------------------------------------------------===//
+// TempScop implementation
+TempScop::~TempScop() {}
+
+void TempScop::print(raw_ostream &OS, ScalarEvolution *SE, LoopInfo *LI) const {
+  OS << "Scop: " << R.getNameStr() << "\n";
+
+  printDetail(OS, SE, LI, &R, 0);
+}
+
+void TempScop::printDetail(raw_ostream &OS, ScalarEvolution *SE, LoopInfo *LI,
+                           const Region *CurR, unsigned ind) const {
+  // FIXME: Print other details rather than memory accesses.
+  for (const auto &CurBlock : CurR->blocks()) {
+    AccFuncMapType::const_iterator AccSetIt = AccFuncMap.find(CurBlock);
+
+    // Ignore trivial blocks that do not contain any memory access.
+    if (AccSetIt == AccFuncMap.end())
+      continue;
+
+    OS.indent(ind) << "BB: " << CurBlock->getName() << '\n';
+    typedef AccFuncSetType::const_iterator access_iterator;
+    const AccFuncSetType &AccFuncs = AccSetIt->second;
+
+    for (access_iterator AI = AccFuncs.begin(), AE = AccFuncs.end(); AI != AE;
+         ++AI)
+      AI->first.print(OS.indent(ind + 2));
+  }
+}
+
+bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
+  // No need to translate these scalar dependences into polyhedral form, because
+  // synthesizable scalars can be generated by the code generator.
+  if (canSynthesize(Inst, LI, SE, R))
+    return false;
+
+  bool AnyCrossStmtUse = false;
+  BasicBlock *ParentBB = Inst->getParent();
+
+  for (User *U : Inst->users()) {
+    Instruction *UI = dyn_cast<Instruction>(U);
+
+    // Ignore the strange user
+    if (UI == 0)
+      continue;
+
+    BasicBlock *UseParent = UI->getParent();
+
+    // Ignore the users in the same BB (statement)
+    if (UseParent == ParentBB)
+      continue;
+
+    // No need to translate these scalar dependences into polyhedral form,
+    // because synthesizable scalars can be generated by the code generator.
+    if (canSynthesize(UI, LI, SE, R))
+      continue;
+
+    // Now U is used in another statement.
+    AnyCrossStmtUse = true;
+
+    // Do not build a read access that is not in the current SCoP
+    if (!R->contains(UseParent))
+      continue;
+
+    assert(!isa<PHINode>(UI) && "Non synthesizable PHINode found in a SCoP!");
+
+    SmallVector<const SCEV *, 4> Subscripts, Sizes;
+
+    // Use the def instruction as base address of the IRAccess, so that it will
+    // become the name of the scalar access in the polyhedral form.
+    IRAccess ScalarAccess(IRAccess::READ, Inst, ZeroOffset, 1, true, Subscripts,
+                          Sizes);
+    AccFuncMap[UseParent].push_back(std::make_pair(ScalarAccess, UI));
+  }
+
+  return AnyCrossStmtUse;
+}
+
+extern MapInsnToMemAcc InsnToMemAcc;
+
+IRAccess TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R) {
+  unsigned Size;
+  Type *SizeType;
+  enum IRAccess::TypeKind Type;
+
+  if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
+    SizeType = Load->getType();
+    Size = TD->getTypeStoreSize(SizeType);
+    Type = IRAccess::READ;
+  } else {
+    StoreInst *Store = cast<StoreInst>(Inst);
+    SizeType = Store->getValueOperand()->getType();
+    Size = TD->getTypeStoreSize(SizeType);
+    Type = IRAccess::MUST_WRITE;
+  }
+
+  const SCEV *AccessFunction = SE->getSCEVAtScope(getPointerOperand(*Inst), L);
+  const SCEVUnknown *BasePointer =
+      dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
+
+  assert(BasePointer && "Could not find base pointer");
+  AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
+  SmallVector<const SCEV *, 4> Subscripts, Sizes;
+
+  MemAcc *Acc = InsnToMemAcc[Inst];
+  if (PollyDelinearize && Acc)
+    return IRAccess(Type, BasePointer->getValue(), AccessFunction, Size, true,
+                    Acc->DelinearizedSubscripts, Acc->Shape->DelinearizedSizes);
+
+  bool IsAffine = isAffineExpr(R, AccessFunction, *SE, BasePointer->getValue());
+  Subscripts.push_back(AccessFunction);
+  if (!IsAffine && Type == IRAccess::MUST_WRITE)
+    Type = IRAccess::MAY_WRITE;
+
+  Sizes.push_back(SE->getConstant(ZeroOffset->getType(), Size));
+  return IRAccess(Type, BasePointer->getValue(), AccessFunction, Size, IsAffine,
+                  Subscripts, Sizes);
+}
+
+void TempScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB) {
+  AccFuncSetType Functions;
+  Loop *L = LI->getLoopFor(&BB);
+
+  for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) {
+    Instruction *Inst = I;
+    if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
+      Functions.push_back(std::make_pair(buildIRAccess(Inst, L, &R), Inst));
+
+    if (!isa<StoreInst>(Inst) && buildScalarDependences(Inst, &R)) {
+      // If the Instruction is used outside the statement, we need to build the
+      // write access.
+      SmallVector<const SCEV *, 4> Subscripts, Sizes;
+      IRAccess ScalarAccess(IRAccess::MUST_WRITE, Inst, ZeroOffset, 1, true,
+                            Subscripts, Sizes);
+      Functions.push_back(std::make_pair(ScalarAccess, Inst));
+    }
+  }
+
+  if (Functions.empty())
+    return;
+
+  AccFuncSetType &Accs = AccFuncMap[&BB];
+  Accs.insert(Accs.end(), Functions.begin(), Functions.end());
+}
+
+void TempScopInfo::buildAffineCondition(Value &V, bool inverted,
+                                        Comparison **Comp) const {
+  if (ConstantInt *C = dyn_cast<ConstantInt>(&V)) {
+    // If this is always true condition, we will create 0 <= 1,
+    // otherwise we will create 0 >= 1.
+    const SCEV *LHS = SE->getConstant(C->getType(), 0);
+    const SCEV *RHS = SE->getConstant(C->getType(), 1);
+
+    if (C->isOne() == inverted)
+      *Comp = new Comparison(LHS, RHS, ICmpInst::ICMP_SLE);
+    else
+      *Comp = new Comparison(LHS, RHS, ICmpInst::ICMP_SGE);
+
+    return;
+  }
+
+  ICmpInst *ICmp = dyn_cast<ICmpInst>(&V);
+  assert(ICmp && "Only ICmpInst of constant as condition supported!");
+
+  Loop *L = LI->getLoopFor(ICmp->getParent());
+  const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
+  const SCEV *RHS = SE->getSCEVAtScope(ICmp->getOperand(1), L);
+
+  ICmpInst::Predicate Pred = ICmp->getPredicate();
+
+  // Invert the predicate if needed.
+  if (inverted)
+    Pred = ICmpInst::getInversePredicate(Pred);
+
+  switch (Pred) {
+  case ICmpInst::ICMP_UGT:
+  case ICmpInst::ICMP_UGE:
+  case ICmpInst::ICMP_ULT:
+  case ICmpInst::ICMP_ULE:
+    // TODO: At the moment we need to see everything as signed. This is an
+    //       correctness issue that needs to be solved.
+    // AffLHS->setUnsigned();
+    // AffRHS->setUnsigned();
+    break;
+  default:
+    break;
+  }
+
+  *Comp = new Comparison(LHS, RHS, Pred);
+}
+
+void TempScopInfo::buildCondition(BasicBlock *BB, BasicBlock *RegionEntry) {
+  BBCond Cond;
+
+  DomTreeNode *BBNode = DT->getNode(BB), *EntryNode = DT->getNode(RegionEntry);
+  assert(BBNode && EntryNode && "Get null node while building condition!");
+
+  // Walk up the dominance tree until reaching the entry node. Add all
+  // conditions on the path to BB except if BB postdominates the block
+  // containing the condition.
+  while (BBNode != EntryNode) {
+    BasicBlock *CurBB = BBNode->getBlock();
+    BBNode = BBNode->getIDom();
+    assert(BBNode && "BBNode should not reach the root node!");
+
+    if (PDT->dominates(CurBB, BBNode->getBlock()))
+      continue;
+
+    BranchInst *Br = dyn_cast<BranchInst>(BBNode->getBlock()->getTerminator());
+    assert(Br && "A Valid Scop should only contain branch instruction");
+
+    if (Br->isUnconditional())
+      continue;
+
+    BasicBlock *TrueBB = Br->getSuccessor(0), *FalseBB = Br->getSuccessor(1);
+
+    // Is BB on the ELSE side of the branch?
+    bool inverted = DT->dominates(FalseBB, BB);
+
+    // If both TrueBB and FalseBB dominate BB, one of them must be the target of
+    // a back-edge, i.e. a loop header.
+    if (inverted && DT->dominates(TrueBB, BB)) {
+      assert(
+          (DT->dominates(TrueBB, FalseBB) || DT->dominates(FalseBB, TrueBB)) &&
+          "One of the successors should be the loop header and dominate the"
+          "other!");
+
+      // It is not an invert if the FalseBB is the header.
+      if (DT->dominates(FalseBB, TrueBB))
+        inverted = false;
+    }
+
+    Comparison *Cmp;
+    buildAffineCondition(*(Br->getCondition()), inverted, &Cmp);
+    Cond.push_back(*Cmp);
+  }
+
+  if (!Cond.empty())
+    BBConds[BB] = Cond;
+}
+
+TempScop *TempScopInfo::buildTempScop(Region &R) {
+  TempScop *TScop = new TempScop(R, BBConds, AccFuncMap);
+
+  for (const auto &BB : R.blocks()) {
+    buildAccessFunctions(R, *BB);
+    buildCondition(BB, R.getEntry());
+  }
+
+  return TScop;
+}
+
+TempScop *TempScopInfo::getTempScop(const Region *R) const {
+  TempScopMapType::const_iterator at = TempScops.find(R);
+  return at == TempScops.end() ? 0 : at->second;
+}
+
+void TempScopInfo::print(raw_ostream &OS, const Module *) const {
+  for (TempScopMapType::const_iterator I = TempScops.begin(),
+                                       E = TempScops.end();
+       I != E; ++I)
+    I->second->print(OS, SE, LI);
+}
+
+bool TempScopInfo::runOnFunction(Function &F) {
+  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+  PDT = &getAnalysis<PostDominatorTree>();
+  SE = &getAnalysis<ScalarEvolution>();
+  LI = &getAnalysis<LoopInfo>();
+  SD = &getAnalysis<ScopDetection>();
+  AA = &getAnalysis<AliasAnalysis>();
+  TD = &getAnalysis<DataLayoutPass>().getDataLayout();
+  ZeroOffset = SE->getConstant(TD->getIntPtrType(F.getContext()), 0);
+
+  for (ScopDetection::iterator I = SD->begin(), E = SD->end(); I != E; ++I) {
+    if (!SD->isMaxRegionInScop(**I))
+      continue;
+    Region *R = const_cast<Region *>(*I);
+    TempScops.insert(std::make_pair(R, buildTempScop(*R)));
+  }
+
+  return false;
+}
+
+void TempScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<DataLayoutPass>();
+  AU.addRequiredTransitive<DominatorTreeWrapperPass>();
+  AU.addRequiredTransitive<PostDominatorTree>();
+  AU.addRequiredTransitive<LoopInfo>();
+  AU.addRequiredTransitive<ScalarEvolution>();
+  AU.addRequiredTransitive<ScopDetection>();
+  AU.addRequiredID(IndependentBlocksID);
+  AU.addRequired<AliasAnalysis>();
+  AU.setPreservesAll();
+}
+
+TempScopInfo::~TempScopInfo() { clear(); }
+
+void TempScopInfo::clear() {
+  BBConds.clear();
+  AccFuncMap.clear();
+  DeleteContainerSeconds(TempScops);
+  TempScops.clear();
+}
+
+//===----------------------------------------------------------------------===//
+// TempScop information extraction pass implement
+char TempScopInfo::ID = 0;
+
+Pass *polly::createTempScopInfoPass() { return new TempScopInfo(); }
+
+INITIALIZE_PASS_BEGIN(TempScopInfo, "polly-analyze-ir",
+                      "Polly - Analyse the LLVM-IR in the detected regions",
+                      false, false);
+INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
+INITIALIZE_PASS_DEPENDENCY(LoopInfo);
+INITIALIZE_PASS_DEPENDENCY(PostDominatorTree);
+INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_DEPENDENCY(DataLayoutPass);
+INITIALIZE_PASS_END(TempScopInfo, "polly-analyze-ir",
+                    "Polly - Analyse the LLVM-IR in the detected regions",
+                    false, false)
diff --git a/final/lib/CMakeLists.txt b/final/lib/CMakeLists.txt
new file mode 100644
index 0000000..651aee6
--- /dev/null
+++ b/final/lib/CMakeLists.txt
@@ -0,0 +1,84 @@
+set(LLVM_NO_RTTI 1)
+
+if (PLUTO_FOUND)
+  set(POLLY_PLUTO_FILES Transform/Pluto.cpp)
+endif (PLUTO_FOUND)
+
+set(POLLY_JSON_FILES
+    JSON/json_reader.cpp
+    JSON/json_value.cpp
+    JSON/json_writer.cpp
+)
+
+set(ISL_CODEGEN_FILES
+    CodeGen/IslAst.cpp
+    CodeGen/IslExprBuilder.cpp
+    CodeGen/IslCodeGeneration.cpp)
+
+if (GPU_CODEGEN)
+  set (GPGPU_CODEGEN_FILES
+       CodeGen/PTXGenerator.cpp)
+endif (GPU_CODEGEN)
+
+add_polly_library(Polly
+  Analysis/Dependences.cpp
+  Analysis/ScopDetection.cpp
+  Analysis/ScopDetectionDiagnostic.cpp
+  Analysis/ScopInfo.cpp
+  Analysis/ScopGraphPrinter.cpp
+  Analysis/ScopPass.cpp
+  Analysis/TempScopInfo.cpp
+  CodeGen/BlockGenerators.cpp
+  ${ISL_CODEGEN_FILES}
+  CodeGen/LoopGenerators.cpp
+  CodeGen/IRBuilder.cpp
+  CodeGen/Utils.cpp
+  CodeGen/RuntimeDebugBuilder.cpp
+  ${GPGPU_CODEGEN_FILES}
+  Exchange/JSONExporter.cpp
+  Support/GICHelper.cpp
+  Support/SCEVValidator.cpp
+  Support/RegisterPasses.cpp
+  Support/ScopHelper.cpp
+  ${POLLY_JSON_FILES}
+  Transform/Canonicalization.cpp
+  Transform/CodePreparation.cpp
+  Transform/DeadCodeElimination.cpp
+  Transform/IndependentBlocks.cpp
+  Transform/ScheduleOptimizer.cpp
+  ${POLLY_PLUTO_FILES}
+  )
+
+if (BUILD_SHARED_LIBS)
+  target_link_libraries(Polly
+    LLVMSupport
+    LLVMCore
+    LLVMScalarOpts
+    LLVMInstCombine
+    LLVMTransformUtils
+    LLVMAnalysis
+    LLVMipo
+    LLVMProfileData
+  )
+  link_directories(
+      ${LLVM_LIBRARY_DIR}
+  )
+endif()
+
+# Build a monolithic Polly.a and a thin module LLVMPolly.moduleext that links to
+# that static library.
+add_polly_loadable_module(LLVMPolly
+  Polly.cpp
+)
+
+if (TARGET intrinsics_gen)
+  # Check if we are building as part of an LLVM build
+  add_dependencies(Polly intrinsics_gen)
+endif()
+
+target_link_libraries(LLVMPolly Polly)
+
+set_target_properties(LLVMPolly
+  PROPERTIES
+  LINKER_LANGUAGE CXX
+  PREFIX "")
diff --git a/final/lib/CodeGen/BlockGenerators.cpp b/final/lib/CodeGen/BlockGenerators.cpp
new file mode 100644
index 0000000..4c0762c
--- /dev/null
+++ b/final/lib/CodeGen/BlockGenerators.cpp
@@ -0,0 +1,600 @@
+//===--- BlockGenerators.cpp - Generate code for statements -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the BlockGenerator and VectorBlockGenerator classes,
+// which generate sequential code and vectorized code for a polyhedral
+// statement, respectively.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/ScopInfo.h"
+#include "isl/aff.h"
+#include "isl/ast.h"
+#include "isl/ast_build.h"
+#include "isl/set.h"
+#include "polly/CodeGen/BlockGenerators.h"
+#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/CodeGen/IslExprBuilder.h"
+#include "polly/Options.h"
+#include "polly/Support/GICHelper.h"
+#include "polly/Support/SCEVValidator.h"
+#include "polly/Support/ScopHelper.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+using namespace llvm;
+using namespace polly;
+
+static cl::opt<bool> Aligned("enable-polly-aligned",
+                             cl::desc("Assumed aligned memory accesses."),
+                             cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                             cl::cat(PollyCategory));
+
+bool polly::canSynthesize(const Instruction *I, const llvm::LoopInfo *LI,
+                          ScalarEvolution *SE, const Region *R) {
+  if (!I || !SE->isSCEVable(I->getType()))
+    return false;
+
+  if (const SCEV *Scev = SE->getSCEV(const_cast<Instruction *>(I)))
+    if (!isa<SCEVCouldNotCompute>(Scev))
+      if (!hasScalarDepsInsideRegion(Scev, R))
+        return true;
+
+  return false;
+}
+
+BlockGenerator::BlockGenerator(PollyIRBuilder &B, ScopStmt &Stmt, Pass *P,
+                               LoopInfo &LI, ScalarEvolution &SE,
+                               isl_ast_build *Build,
+                               IslExprBuilder *ExprBuilder)
+    : Builder(B), Statement(Stmt), P(P), LI(LI), SE(SE), Build(Build),
+      ExprBuilder(ExprBuilder) {}
+
+Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
+                                   ValueMapT &GlobalMap, LoopToScevMapT &LTS,
+                                   Loop *L) const {
+  // We assume constants never change.
+  // This avoids map lookups for many calls to this function.
+  if (isa<Constant>(Old))
+    return const_cast<Value *>(Old);
+
+  if (Value *New = GlobalMap.lookup(Old)) {
+    if (Old->getType()->getScalarSizeInBits() <
+        New->getType()->getScalarSizeInBits())
+      New = Builder.CreateTruncOrBitCast(New, Old->getType());
+
+    return New;
+  }
+
+  if (Value *New = BBMap.lookup(Old))
+    return New;
+
+  if (SE.isSCEVable(Old->getType()))
+    if (const SCEV *Scev = SE.getSCEVAtScope(const_cast<Value *>(Old), L)) {
+      if (!isa<SCEVCouldNotCompute>(Scev)) {
+        const SCEV *NewScev = apply(Scev, LTS, SE);
+        ValueToValueMap VTV;
+        VTV.insert(BBMap.begin(), BBMap.end());
+        VTV.insert(GlobalMap.begin(), GlobalMap.end());
+        NewScev = SCEVParameterRewriter::rewrite(NewScev, SE, VTV);
+        SCEVExpander Expander(SE, "polly");
+        Value *Expanded = Expander.expandCodeFor(NewScev, Old->getType(),
+                                                 Builder.GetInsertPoint());
+
+        BBMap[Old] = Expanded;
+        return Expanded;
+      }
+    }
+
+  // A scop-constant value defined by a global or a function parameter.
+  if (isa<GlobalValue>(Old) || isa<Argument>(Old))
+    return const_cast<Value *>(Old);
+
+  // A scop-constant value defined by an instruction executed outside the scop.
+  if (const Instruction *Inst = dyn_cast<Instruction>(Old))
+    if (!Statement.getParent()->getRegion().contains(Inst->getParent()))
+      return const_cast<Value *>(Old);
+
+  // The scalar dependence is neither available nor SCEVCodegenable.
+  llvm_unreachable("Unexpected scalar dependence in region!");
+  return nullptr;
+}
+
+void BlockGenerator::copyInstScalar(const Instruction *Inst, ValueMapT &BBMap,
+                                    ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
+  // We do not generate debug intrinsics as we did not investigate how to
+  // copy them correctly. At the current state, they just crash the code
+  // generation as the meta-data operands are not correctly copied.
+  if (isa<DbgInfoIntrinsic>(Inst))
+    return;
+
+  Instruction *NewInst = Inst->clone();
+
+  // Replace old operands with the new ones.
+  for (Value *OldOperand : Inst->operands()) {
+    Value *NewOperand =
+        getNewValue(OldOperand, BBMap, GlobalMap, LTS, getLoopForInst(Inst));
+
+    if (!NewOperand) {
+      assert(!isa<StoreInst>(NewInst) &&
+             "Store instructions are always needed!");
+      delete NewInst;
+      return;
+    }
+
+    NewInst->replaceUsesOfWith(OldOperand, NewOperand);
+  }
+
+  Builder.Insert(NewInst);
+  BBMap[Inst] = NewInst;
+
+  if (!NewInst->getType()->isVoidTy())
+    NewInst->setName("p_" + Inst->getName());
+}
+
+Value *BlockGenerator::getNewAccessOperand(const MemoryAccess &MA) {
+  isl_pw_multi_aff *PWAccRel;
+  isl_union_map *Schedule;
+  isl_ast_expr *Expr;
+
+  assert(ExprBuilder && Build &&
+         "Cannot generate new value without IslExprBuilder!");
+
+  Schedule = isl_ast_build_get_schedule(Build);
+  PWAccRel = MA.applyScheduleToAccessRelation(Schedule);
+
+  Expr = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel);
+  Expr = isl_ast_expr_address_of(Expr);
+
+  return ExprBuilder->create(Expr);
+}
+
+Value *BlockGenerator::generateLocationAccessed(const Instruction *Inst,
+                                                const Value *Pointer,
+                                                ValueMapT &BBMap,
+                                                ValueMapT &GlobalMap,
+                                                LoopToScevMapT &LTS) {
+  const MemoryAccess &MA = Statement.getAccessFor(Inst);
+
+  Value *NewPointer;
+  if (MA.hasNewAccessRelation())
+    NewPointer = getNewAccessOperand(MA);
+  else
+    NewPointer =
+        getNewValue(Pointer, BBMap, GlobalMap, LTS, getLoopForInst(Inst));
+
+  return NewPointer;
+}
+
+Loop *BlockGenerator::getLoopForInst(const llvm::Instruction *Inst) {
+  return LI.getLoopFor(Inst->getParent());
+}
+
+Value *BlockGenerator::generateScalarLoad(const LoadInst *Load,
+                                          ValueMapT &BBMap,
+                                          ValueMapT &GlobalMap,
+                                          LoopToScevMapT &LTS) {
+  const Value *Pointer = Load->getPointerOperand();
+  Value *NewPointer =
+      generateLocationAccessed(Load, Pointer, BBMap, GlobalMap, LTS);
+  Value *ScalarLoad = Builder.CreateAlignedLoad(
+      NewPointer, Load->getAlignment(), Load->getName() + "_p_scalar_");
+  return ScalarLoad;
+}
+
+Value *BlockGenerator::generateScalarStore(const StoreInst *Store,
+                                           ValueMapT &BBMap,
+                                           ValueMapT &GlobalMap,
+                                           LoopToScevMapT &LTS) {
+  const Value *Pointer = Store->getPointerOperand();
+  Value *NewPointer =
+      generateLocationAccessed(Store, Pointer, BBMap, GlobalMap, LTS);
+  Value *ValueOperand = getNewValue(Store->getValueOperand(), BBMap, GlobalMap,
+                                    LTS, getLoopForInst(Store));
+
+  Value *NewStore = Builder.CreateAlignedStore(ValueOperand, NewPointer,
+                                               Store->getAlignment());
+  return NewStore;
+}
+
+void BlockGenerator::copyInstruction(const Instruction *Inst, ValueMapT &BBMap,
+                                     ValueMapT &GlobalMap,
+                                     LoopToScevMapT &LTS) {
+  // Terminator instructions control the control flow. They are explicitly
+  // expressed in the clast and do not need to be copied.
+  if (Inst->isTerminator())
+    return;
+
+  if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE,
+                    &Statement.getParent()->getRegion()))
+    return;
+
+  if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
+    Value *NewLoad = generateScalarLoad(Load, BBMap, GlobalMap, LTS);
+    // Compute NewLoad before its insertion in BBMap to make the insertion
+    // deterministic.
+    BBMap[Load] = NewLoad;
+    return;
+  }
+
+  if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
+    Value *NewStore = generateScalarStore(Store, BBMap, GlobalMap, LTS);
+    // Compute NewStore before its insertion in BBMap to make the insertion
+    // deterministic.
+    BBMap[Store] = NewStore;
+    return;
+  }
+
+  copyInstScalar(Inst, BBMap, GlobalMap, LTS);
+}
+
+void BlockGenerator::copyBB(ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
+  BasicBlock *BB = Statement.getBasicBlock();
+  BasicBlock *CopyBB =
+      SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P);
+  CopyBB->setName("polly.stmt." + BB->getName());
+  Builder.SetInsertPoint(CopyBB->begin());
+
+  ValueMapT BBMap;
+
+  for (Instruction &Inst : *BB)
+    copyInstruction(&Inst, BBMap, GlobalMap, LTS);
+}
+
+VectorBlockGenerator::VectorBlockGenerator(
+    PollyIRBuilder &B, VectorValueMapT &GlobalMaps,
+    std::vector<LoopToScevMapT> &VLTS, ScopStmt &Stmt,
+    __isl_keep isl_map *Schedule, Pass *P, LoopInfo &LI, ScalarEvolution &SE,
+    __isl_keep isl_ast_build *Build, IslExprBuilder *ExprBuilder)
+    : BlockGenerator(B, Stmt, P, LI, SE, Build, ExprBuilder),
+      GlobalMaps(GlobalMaps), VLTS(VLTS), Schedule(Schedule) {
+  assert(GlobalMaps.size() > 1 && "Only one vector lane found");
+  assert(Schedule && "No statement domain provided");
+}
+
+Value *VectorBlockGenerator::getVectorValue(const Value *Old,
+                                            ValueMapT &VectorMap,
+                                            VectorValueMapT &ScalarMaps,
+                                            Loop *L) {
+  if (Value *NewValue = VectorMap.lookup(Old))
+    return NewValue;
+
+  int Width = getVectorWidth();
+
+  Value *Vector = UndefValue::get(VectorType::get(Old->getType(), Width));
+
+  for (int Lane = 0; Lane < Width; Lane++)
+    Vector = Builder.CreateInsertElement(
+        Vector,
+        getNewValue(Old, ScalarMaps[Lane], GlobalMaps[Lane], VLTS[Lane], L),
+        Builder.getInt32(Lane));
+
+  VectorMap[Old] = Vector;
+
+  return Vector;
+}
+
+Type *VectorBlockGenerator::getVectorPtrTy(const Value *Val, int Width) {
+  PointerType *PointerTy = dyn_cast<PointerType>(Val->getType());
+  assert(PointerTy && "PointerType expected");
+
+  Type *ScalarType = PointerTy->getElementType();
+  VectorType *VectorType = VectorType::get(ScalarType, Width);
+
+  return PointerType::getUnqual(VectorType);
+}
+
+Value *
+VectorBlockGenerator::generateStrideOneLoad(const LoadInst *Load,
+                                            VectorValueMapT &ScalarMaps,
+                                            bool NegativeStride = false) {
+  unsigned VectorWidth = getVectorWidth();
+  const Value *Pointer = Load->getPointerOperand();
+  Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth);
+  unsigned Offset = NegativeStride ? VectorWidth - 1 : 0;
+
+  Value *NewPointer = nullptr;
+  NewPointer = generateLocationAccessed(Load, Pointer, ScalarMaps[Offset],
+                                        GlobalMaps[Offset], VLTS[Offset]);
+  Value *VectorPtr =
+      Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr");
+  LoadInst *VecLoad =
+      Builder.CreateLoad(VectorPtr, Load->getName() + "_p_vec_full");
+  if (!Aligned)
+    VecLoad->setAlignment(8);
+
+  if (NegativeStride) {
+    SmallVector<Constant *, 16> Indices;
+    for (int i = VectorWidth - 1; i >= 0; i--)
+      Indices.push_back(ConstantInt::get(Builder.getInt32Ty(), i));
+    Constant *SV = llvm::ConstantVector::get(Indices);
+    Value *RevVecLoad = Builder.CreateShuffleVector(
+        VecLoad, VecLoad, SV, Load->getName() + "_reverse");
+    return RevVecLoad;
+  }
+
+  return VecLoad;
+}
+
+Value *VectorBlockGenerator::generateStrideZeroLoad(const LoadInst *Load,
+                                                    ValueMapT &BBMap) {
+  const Value *Pointer = Load->getPointerOperand();
+  Type *VectorPtrType = getVectorPtrTy(Pointer, 1);
+  Value *NewPointer =
+      generateLocationAccessed(Load, Pointer, BBMap, GlobalMaps[0], VLTS[0]);
+  Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType,
+                                           Load->getName() + "_p_vec_p");
+  LoadInst *ScalarLoad =
+      Builder.CreateLoad(VectorPtr, Load->getName() + "_p_splat_one");
+
+  if (!Aligned)
+    ScalarLoad->setAlignment(8);
+
+  Constant *SplatVector = Constant::getNullValue(
+      VectorType::get(Builder.getInt32Ty(), getVectorWidth()));
+
+  Value *VectorLoad = Builder.CreateShuffleVector(
+      ScalarLoad, ScalarLoad, SplatVector, Load->getName() + "_p_splat");
+  return VectorLoad;
+}
+
+Value *
+VectorBlockGenerator::generateUnknownStrideLoad(const LoadInst *Load,
+                                                VectorValueMapT &ScalarMaps) {
+  int VectorWidth = getVectorWidth();
+  const Value *Pointer = Load->getPointerOperand();
+  VectorType *VectorType = VectorType::get(
+      dyn_cast<PointerType>(Pointer->getType())->getElementType(), VectorWidth);
+
+  Value *Vector = UndefValue::get(VectorType);
+
+  for (int i = 0; i < VectorWidth; i++) {
+    Value *NewPointer = generateLocationAccessed(Load, Pointer, ScalarMaps[i],
+                                                 GlobalMaps[i], VLTS[i]);
+    Value *ScalarLoad =
+        Builder.CreateLoad(NewPointer, Load->getName() + "_p_scalar_");
+    Vector = Builder.CreateInsertElement(
+        Vector, ScalarLoad, Builder.getInt32(i), Load->getName() + "_p_vec_");
+  }
+
+  return Vector;
+}
+
+void VectorBlockGenerator::generateLoad(const LoadInst *Load,
+                                        ValueMapT &VectorMap,
+                                        VectorValueMapT &ScalarMaps) {
+  if (PollyVectorizerChoice >= VECTORIZER_FIRST_NEED_GROUPED_UNROLL ||
+      !VectorType::isValidElementType(Load->getType())) {
+    for (int i = 0; i < getVectorWidth(); i++)
+      ScalarMaps[i][Load] =
+          generateScalarLoad(Load, ScalarMaps[i], GlobalMaps[i], VLTS[i]);
+    return;
+  }
+
+  const MemoryAccess &Access = Statement.getAccessFor(Load);
+
+  // Make sure we have scalar values available to access the pointer to
+  // the data location.
+  extractScalarValues(Load, VectorMap, ScalarMaps);
+
+  Value *NewLoad;
+  if (Access.isStrideZero(isl_map_copy(Schedule)))
+    NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0]);
+  else if (Access.isStrideOne(isl_map_copy(Schedule)))
+    NewLoad = generateStrideOneLoad(Load, ScalarMaps);
+  else if (Access.isStrideX(isl_map_copy(Schedule), -1))
+    NewLoad = generateStrideOneLoad(Load, ScalarMaps, true);
+  else
+    NewLoad = generateUnknownStrideLoad(Load, ScalarMaps);
+
+  VectorMap[Load] = NewLoad;
+}
+
+void VectorBlockGenerator::copyUnaryInst(const UnaryInstruction *Inst,
+                                         ValueMapT &VectorMap,
+                                         VectorValueMapT &ScalarMaps) {
+  int VectorWidth = getVectorWidth();
+  Value *NewOperand = getVectorValue(Inst->getOperand(0), VectorMap, ScalarMaps,
+                                     getLoopForInst(Inst));
+
+  assert(isa<CastInst>(Inst) && "Can not generate vector code for instruction");
+
+  const CastInst *Cast = dyn_cast<CastInst>(Inst);
+  VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth);
+  VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand, DestType);
+}
+
+void VectorBlockGenerator::copyBinaryInst(const BinaryOperator *Inst,
+                                          ValueMapT &VectorMap,
+                                          VectorValueMapT &ScalarMaps) {
+  Loop *L = getLoopForInst(Inst);
+  Value *OpZero = Inst->getOperand(0);
+  Value *OpOne = Inst->getOperand(1);
+
+  Value *NewOpZero, *NewOpOne;
+  NewOpZero = getVectorValue(OpZero, VectorMap, ScalarMaps, L);
+  NewOpOne = getVectorValue(OpOne, VectorMap, ScalarMaps, L);
+
+  Value *NewInst = Builder.CreateBinOp(Inst->getOpcode(), NewOpZero, NewOpOne,
+                                       Inst->getName() + "p_vec");
+  VectorMap[Inst] = NewInst;
+}
+
+void VectorBlockGenerator::copyStore(const StoreInst *Store,
+                                     ValueMapT &VectorMap,
+                                     VectorValueMapT &ScalarMaps) {
+  const MemoryAccess &Access = Statement.getAccessFor(Store);
+
+  const Value *Pointer = Store->getPointerOperand();
+  Value *Vector = getVectorValue(Store->getValueOperand(), VectorMap,
+                                 ScalarMaps, getLoopForInst(Store));
+
+  // Make sure we have scalar values available to access the pointer to
+  // the data location.
+  extractScalarValues(Store, VectorMap, ScalarMaps);
+
+  if (Access.isStrideOne(isl_map_copy(Schedule))) {
+    Type *VectorPtrType = getVectorPtrTy(Pointer, getVectorWidth());
+    Value *NewPointer = generateLocationAccessed(Store, Pointer, ScalarMaps[0],
+                                                 GlobalMaps[0], VLTS[0]);
+
+    Value *VectorPtr =
+        Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr");
+    StoreInst *Store = Builder.CreateStore(Vector, VectorPtr);
+
+    if (!Aligned)
+      Store->setAlignment(8);
+  } else {
+    for (unsigned i = 0; i < ScalarMaps.size(); i++) {
+      Value *Scalar = Builder.CreateExtractElement(Vector, Builder.getInt32(i));
+      Value *NewPointer = generateLocationAccessed(
+          Store, Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]);
+      Builder.CreateStore(Scalar, NewPointer);
+    }
+  }
+}
+
+bool VectorBlockGenerator::hasVectorOperands(const Instruction *Inst,
+                                             ValueMapT &VectorMap) {
+  for (Value *Operand : Inst->operands())
+    if (VectorMap.count(Operand))
+      return true;
+  return false;
+}
+
+bool VectorBlockGenerator::extractScalarValues(const Instruction *Inst,
+                                               ValueMapT &VectorMap,
+                                               VectorValueMapT &ScalarMaps) {
+  bool HasVectorOperand = false;
+  int VectorWidth = getVectorWidth();
+
+  for (Value *Operand : Inst->operands()) {
+    ValueMapT::iterator VecOp = VectorMap.find(Operand);
+
+    if (VecOp == VectorMap.end())
+      continue;
+
+    HasVectorOperand = true;
+    Value *NewVector = VecOp->second;
+
+    for (int i = 0; i < VectorWidth; ++i) {
+      ValueMapT &SM = ScalarMaps[i];
+
+      // If there is one scalar extracted, all scalar elements should have
+      // already been extracted by the code here. So no need to check for the
+      // existance of all of them.
+      if (SM.count(Operand))
+        break;
+
+      SM[Operand] =
+          Builder.CreateExtractElement(NewVector, Builder.getInt32(i));
+    }
+  }
+
+  return HasVectorOperand;
+}
+
+void VectorBlockGenerator::copyInstScalarized(const Instruction *Inst,
+                                              ValueMapT &VectorMap,
+                                              VectorValueMapT &ScalarMaps) {
+  bool HasVectorOperand;
+  int VectorWidth = getVectorWidth();
+
+  HasVectorOperand = extractScalarValues(Inst, VectorMap, ScalarMaps);
+
+  for (int VectorLane = 0; VectorLane < getVectorWidth(); VectorLane++)
+    BlockGenerator::copyInstruction(Inst, ScalarMaps[VectorLane],
+                                    GlobalMaps[VectorLane], VLTS[VectorLane]);
+
+  if (!VectorType::isValidElementType(Inst->getType()) || !HasVectorOperand)
+    return;
+
+  // Make the result available as vector value.
+  VectorType *VectorType = VectorType::get(Inst->getType(), VectorWidth);
+  Value *Vector = UndefValue::get(VectorType);
+
+  for (int i = 0; i < VectorWidth; i++)
+    Vector = Builder.CreateInsertElement(Vector, ScalarMaps[i][Inst],
+                                         Builder.getInt32(i));
+
+  VectorMap[Inst] = Vector;
+}
+
+int VectorBlockGenerator::getVectorWidth() { return GlobalMaps.size(); }
+
+void VectorBlockGenerator::copyInstruction(const Instruction *Inst,
+                                           ValueMapT &VectorMap,
+                                           VectorValueMapT &ScalarMaps) {
+  // Terminator instructions control the control flow. They are explicitly
+  // expressed in the clast and do not need to be copied.
+  if (Inst->isTerminator())
+    return;
+
+  if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE,
+                    &Statement.getParent()->getRegion()))
+    return;
+
+  if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
+    generateLoad(Load, VectorMap, ScalarMaps);
+    return;
+  }
+
+  if (hasVectorOperands(Inst, VectorMap)) {
+    if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
+      copyStore(Store, VectorMap, ScalarMaps);
+      return;
+    }
+
+    if (const UnaryInstruction *Unary = dyn_cast<UnaryInstruction>(Inst)) {
+      copyUnaryInst(Unary, VectorMap, ScalarMaps);
+      return;
+    }
+
+    if (const BinaryOperator *Binary = dyn_cast<BinaryOperator>(Inst)) {
+      copyBinaryInst(Binary, VectorMap, ScalarMaps);
+      return;
+    }
+
+    // Falltrough: We generate scalar instructions, if we don't know how to
+    // generate vector code.
+  }
+
+  copyInstScalarized(Inst, VectorMap, ScalarMaps);
+}
+
+void VectorBlockGenerator::copyBB() {
+  BasicBlock *BB = Statement.getBasicBlock();
+  BasicBlock *CopyBB =
+      SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P);
+  CopyBB->setName("polly.stmt." + BB->getName());
+  Builder.SetInsertPoint(CopyBB->begin());
+
+  // Create two maps that store the mapping from the original instructions of
+  // the old basic block to their copies in the new basic block. Those maps
+  // are basic block local.
+  //
+  // As vector code generation is supported there is one map for scalar values
+  // and one for vector values.
+  //
+  // In case we just do scalar code generation, the vectorMap is not used and
+  // the scalarMap has just one dimension, which contains the mapping.
+  //
+  // In case vector code generation is done, an instruction may either appear
+  // in the vector map once (as it is calculating >vectorwidth< values at a
+  // time. Or (if the values are calculated using scalar operations), it
+  // appears once in every dimension of the scalarMap.
+  VectorValueMapT ScalarBlockMap(getVectorWidth());
+  ValueMapT VectorBlockMap;
+
+  for (Instruction &Inst : *BB)
+    copyInstruction(&Inst, VectorBlockMap, ScalarBlockMap);
+}
diff --git a/final/lib/CodeGen/IRBuilder.cpp b/final/lib/CodeGen/IRBuilder.cpp
new file mode 100644
index 0000000..cbd1626
--- /dev/null
+++ b/final/lib/CodeGen/IRBuilder.cpp
@@ -0,0 +1,150 @@
+//===------ PollyIRBuilder.cpp --------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
+// that are used e.g. to emit the llvm.loop.parallel metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/IRBuilder.h"
+
+#include "polly/ScopInfo.h"
+#include "polly/Support/ScopHelper.h"
+
+#include "llvm/IR/Metadata.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+using namespace polly;
+
+/// @brief Get a self referencing id metadata node.
+///
+/// The MDNode looks like this (if arg0/arg1 are not null):
+///
+///    '!n = metadata !{metadata !n, arg0, arg1}'
+///
+/// @return The self referencing id metadata node.
+static MDNode *getID(LLVMContext &Ctx, Metadata *arg0 = nullptr,
+                     Metadata *arg1 = nullptr) {
+  MDNode *ID;
+  SmallVector<Metadata *, 3> Args;
+  // Use a temporary node to safely create a unique pointer for the first arg.
+  MDNode *TempNode = MDNode::getTemporary(Ctx, None);
+  // Reserve operand 0 for loop id self reference.
+  Args.push_back(TempNode);
+
+  if (arg0)
+    Args.push_back(arg0);
+  if (arg1)
+    Args.push_back(arg1);
+
+  ID = MDNode::get(Ctx, Args);
+  ID->replaceOperandWith(0, ID);
+  MDNode::deleteTemporary(TempNode);
+  return ID;
+}
+
+ScopAnnotator::ScopAnnotator() : SE(nullptr), AliasScopeDomain(nullptr) {}
+
+void ScopAnnotator::buildAliasScopes(Scop &S) {
+  SE = S.getSE();
+
+  LLVMContext &Ctx = SE->getContext();
+  AliasScopeDomain = getID(Ctx, MDString::get(Ctx, "polly.alias.scope.domain"));
+
+  AliasScopeMap.clear();
+  OtherAliasScopeListMap.clear();
+
+  SetVector<Value *> BasePtrs;
+  for (ScopStmt *Stmt : S)
+    for (MemoryAccess *MA : *Stmt)
+      BasePtrs.insert(MA->getBaseAddr());
+
+  std::string AliasScopeStr = "polly.alias.scope.";
+  for (Value *BasePtr : BasePtrs)
+    AliasScopeMap[BasePtr] = getID(
+        Ctx, AliasScopeDomain,
+        MDString::get(Ctx, (AliasScopeStr + BasePtr->getName()).str().c_str()));
+
+  for (Value *BasePtr : BasePtrs) {
+    MDNode *AliasScopeList = MDNode::get(Ctx, {});
+    for (const auto &AliasScopePair : AliasScopeMap) {
+      if (BasePtr == AliasScopePair.first)
+        continue;
+
+      Metadata *Args = {AliasScopePair.second};
+      AliasScopeList =
+          MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args));
+    }
+
+    OtherAliasScopeListMap[BasePtr] = AliasScopeList;
+  }
+}
+
+void ScopAnnotator::pushLoop(Loop *L, bool IsParallel) {
+
+  ActiveLoops.push_back(L);
+  if (!IsParallel)
+    return;
+
+  BasicBlock *Header = L->getHeader();
+  MDNode *Id = getID(Header->getContext());
+  assert(Id->getOperand(0) == Id && "Expected Id to be a self-reference");
+  assert(Id->getNumOperands() == 1 && "Unexpected extra operands in Id");
+  MDNode *Ids = ParallelLoops.empty()
+                    ? Id
+                    : MDNode::concatenate(ParallelLoops.back(), Id);
+  ParallelLoops.push_back(Ids);
+}
+
+void ScopAnnotator::popLoop(bool IsParallel) {
+  ActiveLoops.pop_back();
+  if (!IsParallel)
+    return;
+
+  assert(!ParallelLoops.empty() && "Expected a parallel loop to pop");
+  ParallelLoops.pop_back();
+}
+
+void ScopAnnotator::annotateLoopLatch(BranchInst *B, Loop *L,
+                                      bool IsParallel) const {
+  if (!IsParallel)
+    return;
+
+  assert(!ParallelLoops.empty() && "Expected a parallel loop to annotate");
+  MDNode *Ids = ParallelLoops.back();
+  MDNode *Id = cast<MDNode>(Ids->getOperand(Ids->getNumOperands() - 1));
+  B->setMetadata("llvm.loop", Id);
+}
+
+void ScopAnnotator::annotate(Instruction *Inst) {
+  if (!Inst->mayReadOrWriteMemory())
+    return;
+
+  // TODO: Use the ScopArrayInfo once available here.
+  if (AliasScopeDomain) {
+    Value *BasePtr = nullptr;
+    if (isa<StoreInst>(Inst) || isa<LoadInst>(Inst)) {
+      const SCEV *PtrSCEV = SE->getSCEV(getPointerOperand(*Inst));
+      const SCEV *BaseSCEV = SE->getPointerBase(PtrSCEV);
+      if (const SCEVUnknown *SU = dyn_cast<SCEVUnknown>(BaseSCEV))
+        BasePtr = SU->getValue();
+    }
+
+    if (BasePtr) {
+      Inst->setMetadata("alias.scope", AliasScopeMap[BasePtr]);
+      Inst->setMetadata("noalias", OtherAliasScopeListMap[BasePtr]);
+    }
+  }
+
+  if (ParallelLoops.empty())
+    return;
+
+  Inst->setMetadata("llvm.mem.parallel_loop_access", ParallelLoops.back());
+}
diff --git a/final/lib/CodeGen/IslAst.cpp b/final/lib/CodeGen/IslAst.cpp
new file mode 100644
index 0000000..d7973e4
--- /dev/null
+++ b/final/lib/CodeGen/IslAst.cpp
@@ -0,0 +1,562 @@
+//===- IslAst.cpp - isl code generator interface --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The isl code generator interface takes a Scop and generates a isl_ast. This
+// ist_ast can either be returned directly or it can be pretty printed to
+// stdout.
+//
+// A typical isl_ast output looks like this:
+//
+// for (c2 = max(0, ceild(n + m, 2); c2 <= min(511, floord(5 * n, 3)); c2++) {
+//   bb2(c2);
+// }
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/CodeGen/IslAst.h"
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+#include "llvm/Support/Debug.h"
+
+#include "isl/union_map.h"
+#include "isl/list.h"
+#include "isl/ast_build.h"
+#include "isl/set.h"
+#include "isl/map.h"
+#include "isl/aff.h"
+
+#define DEBUG_TYPE "polly-ast"
+
+using namespace llvm;
+using namespace polly;
+
+using IslAstUserPayload = IslAstInfo::IslAstUserPayload;
+
+static cl::opt<bool>
+    PollyParallel("polly-parallel",
+                  cl::desc("Generate thread parallel code (isl codegen only)"),
+                  cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> PollyParallelForce(
+    "polly-parallel-force",
+    cl::desc(
+        "Force generation of thread parallel code ignoring any cost model"),
+    cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> UseContext("polly-ast-use-context",
+                                cl::desc("Use context"), cl::Hidden,
+                                cl::init(false), cl::ZeroOrMore,
+                                cl::cat(PollyCategory));
+
+static cl::opt<bool> DetectParallel("polly-ast-detect-parallel",
+                                    cl::desc("Detect parallelism"), cl::Hidden,
+                                    cl::init(false), cl::ZeroOrMore,
+                                    cl::cat(PollyCategory));
+
+namespace polly {
+class IslAst {
+public:
+  IslAst(Scop *Scop, Dependences &D);
+
+  ~IslAst();
+
+  /// Print a source code representation of the program.
+  void pprint(llvm::raw_ostream &OS);
+
+  __isl_give isl_ast_node *getAst();
+
+  /// @brief Get the run-time conditions for the Scop.
+  __isl_give isl_ast_expr *getRunCondition();
+
+private:
+  Scop *S;
+  isl_ast_node *Root;
+  isl_ast_expr *RunCondition;
+
+  void buildRunCondition(__isl_keep isl_ast_build *Build);
+};
+} // End namespace polly.
+
+/// @brief Free an IslAstUserPayload object pointed to by @p Ptr
+static void freeIslAstUserPayload(void *Ptr) {
+  delete ((IslAstInfo::IslAstUserPayload *)Ptr);
+}
+
+IslAstInfo::IslAstUserPayload::~IslAstUserPayload() {
+  isl_ast_build_free(Build);
+  isl_pw_aff_free(MinimalDependenceDistance);
+}
+
+/// @brief Temporary information used when building the ast.
+struct AstBuildUserInfo {
+  /// @brief Construct and initialize the helper struct for AST creation.
+  AstBuildUserInfo()
+      : Deps(nullptr), InParallelFor(false), LastForNodeId(nullptr) {}
+
+  /// @brief The dependence information used for the parallelism check.
+  Dependences *Deps;
+
+  /// @brief Flag to indicate that we are inside a parallel for node.
+  bool InParallelFor;
+
+  /// @brief The last iterator id created for the current SCoP.
+  isl_id *LastForNodeId;
+};
+
+/// @brief Print a string @p str in a single line using @p Printer.
+static isl_printer *printLine(__isl_take isl_printer *Printer,
+                              const std::string &str,
+                              __isl_keep isl_pw_aff *PWA = nullptr) {
+  Printer = isl_printer_start_line(Printer);
+  Printer = isl_printer_print_str(Printer, str.c_str());
+  if (PWA)
+    Printer = isl_printer_print_pw_aff(Printer, PWA);
+  return isl_printer_end_line(Printer);
+}
+
+/// @brief Return all broken reductions as a string of clauses (OpenMP style).
+static const std::string getBrokenReductionsStr(__isl_keep isl_ast_node *Node) {
+  IslAstInfo::MemoryAccessSet *BrokenReductions;
+  std::string str;
+
+  BrokenReductions = IslAstInfo::getBrokenReductions(Node);
+  if (!BrokenReductions || BrokenReductions->empty())
+    return "";
+
+  // Map each type of reduction to a comma separated list of the base addresses.
+  std::map<MemoryAccess::ReductionType, std::string> Clauses;
+  for (MemoryAccess *MA : *BrokenReductions)
+    if (MA->isWrite())
+      Clauses[MA->getReductionType()] +=
+          ", " + MA->getBaseAddr()->getName().str();
+
+  // Now print the reductions sorted by type. Each type will cause a clause
+  // like:  reduction (+ : sum0, sum1, sum2)
+  for (const auto &ReductionClause : Clauses) {
+    str += " reduction (";
+    str += MemoryAccess::getReductionOperatorStr(ReductionClause.first);
+    // Remove the first two symbols (", ") to make the output look pretty.
+    str += " : " + ReductionClause.second.substr(2) + ")";
+  }
+
+  return str;
+}
+
+/// @brief Callback executed for each for node in the ast in order to print it.
+static isl_printer *cbPrintFor(__isl_take isl_printer *Printer,
+                               __isl_take isl_ast_print_options *Options,
+                               __isl_keep isl_ast_node *Node, void *) {
+
+  isl_pw_aff *DD = IslAstInfo::getMinimalDependenceDistance(Node);
+  const std::string BrokenReductionsStr = getBrokenReductionsStr(Node);
+  const std::string KnownParallelStr = "#pragma known-parallel";
+  const std::string DepDisPragmaStr = "#pragma minimal dependence distance: ";
+  const std::string SimdPragmaStr = "#pragma simd";
+  const std::string OmpPragmaStr = "#pragma omp parallel for";
+
+  if (DD)
+    Printer = printLine(Printer, DepDisPragmaStr, DD);
+
+  if (IslAstInfo::isInnermostParallel(Node))
+    Printer = printLine(Printer, SimdPragmaStr + BrokenReductionsStr);
+
+  if (IslAstInfo::isExecutedInParallel(Node))
+    Printer = printLine(Printer, OmpPragmaStr);
+  else if (IslAstInfo::isOutermostParallel(Node))
+    Printer = printLine(Printer, KnownParallelStr + BrokenReductionsStr);
+
+  isl_pw_aff_free(DD);
+  return isl_ast_node_for_print(Node, Printer, Options);
+}
+
+/// @brief Check if the current scheduling dimension is parallel
+///
+/// In case the dimension is parallel we also check if any reduction
+/// dependences is broken when we exploit this parallelism. If so,
+/// @p IsReductionParallel will be set to true. The reduction dependences we use
+/// to check are actually the union of the transitive closure of the initial
+/// reduction dependences together with their reveresal. Even though these
+/// dependences connect all iterations with each other (thus they are cyclic)
+/// we can perform the parallelism check as we are only interested in a zero
+/// (or non-zero) dependence distance on the dimension in question.
+static bool astScheduleDimIsParallel(__isl_keep isl_ast_build *Build,
+                                     Dependences *D,
+                                     IslAstUserPayload *NodeInfo) {
+  if (!D->hasValidDependences())
+    return false;
+
+  isl_union_map *Schedule = isl_ast_build_get_schedule(Build);
+  isl_union_map *Deps = D->getDependences(
+      Dependences::TYPE_RAW | Dependences::TYPE_WAW | Dependences::TYPE_WAR);
+
+  if (!D->isParallel(Schedule, Deps, &NodeInfo->MinimalDependenceDistance) &&
+      !isl_union_map_free(Schedule))
+    return false;
+
+  isl_union_map *RedDeps = D->getDependences(Dependences::TYPE_TC_RED);
+  if (!D->isParallel(Schedule, RedDeps))
+    NodeInfo->IsReductionParallel = true;
+
+  if (!NodeInfo->IsReductionParallel && !isl_union_map_free(Schedule))
+    return true;
+
+  // Annotate reduction parallel nodes with the memory accesses which caused the
+  // reduction dependences parallel execution of the node conflicts with.
+  for (const auto &MaRedPair : D->getReductionDependences()) {
+    if (!MaRedPair.second)
+      continue;
+    RedDeps = isl_union_map_from_map(isl_map_copy(MaRedPair.second));
+    if (!D->isParallel(Schedule, RedDeps))
+      NodeInfo->BrokenReductions.insert(MaRedPair.first);
+  }
+
+  isl_union_map_free(Schedule);
+  return true;
+}
+
+// This method is executed before the construction of a for node. It creates
+// an isl_id that is used to annotate the subsequently generated ast for nodes.
+//
+// In this function we also run the following analyses:
+//
+// - Detection of openmp parallel loops
+//
+static __isl_give isl_id *astBuildBeforeFor(__isl_keep isl_ast_build *Build,
+                                            void *User) {
+  AstBuildUserInfo *BuildInfo = (AstBuildUserInfo *)User;
+  IslAstUserPayload *Payload = new IslAstUserPayload();
+  isl_id *Id = isl_id_alloc(isl_ast_build_get_ctx(Build), "", Payload);
+  Id = isl_id_set_free_user(Id, freeIslAstUserPayload);
+  BuildInfo->LastForNodeId = Id;
+
+  // Test for parallelism only if we are not already inside a parallel loop
+  if (!BuildInfo->InParallelFor)
+    BuildInfo->InParallelFor = Payload->IsOutermostParallel =
+        astScheduleDimIsParallel(Build, BuildInfo->Deps, Payload);
+
+  return Id;
+}
+
+// This method is executed after the construction of a for node.
+//
+// It performs the following actions:
+//
+// - Reset the 'InParallelFor' flag, as soon as we leave a for node,
+//   that is marked as openmp parallel.
+//
+static __isl_give isl_ast_node *
+astBuildAfterFor(__isl_take isl_ast_node *Node, __isl_keep isl_ast_build *Build,
+                 void *User) {
+  isl_id *Id = isl_ast_node_get_annotation(Node);
+  assert(Id && "Post order visit assumes annotated for nodes");
+  IslAstUserPayload *Payload = (IslAstUserPayload *)isl_id_get_user(Id);
+  assert(Payload && "Post order visit assumes annotated for nodes");
+
+  AstBuildUserInfo *BuildInfo = (AstBuildUserInfo *)User;
+  assert(!Payload->Build && "Build environment already set");
+  Payload->Build = isl_ast_build_copy(Build);
+  Payload->IsInnermost = (Id == BuildInfo->LastForNodeId);
+
+  // Innermost loops that are surrounded by parallel loops have not yet been
+  // tested for parallelism. Test them here to ensure we check all innermost
+  // loops for parallelism.
+  if (Payload->IsInnermost && BuildInfo->InParallelFor) {
+    if (Payload->IsOutermostParallel)
+      Payload->IsInnermostParallel = true;
+    else
+      Payload->IsInnermostParallel =
+          astScheduleDimIsParallel(Build, BuildInfo->Deps, Payload);
+  }
+  if (Payload->IsOutermostParallel)
+    BuildInfo->InParallelFor = false;
+
+  isl_id_free(Id);
+  return Node;
+}
+
+static __isl_give isl_ast_node *AtEachDomain(__isl_take isl_ast_node *Node,
+                                             __isl_keep isl_ast_build *Build,
+                                             void *User) {
+  assert(!isl_ast_node_get_annotation(Node) && "Node already annotated");
+
+  IslAstUserPayload *Payload = new IslAstUserPayload();
+  isl_id *Id = isl_id_alloc(isl_ast_build_get_ctx(Build), "", Payload);
+  Id = isl_id_set_free_user(Id, freeIslAstUserPayload);
+
+  Payload->Build = isl_ast_build_copy(Build);
+
+  return isl_ast_node_set_annotation(Node, Id);
+}
+
+void IslAst::buildRunCondition(__isl_keep isl_ast_build *Build) {
+  // The conditions that need to be checked at run-time for this scop are
+  // available as an isl_set in the AssumedContext. We generate code for this
+  // check as follows. First, we generate an isl_pw_aff that is 1, if a certain
+  // combination of parameter values fulfills the conditions in the assumed
+  // context, and that is 0 otherwise. We then translate this isl_pw_aff into
+  // an isl_ast_expr. At run-time this expression can be evaluated and the
+  // optimized scop can be executed conditionally according to the result of the
+  // run-time check.
+
+  isl_aff *Zero =
+      isl_aff_zero_on_domain(isl_local_space_from_space(S->getParamSpace()));
+  isl_aff *One =
+      isl_aff_zero_on_domain(isl_local_space_from_space(S->getParamSpace()));
+
+  One = isl_aff_add_constant_si(One, 1);
+
+  isl_pw_aff *PwZero = isl_pw_aff_from_aff(Zero);
+  isl_pw_aff *PwOne = isl_pw_aff_from_aff(One);
+
+  PwOne = isl_pw_aff_intersect_domain(PwOne, S->getAssumedContext());
+  PwZero = isl_pw_aff_intersect_domain(
+      PwZero, isl_set_complement(S->getAssumedContext()));
+
+  isl_pw_aff *Cond = isl_pw_aff_union_max(PwOne, PwZero);
+
+  RunCondition = isl_ast_build_expr_from_pw_aff(Build, Cond);
+
+  // Create the alias checks from the minimal/maximal accesses in each alias
+  // group. This operation is by construction quadratic in the number of
+  // elements in each alias group.
+  isl_ast_expr *NonAliasGroup, *MinExpr, *MaxExpr;
+  for (const Scop::MinMaxVectorTy *MinMaxAccesses : S->getAliasGroups()) {
+    auto AccEnd = MinMaxAccesses->end();
+    for (auto AccIt0 = MinMaxAccesses->begin(); AccIt0 != AccEnd; ++AccIt0) {
+      for (auto AccIt1 = AccIt0 + 1; AccIt1 != AccEnd; ++AccIt1) {
+        MinExpr =
+            isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
+                Build, isl_pw_multi_aff_copy(AccIt0->first)));
+        MaxExpr =
+            isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
+                Build, isl_pw_multi_aff_copy(AccIt1->second)));
+        NonAliasGroup = isl_ast_expr_le(MaxExpr, MinExpr);
+        MinExpr =
+            isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
+                Build, isl_pw_multi_aff_copy(AccIt1->first)));
+        MaxExpr =
+            isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
+                Build, isl_pw_multi_aff_copy(AccIt0->second)));
+        NonAliasGroup =
+            isl_ast_expr_or(NonAliasGroup, isl_ast_expr_le(MaxExpr, MinExpr));
+        RunCondition = isl_ast_expr_and(RunCondition, NonAliasGroup);
+      }
+    }
+  }
+}
+
+IslAst::IslAst(Scop *Scop, Dependences &D) : S(Scop) {
+  isl_ctx *Ctx = S->getIslCtx();
+  isl_options_set_ast_build_atomic_upper_bound(Ctx, true);
+  isl_ast_build *Build;
+  AstBuildUserInfo BuildInfo;
+
+  if (UseContext)
+    Build = isl_ast_build_from_context(S->getContext());
+  else
+    Build = isl_ast_build_from_context(isl_set_universe(S->getParamSpace()));
+
+  Build = isl_ast_build_set_at_each_domain(Build, AtEachDomain, nullptr);
+
+  isl_union_map *Schedule =
+      isl_union_map_intersect_domain(S->getSchedule(), S->getDomains());
+
+  if (PollyParallel || DetectParallel ||
+      PollyVectorizerChoice != VECTORIZER_NONE) {
+    BuildInfo.Deps = &D;
+    BuildInfo.InParallelFor = 0;
+
+    Build = isl_ast_build_set_before_each_for(Build, &astBuildBeforeFor,
+                                              &BuildInfo);
+    Build =
+        isl_ast_build_set_after_each_for(Build, &astBuildAfterFor, &BuildInfo);
+  }
+
+  buildRunCondition(Build);
+
+  Root = isl_ast_build_ast_from_schedule(Build, Schedule);
+
+  isl_ast_build_free(Build);
+}
+
+IslAst::~IslAst() {
+  isl_ast_node_free(Root);
+  isl_ast_expr_free(RunCondition);
+}
+
+__isl_give isl_ast_node *IslAst::getAst() { return isl_ast_node_copy(Root); }
+__isl_give isl_ast_expr *IslAst::getRunCondition() {
+  return isl_ast_expr_copy(RunCondition);
+}
+
+void IslAstInfo::releaseMemory() {
+  if (Ast) {
+    delete Ast;
+    Ast = nullptr;
+  }
+}
+
+bool IslAstInfo::runOnScop(Scop &Scop) {
+  if (Ast)
+    delete Ast;
+
+  S = &Scop;
+
+  Dependences &D = getAnalysis<Dependences>();
+
+  Ast = new IslAst(&Scop, D);
+
+  DEBUG(printScop(dbgs()));
+  return false;
+}
+
+__isl_give isl_ast_node *IslAstInfo::getAst() const { return Ast->getAst(); }
+__isl_give isl_ast_expr *IslAstInfo::getRunCondition() const {
+  return Ast->getRunCondition();
+}
+
+IslAstUserPayload *IslAstInfo::getNodePayload(__isl_keep isl_ast_node *Node) {
+  isl_id *Id = isl_ast_node_get_annotation(Node);
+  if (!Id)
+    return nullptr;
+  IslAstUserPayload *Payload = (IslAstUserPayload *)isl_id_get_user(Id);
+  isl_id_free(Id);
+  return Payload;
+}
+
+bool IslAstInfo::isInnermost(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload && Payload->IsInnermost;
+}
+
+bool IslAstInfo::isParallel(__isl_keep isl_ast_node *Node) {
+  return IslAstInfo::isInnermostParallel(Node) ||
+         IslAstInfo::isOutermostParallel(Node);
+}
+
+bool IslAstInfo::isInnermostParallel(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload && Payload->IsInnermostParallel;
+}
+
+bool IslAstInfo::isOutermostParallel(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload && Payload->IsOutermostParallel;
+}
+
+bool IslAstInfo::isReductionParallel(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload && Payload->IsReductionParallel;
+}
+
+bool IslAstInfo::isExecutedInParallel(__isl_keep isl_ast_node *Node) {
+
+  if (!PollyParallel)
+    return false;
+
+  // Do not parallelize innermost loops.
+  //
+  // Parallelizing innermost loops is often not profitable, especially if
+  // they have a low number of iterations.
+  //
+  // TODO: Decide this based on the number of loop iterations that will be
+  //       executed. This can possibly require run-time checks, which again
+  //       raises the question of both run-time check overhead and code size
+  //       costs.
+  if (!PollyParallelForce && isInnermost(Node))
+    return false;
+
+  return isOutermostParallel(Node) && !isReductionParallel(Node);
+}
+
+isl_union_map *IslAstInfo::getSchedule(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload ? isl_ast_build_get_schedule(Payload->Build) : nullptr;
+}
+
+isl_pw_aff *
+IslAstInfo::getMinimalDependenceDistance(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload ? isl_pw_aff_copy(Payload->MinimalDependenceDistance)
+                 : nullptr;
+}
+
+IslAstInfo::MemoryAccessSet *
+IslAstInfo::getBrokenReductions(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload ? &Payload->BrokenReductions : nullptr;
+}
+
+isl_ast_build *IslAstInfo::getBuild(__isl_keep isl_ast_node *Node) {
+  IslAstUserPayload *Payload = getNodePayload(Node);
+  return Payload ? Payload->Build : nullptr;
+}
+
+void IslAstInfo::printScop(raw_ostream &OS) const {
+  isl_ast_print_options *Options;
+  isl_ast_node *RootNode = getAst();
+  isl_ast_expr *RunCondition = getRunCondition();
+  char *RtCStr, *AstStr;
+
+  Scop &S = getCurScop();
+  Options = isl_ast_print_options_alloc(S.getIslCtx());
+  Options = isl_ast_print_options_set_print_for(Options, cbPrintFor, nullptr);
+
+  isl_printer *P = isl_printer_to_str(S.getIslCtx());
+  P = isl_printer_print_ast_expr(P, RunCondition);
+  RtCStr = isl_printer_get_str(P);
+  P = isl_printer_flush(P);
+  P = isl_printer_indent(P, 4);
+  P = isl_printer_set_output_format(P, ISL_FORMAT_C);
+  P = isl_ast_node_print(RootNode, P, Options);
+  AstStr = isl_printer_get_str(P);
+
+  Function *F = S.getRegion().getEntry()->getParent();
+  isl_union_map *Schedule =
+      isl_union_map_intersect_domain(S.getSchedule(), S.getDomains());
+
+  OS << ":: isl ast :: " << F->getName() << " :: " << S.getRegion().getNameStr()
+     << "\n";
+  DEBUG({
+    dbgs() << S.getContextStr() << "\n";
+    dbgs() << stringFromIslObj(Schedule);
+  });
+  OS << "\nif (" << RtCStr << ")\n\n";
+  OS << AstStr << "\n";
+  OS << "else\n";
+  OS << "    {  /* original code */ }\n\n";
+
+  isl_ast_expr_free(RunCondition);
+  isl_union_map_free(Schedule);
+  isl_ast_node_free(RootNode);
+  isl_printer_free(P);
+}
+
+void IslAstInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+  // Get the Common analysis usage of ScopPasses.
+  ScopPass::getAnalysisUsage(AU);
+  AU.addRequired<ScopInfo>();
+  AU.addRequired<Dependences>();
+}
+
+char IslAstInfo::ID = 0;
+
+Pass *polly::createIslAstInfoPass() { return new IslAstInfo(); }
+
+INITIALIZE_PASS_BEGIN(IslAstInfo, "polly-ast",
+                      "Polly - Generate an AST of the SCoP (isl)", false,
+                      false);
+INITIALIZE_PASS_DEPENDENCY(ScopInfo);
+INITIALIZE_PASS_DEPENDENCY(Dependences);
+INITIALIZE_PASS_END(IslAstInfo, "polly-ast",
+                    "Polly - Generate an AST from the SCoP (isl)", false, false)
diff --git a/final/lib/CodeGen/IslCodeGeneration.cpp b/final/lib/CodeGen/IslCodeGeneration.cpp
new file mode 100644
index 0000000..935f0a7
--- /dev/null
+++ b/final/lib/CodeGen/IslCodeGeneration.cpp
@@ -0,0 +1,986 @@
+//===------ IslCodeGeneration.cpp - Code generate the Scops using ISL. ----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The IslCodeGeneration pass takes a Scop created by ScopInfo and translates it
+// back to LLVM-IR using the ISL code generator.
+//
+// The Scop describes the high level memory behaviour of a control flow region.
+// Transformation passes can update the schedule (execution order) of statements
+// in the Scop. ISL is used to generate an abstract syntax tree that reflects
+// the updated execution order. This clast is used to create new LLVM-IR that is
+// computationally equivalent to the original control flow region, but executes
+// its code in the new execution order defined by the changed scattering.
+//
+//===----------------------------------------------------------------------===//
+#include "polly/Config/config.h"
+#include "polly/CodeGen/IslExprBuilder.h"
+#include "polly/CodeGen/BlockGenerators.h"
+#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/CodeGen/IslAst.h"
+#include "polly/CodeGen/LoopGenerators.h"
+#include "polly/CodeGen/Utils.h"
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+#include "polly/Support/ScopHelper.h"
+#include "polly/Support/SCEVValidator.h"
+#include "polly/TempScopInfo.h"
+
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+#include "isl/union_map.h"
+#include "isl/list.h"
+#include "isl/ast.h"
+#include "isl/ast_build.h"
+#include "isl/set.h"
+#include "isl/map.h"
+#include "isl/aff.h"
+
+using namespace polly;
+using namespace llvm;
+
+#define DEBUG_TYPE "polly-codegen-isl"
+
+class IslNodeBuilder {
+public:
+  IslNodeBuilder(PollyIRBuilder &Builder, ScopAnnotator &Annotator, Pass *P,
+                 const DataLayout &DL, LoopInfo &LI, ScalarEvolution &SE,
+                 DominatorTree &DT, Scop &S)
+      : S(S), Builder(Builder), Annotator(Annotator),
+        Rewriter(new SCEVExpander(SE, "polly")),
+        ExprBuilder(Builder, IDToValue, *Rewriter), P(P), DL(DL), LI(LI),
+        SE(SE), DT(DT) {}
+
+  ~IslNodeBuilder() { delete Rewriter; }
+
+  void addParameters(__isl_take isl_set *Context);
+  void create(__isl_take isl_ast_node *Node);
+  IslExprBuilder &getExprBuilder() { return ExprBuilder; }
+
+private:
+  Scop &S;
+  PollyIRBuilder &Builder;
+  ScopAnnotator &Annotator;
+
+  /// @brief A SCEVExpander to create llvm values from SCEVs.
+  SCEVExpander *Rewriter;
+
+  IslExprBuilder ExprBuilder;
+  Pass *P;
+  const DataLayout &DL;
+  LoopInfo &LI;
+  ScalarEvolution &SE;
+  DominatorTree &DT;
+
+  /// @brief The current iteration of out-of-scop loops
+  ///
+  /// This map provides for a given loop a llvm::Value that contains the current
+  /// loop iteration.
+  LoopToScevMapT OutsideLoopIterations;
+
+  // This maps an isl_id* to the Value* it has in the generated program. For now
+  // on, the only isl_ids that are stored here are the newly calculated loop
+  // ivs.
+  IslExprBuilder::IDToValueTy IDToValue;
+
+  /// Generate code for a given SCEV*
+  ///
+  /// This function generates code for a given SCEV expression. It generated
+  /// code is emmitted at the end of the basic block our Builder currently
+  /// points to and the resulting value is returned.
+  ///
+  /// @param Expr The expression to code generate.
+  Value *generateSCEV(const SCEV *Expr);
+
+  /// A set of Value -> Value remappings to apply when generating new code.
+  ///
+  /// When generating new code for a ScopStmt this map is used to map certain
+  /// llvm::Values to new llvm::Values.
+  ValueMapT ValueMap;
+
+  // Extract the upper bound of this loop
+  //
+  // The isl code generation can generate arbitrary expressions to check if the
+  // upper bound of a loop is reached, but it provides an option to enforce
+  // 'atomic' upper bounds. An 'atomic upper bound is always of the form
+  // iv <= expr, where expr is an (arbitrary) expression not containing iv.
+  //
+  // This function extracts 'atomic' upper bounds. Polly, in general, requires
+  // atomic upper bounds for the following reasons:
+  //
+  // 1. An atomic upper bound is loop invariant
+  //
+  //    It must not be calculated at each loop iteration and can often even be
+  //    hoisted out further by the loop invariant code motion.
+  //
+  // 2. OpenMP needs a loop invarient upper bound to calculate the number
+  //    of loop iterations.
+  //
+  // 3. With the existing code, upper bounds have been easier to implement.
+  __isl_give isl_ast_expr *getUpperBound(__isl_keep isl_ast_node *For,
+                                         CmpInst::Predicate &Predicate);
+
+  unsigned getNumberOfIterations(__isl_keep isl_ast_node *For);
+
+  /// Compute the values and loops referenced in this subtree.
+  ///
+  /// This function looks at all ScopStmts scheduled below the provided For node
+  /// and finds the llvm::Value[s] and llvm::Loops[s] which are referenced but
+  /// not locally defined.
+  ///
+  /// Values that can be synthesized or that are available as globals are
+  /// considered locally defined.
+  ///
+  /// Loops that contain the scop or that are part of the scop are considered
+  /// locally defined. Loops that are before the scop, but do not contain the
+  /// scop itself are considered not locally defined.
+  ///
+  /// @param For    The node defining the subtree.
+  /// @param Values A vector that will be filled with the Values referenced in
+  ///               this subtree.
+  /// @param Loops  A vector that will be filled with the Loops referenced in
+  ///               this subtree.
+  void getReferencesInSubtree(__isl_keep isl_ast_node *For,
+                              SetVector<Value *> &Values,
+                              SetVector<const Loop *> &Loops);
+
+  /// Change the llvm::Value(s) used for code generation.
+  ///
+  /// When generating code certain values (e.g., references to induction
+  /// variables or array base pointers) in the original code may be replaced by
+  /// new values. This function allows to (partially) update the set of values
+  /// used. A typical use case for this function is the case when we continue
+  /// code generation in a subfunction/kernel function and need to explicitly
+  /// pass down certain values.
+  ///
+  /// @param NewValues A map that maps certain llvm::Values to new llvm::Values.
+  void updateValues(ParallelLoopGenerator::ValueToValueMapTy &NewValues);
+
+  void createFor(__isl_take isl_ast_node *For);
+  void createForVector(__isl_take isl_ast_node *For, int VectorWidth);
+  void createForSequential(__isl_take isl_ast_node *For);
+
+  /// Create LLVM-IR that executes a for node thread parallel.
+  ///
+  /// @param For The FOR isl_ast_node for which code is generated.
+  void createForParallel(__isl_take isl_ast_node *For);
+
+  /// Generate LLVM-IR that computes the values of the original induction
+  /// variables in function of the newly generated loop induction variables.
+  ///
+  /// Example:
+  ///
+  ///   // Original
+  ///   for i
+  ///     for j
+  ///       S(i)
+  ///
+  ///   Schedule: [i,j] -> [i+j, j]
+  ///
+  ///   // New
+  ///   for c0
+  ///     for c1
+  ///       S(c0 - c1, c1)
+  ///
+  /// Assuming the original code consists of two loops which are
+  /// transformed according to a schedule [i,j] -> [c0=i+j,c1=j]. The resulting
+  /// ast models the original statement as a call expression where each argument
+  /// is an expression that computes the old induction variables from the new
+  /// ones, ordered such that the first argument computes the value of induction
+  /// variable that was outermost in the original code.
+  ///
+  /// @param Expr The call expression that represents the statement.
+  /// @param Stmt The statement that is called.
+  /// @param VMap The value map into which the mapping from the old induction
+  ///             variable to the new one is inserted. This mapping is used
+  ///             for the classical code generation (not scev-based) and
+  ///             gives an explicit mapping from an original, materialized
+  ///             induction variable. It consequently can only be expressed
+  ///             if there was an explicit induction variable.
+  /// @param LTS  The loop to SCEV map in which the mapping from the original
+  ///             loop to a SCEV representing the new loop iv is added. This
+  ///             mapping does not require an explicit induction variable.
+  ///             Instead, we think in terms of an implicit induction variable
+  ///             that counts the number of times a loop is executed. For each
+  ///             original loop this count, expressed in function of the new
+  ///             induction variables, is added to the LTS map.
+  void createSubstitutions(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt,
+                           ValueMapT &VMap, LoopToScevMapT &LTS);
+  void createSubstitutionsVector(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt,
+                                 VectorValueMapT &VMap,
+                                 std::vector<LoopToScevMapT> &VLTS,
+                                 std::vector<Value *> &IVS,
+                                 __isl_take isl_id *IteratorID);
+  void createIf(__isl_take isl_ast_node *If);
+  void createUserVector(__isl_take isl_ast_node *User,
+                        std::vector<Value *> &IVS,
+                        __isl_take isl_id *IteratorID,
+                        __isl_take isl_union_map *Schedule);
+  void createUser(__isl_take isl_ast_node *User);
+  void createBlock(__isl_take isl_ast_node *Block);
+};
+
+__isl_give isl_ast_expr *
+IslNodeBuilder::getUpperBound(__isl_keep isl_ast_node *For,
+                              ICmpInst::Predicate &Predicate) {
+  isl_id *UBID, *IteratorID;
+  isl_ast_expr *Cond, *Iterator, *UB, *Arg0;
+  isl_ast_op_type Type;
+
+  Cond = isl_ast_node_for_get_cond(For);
+  Iterator = isl_ast_node_for_get_iterator(For);
+  isl_ast_expr_get_type(Cond);
+  assert(isl_ast_expr_get_type(Cond) == isl_ast_expr_op &&
+         "conditional expression is not an atomic upper bound");
+
+  Type = isl_ast_expr_get_op_type(Cond);
+
+  switch (Type) {
+  case isl_ast_op_le:
+    Predicate = ICmpInst::ICMP_SLE;
+    break;
+  case isl_ast_op_lt:
+    Predicate = ICmpInst::ICMP_SLT;
+    break;
+  default:
+    llvm_unreachable("Unexpected comparision type in loop conditon");
+  }
+
+  Arg0 = isl_ast_expr_get_op_arg(Cond, 0);
+
+  assert(isl_ast_expr_get_type(Arg0) == isl_ast_expr_id &&
+         "conditional expression is not an atomic upper bound");
+
+  UBID = isl_ast_expr_get_id(Arg0);
+
+  assert(isl_ast_expr_get_type(Iterator) == isl_ast_expr_id &&
+         "Could not get the iterator");
+
+  IteratorID = isl_ast_expr_get_id(Iterator);
+
+  assert(UBID == IteratorID &&
+         "conditional expression is not an atomic upper bound");
+
+  UB = isl_ast_expr_get_op_arg(Cond, 1);
+
+  isl_ast_expr_free(Cond);
+  isl_ast_expr_free(Iterator);
+  isl_ast_expr_free(Arg0);
+  isl_id_free(IteratorID);
+  isl_id_free(UBID);
+
+  return UB;
+}
+
+unsigned IslNodeBuilder::getNumberOfIterations(__isl_keep isl_ast_node *For) {
+  isl_union_map *Schedule = IslAstInfo::getSchedule(For);
+  isl_set *LoopDomain = isl_set_from_union_set(isl_union_map_range(Schedule));
+  int NumberOfIterations = polly::getNumberOfIterations(LoopDomain);
+  if (NumberOfIterations == -1)
+    return -1;
+  return NumberOfIterations + 1;
+}
+
+struct FindValuesUser {
+  LoopInfo &LI;
+  ScalarEvolution &SE;
+  Region &R;
+  SetVector<Value *> &Values;
+  SetVector<const SCEV *> &SCEVs;
+};
+
+/// Extract the values and SCEVs needed to generate code for a ScopStmt.
+///
+/// This function extracts a ScopStmt from a given isl_set and computes the
+/// Values this statement depends on as well as a set of SCEV expressions that
+/// need to be synthesized when generating code for this statment.
+static int findValuesInStmt(isl_set *Set, void *UserPtr) {
+  isl_id *Id = isl_set_get_tuple_id(Set);
+  struct FindValuesUser &User = *static_cast<struct FindValuesUser *>(UserPtr);
+  const ScopStmt *Stmt = static_cast<const ScopStmt *>(isl_id_get_user(Id));
+  const BasicBlock *BB = Stmt->getBasicBlock();
+
+  // Check all the operands of instructions in the basic block.
+  for (const Instruction &Inst : *BB) {
+    for (Value *SrcVal : Inst.operands()) {
+      if (Instruction *OpInst = dyn_cast<Instruction>(SrcVal))
+        if (canSynthesize(OpInst, &User.LI, &User.SE, &User.R)) {
+          User.SCEVs.insert(
+              User.SE.getSCEVAtScope(OpInst, User.LI.getLoopFor(BB)));
+          continue;
+        }
+      if (Instruction *OpInst = dyn_cast<Instruction>(SrcVal))
+        if (Stmt->getParent()->getRegion().contains(OpInst))
+          continue;
+
+      if (isa<Instruction>(SrcVal) || isa<Argument>(SrcVal))
+        User.Values.insert(SrcVal);
+    }
+  }
+  isl_id_free(Id);
+  isl_set_free(Set);
+  return 0;
+}
+
+void IslNodeBuilder::getReferencesInSubtree(__isl_keep isl_ast_node *For,
+                                            SetVector<Value *> &Values,
+                                            SetVector<const Loop *> &Loops) {
+
+  SetVector<const SCEV *> SCEVs;
+  struct FindValuesUser FindValues = {LI, SE, S.getRegion(), Values, SCEVs};
+
+  for (const auto &I : IDToValue)
+    Values.insert(I.second);
+
+  for (const auto &I : OutsideLoopIterations)
+    Values.insert(cast<SCEVUnknown>(I.second)->getValue());
+
+  isl_union_set *Schedule = isl_union_map_domain(IslAstInfo::getSchedule(For));
+
+  isl_union_set_foreach_set(Schedule, findValuesInStmt, &FindValues);
+  isl_union_set_free(Schedule);
+
+  for (const SCEV *Expr : SCEVs) {
+    findValues(Expr, Values);
+    findLoops(Expr, Loops);
+  }
+
+  Values.remove_if([](const Value *V) { return isa<GlobalValue>(V); });
+
+  /// Remove loops that contain the scop or that are part of the scop, as they
+  /// are considered local. This leaves only loops that are before the scop, but
+  /// do not contain the scop itself.
+  Loops.remove_if([this](const Loop *L) {
+    return this->S.getRegion().contains(L) ||
+           L->contains(S.getRegion().getEntry());
+  });
+}
+
+void IslNodeBuilder::updateValues(
+    ParallelLoopGenerator::ValueToValueMapTy &NewValues) {
+  SmallPtrSet<Value *, 5> Inserted;
+
+  for (const auto &I : IDToValue) {
+    IDToValue[I.first] = NewValues[I.second];
+    Inserted.insert(I.second);
+  }
+
+  for (const auto &I : NewValues) {
+    if (Inserted.count(I.first))
+      continue;
+
+    ValueMap[I.first] = I.second;
+  }
+}
+
+void IslNodeBuilder::createUserVector(__isl_take isl_ast_node *User,
+                                      std::vector<Value *> &IVS,
+                                      __isl_take isl_id *IteratorID,
+                                      __isl_take isl_union_map *Schedule) {
+  isl_ast_expr *Expr = isl_ast_node_user_get_expr(User);
+  isl_ast_expr *StmtExpr = isl_ast_expr_get_op_arg(Expr, 0);
+  isl_id *Id = isl_ast_expr_get_id(StmtExpr);
+  isl_ast_expr_free(StmtExpr);
+  ScopStmt *Stmt = (ScopStmt *)isl_id_get_user(Id);
+  VectorValueMapT VectorMap(IVS.size());
+  std::vector<LoopToScevMapT> VLTS(IVS.size());
+
+  isl_union_set *Domain = isl_union_set_from_set(Stmt->getDomain());
+  Schedule = isl_union_map_intersect_domain(Schedule, Domain);
+  isl_map *S = isl_map_from_union_map(Schedule);
+
+  createSubstitutionsVector(Expr, Stmt, VectorMap, VLTS, IVS, IteratorID);
+  VectorBlockGenerator::generate(Builder, *Stmt, VectorMap, VLTS, S, P, LI, SE,
+                                 IslAstInfo::getBuild(User), &ExprBuilder);
+
+  isl_map_free(S);
+  isl_id_free(Id);
+  isl_ast_node_free(User);
+}
+
+void IslNodeBuilder::createForVector(__isl_take isl_ast_node *For,
+                                     int VectorWidth) {
+  isl_ast_node *Body = isl_ast_node_for_get_body(For);
+  isl_ast_expr *Init = isl_ast_node_for_get_init(For);
+  isl_ast_expr *Inc = isl_ast_node_for_get_inc(For);
+  isl_ast_expr *Iterator = isl_ast_node_for_get_iterator(For);
+  isl_id *IteratorID = isl_ast_expr_get_id(Iterator);
+
+  Value *ValueLB = ExprBuilder.create(Init);
+  Value *ValueInc = ExprBuilder.create(Inc);
+
+  Type *MaxType = ExprBuilder.getType(Iterator);
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueLB->getType());
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueInc->getType());
+
+  if (MaxType != ValueLB->getType())
+    ValueLB = Builder.CreateSExt(ValueLB, MaxType);
+  if (MaxType != ValueInc->getType())
+    ValueInc = Builder.CreateSExt(ValueInc, MaxType);
+
+  std::vector<Value *> IVS(VectorWidth);
+  IVS[0] = ValueLB;
+
+  for (int i = 1; i < VectorWidth; i++)
+    IVS[i] = Builder.CreateAdd(IVS[i - 1], ValueInc, "p_vector_iv");
+
+  isl_union_map *Schedule = IslAstInfo::getSchedule(For);
+  assert(Schedule && "For statement annotation does not contain its schedule");
+
+  IDToValue[IteratorID] = ValueLB;
+
+  switch (isl_ast_node_get_type(Body)) {
+  case isl_ast_node_user:
+    createUserVector(Body, IVS, isl_id_copy(IteratorID),
+                     isl_union_map_copy(Schedule));
+    break;
+  case isl_ast_node_block: {
+    isl_ast_node_list *List = isl_ast_node_block_get_children(Body);
+
+    for (int i = 0; i < isl_ast_node_list_n_ast_node(List); ++i)
+      createUserVector(isl_ast_node_list_get_ast_node(List, i), IVS,
+                       isl_id_copy(IteratorID), isl_union_map_copy(Schedule));
+
+    isl_ast_node_free(Body);
+    isl_ast_node_list_free(List);
+    break;
+  }
+  default:
+    isl_ast_node_dump(Body);
+    llvm_unreachable("Unhandled isl_ast_node in vectorizer");
+  }
+
+  IDToValue.erase(IDToValue.find(IteratorID));
+  isl_id_free(IteratorID);
+  isl_union_map_free(Schedule);
+
+  isl_ast_node_free(For);
+  isl_ast_expr_free(Iterator);
+}
+
+void IslNodeBuilder::createForSequential(__isl_take isl_ast_node *For) {
+  isl_ast_node *Body;
+  isl_ast_expr *Init, *Inc, *Iterator, *UB;
+  isl_id *IteratorID;
+  Value *ValueLB, *ValueUB, *ValueInc;
+  Type *MaxType;
+  BasicBlock *ExitBlock;
+  Value *IV;
+  CmpInst::Predicate Predicate;
+  bool Parallel;
+
+  Parallel =
+      IslAstInfo::isParallel(For) && !IslAstInfo::isReductionParallel(For);
+
+  Body = isl_ast_node_for_get_body(For);
+
+  // isl_ast_node_for_is_degenerate(For)
+  //
+  // TODO: For degenerated loops we could generate a plain assignment.
+  //       However, for now we just reuse the logic for normal loops, which will
+  //       create a loop with a single iteration.
+
+  Init = isl_ast_node_for_get_init(For);
+  Inc = isl_ast_node_for_get_inc(For);
+  Iterator = isl_ast_node_for_get_iterator(For);
+  IteratorID = isl_ast_expr_get_id(Iterator);
+  UB = getUpperBound(For, Predicate);
+
+  ValueLB = ExprBuilder.create(Init);
+  ValueUB = ExprBuilder.create(UB);
+  ValueInc = ExprBuilder.create(Inc);
+
+  MaxType = ExprBuilder.getType(Iterator);
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueLB->getType());
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueUB->getType());
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueInc->getType());
+
+  if (MaxType != ValueLB->getType())
+    ValueLB = Builder.CreateSExt(ValueLB, MaxType);
+  if (MaxType != ValueUB->getType())
+    ValueUB = Builder.CreateSExt(ValueUB, MaxType);
+  if (MaxType != ValueInc->getType())
+    ValueInc = Builder.CreateSExt(ValueInc, MaxType);
+
+  // If we can show that LB <Predicate> UB holds at least once, we can
+  // omit the GuardBB in front of the loop.
+  bool UseGuardBB =
+      !SE.isKnownPredicate(Predicate, SE.getSCEV(ValueLB), SE.getSCEV(ValueUB));
+  IV = createLoop(ValueLB, ValueUB, ValueInc, Builder, P, LI, DT, ExitBlock,
+                  Predicate, &Annotator, Parallel, UseGuardBB);
+  IDToValue[IteratorID] = IV;
+
+  create(Body);
+
+  Annotator.popLoop(Parallel);
+
+  IDToValue.erase(IDToValue.find(IteratorID));
+
+  Builder.SetInsertPoint(ExitBlock->begin());
+
+  isl_ast_node_free(For);
+  isl_ast_expr_free(Iterator);
+  isl_id_free(IteratorID);
+}
+
+/// @brief Remove the BBs contained in a (sub)function from the dominator tree.
+///
+/// This function removes the basic blocks that are part of a subfunction from
+/// the dominator tree. Specifically, when generating code it may happen that at
+/// some point the code generation continues in a new sub-function (e.g., when
+/// generating OpenMP code). The basic blocks that are created in this
+/// sub-function are then still part of the dominator tree of the original
+/// function, such that the dominator tree reaches over function boundaries.
+/// This is not only incorrect, but also causes crashes. This function now
+/// removes from the dominator tree all basic blocks that are dominated (and
+/// consequently reachable) from the entry block of this (sub)function.
+///
+/// FIXME: A LLVM (function or region) pass should not touch anything outside of
+/// the function/region it runs on. Hence, the pure need for this function shows
+/// that we do not comply to this rule. At the moment, this does not cause any
+/// issues, but we should be aware that such issues may appear. Unfortunately
+/// the current LLVM pass infrastructure does not allow to make Polly a module
+/// or call-graph pass to solve this issue, as such a pass would not have access
+/// to the per-function analyses passes needed by Polly. A future pass manager
+/// infrastructure is supposed to enable such kind of access possibly allowing
+/// us to create a cleaner solution here.
+///
+/// FIXME: Instead of adding the dominance information and then dropping it
+/// later on, we should try to just not add it in the first place. This requires
+/// some careful testing to make sure this does not break in interaction with
+/// the SCEVBuilder and SplitBlock which may rely on the dominator tree or
+/// which may try to update it.
+///
+/// @param F The function which contains the BBs to removed.
+/// @param DT The dominator tree from which to remove the BBs.
+static void removeSubFuncFromDomTree(Function *F, DominatorTree &DT) {
+  DomTreeNode *N = DT.getNode(&F->getEntryBlock());
+  std::vector<BasicBlock *> Nodes;
+
+  // We can only remove an element from the dominator tree, if all its children
+  // have been removed. To ensure this we obtain the list of nodes to remove
+  // using a post-order tree traversal.
+  for (po_iterator<DomTreeNode *> I = po_begin(N), E = po_end(N); I != E; ++I)
+    Nodes.push_back(I->getBlock());
+
+  for (BasicBlock *BB : Nodes)
+    DT.eraseNode(BB);
+}
+
+void IslNodeBuilder::createForParallel(__isl_take isl_ast_node *For) {
+  isl_ast_node *Body;
+  isl_ast_expr *Init, *Inc, *Iterator, *UB;
+  isl_id *IteratorID;
+  Value *ValueLB, *ValueUB, *ValueInc;
+  Type *MaxType;
+  Value *IV;
+  CmpInst::Predicate Predicate;
+
+  Body = isl_ast_node_for_get_body(For);
+  Init = isl_ast_node_for_get_init(For);
+  Inc = isl_ast_node_for_get_inc(For);
+  Iterator = isl_ast_node_for_get_iterator(For);
+  IteratorID = isl_ast_expr_get_id(Iterator);
+  UB = getUpperBound(For, Predicate);
+
+  ValueLB = ExprBuilder.create(Init);
+  ValueUB = ExprBuilder.create(UB);
+  ValueInc = ExprBuilder.create(Inc);
+
+  // OpenMP always uses SLE. In case the isl generated AST uses a SLT
+  // expression, we need to adjust the loop blound by one.
+  if (Predicate == CmpInst::ICMP_SLT)
+    ValueUB = Builder.CreateAdd(
+        ValueUB, Builder.CreateSExt(Builder.getTrue(), ValueUB->getType()));
+
+  MaxType = ExprBuilder.getType(Iterator);
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueLB->getType());
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueUB->getType());
+  MaxType = ExprBuilder.getWidestType(MaxType, ValueInc->getType());
+
+  if (MaxType != ValueLB->getType())
+    ValueLB = Builder.CreateSExt(ValueLB, MaxType);
+  if (MaxType != ValueUB->getType())
+    ValueUB = Builder.CreateSExt(ValueUB, MaxType);
+  if (MaxType != ValueInc->getType())
+    ValueInc = Builder.CreateSExt(ValueInc, MaxType);
+
+  BasicBlock::iterator LoopBody;
+
+  SetVector<Value *> SubtreeValues;
+  SetVector<const Loop *> Loops;
+
+  getReferencesInSubtree(For, SubtreeValues, Loops);
+
+  // Create for all loops we depend on values that contain the current loop
+  // iteration. These values are necessary to generate code for SCEVs that
+  // depend on such loops. As a result we need to pass them to the subfunction.
+  for (const Loop *L : Loops) {
+    const SCEV *OuterLIV = SE.getAddRecExpr(SE.getUnknown(Builder.getInt64(0)),
+                                            SE.getUnknown(Builder.getInt64(1)),
+                                            L, SCEV::FlagAnyWrap);
+    Value *V = generateSCEV(OuterLIV);
+    OutsideLoopIterations[L] = SE.getUnknown(V);
+    SubtreeValues.insert(V);
+  }
+
+  ParallelLoopGenerator::ValueToValueMapTy NewValues;
+  ParallelLoopGenerator ParallelLoopGen(Builder, P, LI, DT, DL);
+
+  IV = ParallelLoopGen.createParallelLoop(ValueLB, ValueUB, ValueInc,
+                                          SubtreeValues, NewValues, &LoopBody);
+  BasicBlock::iterator AfterLoop = Builder.GetInsertPoint();
+  Builder.SetInsertPoint(LoopBody);
+
+  // Save the current values.
+  ValueMapT ValueMapCopy = ValueMap;
+  IslExprBuilder::IDToValueTy IDToValueCopy = IDToValue;
+
+  updateValues(NewValues);
+  IDToValue[IteratorID] = IV;
+
+  create(Body);
+
+  // Restore the original values.
+  ValueMap = ValueMapCopy;
+  IDToValue = IDToValueCopy;
+
+  Builder.SetInsertPoint(AfterLoop);
+  removeSubFuncFromDomTree((*LoopBody).getParent()->getParent(), DT);
+
+  for (const Loop *L : Loops)
+    OutsideLoopIterations.erase(L);
+
+  isl_ast_node_free(For);
+  isl_ast_expr_free(Iterator);
+  isl_id_free(IteratorID);
+}
+
+void IslNodeBuilder::createFor(__isl_take isl_ast_node *For) {
+  bool Vector = PollyVectorizerChoice != VECTORIZER_NONE;
+
+  if (Vector && IslAstInfo::isInnermostParallel(For) &&
+      !IslAstInfo::isReductionParallel(For)) {
+    int VectorWidth = getNumberOfIterations(For);
+    if (1 < VectorWidth && VectorWidth <= 16) {
+      createForVector(For, VectorWidth);
+      return;
+    }
+  }
+
+  if (IslAstInfo::isExecutedInParallel(For)) {
+    createForParallel(For);
+    return;
+  }
+  createForSequential(For);
+}
+
+void IslNodeBuilder::createIf(__isl_take isl_ast_node *If) {
+  isl_ast_expr *Cond = isl_ast_node_if_get_cond(If);
+
+  Function *F = Builder.GetInsertBlock()->getParent();
+  LLVMContext &Context = F->getContext();
+
+  BasicBlock *CondBB =
+      SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P);
+  CondBB->setName("polly.cond");
+  BasicBlock *MergeBB = SplitBlock(CondBB, CondBB->begin(), P);
+  MergeBB->setName("polly.merge");
+  BasicBlock *ThenBB = BasicBlock::Create(Context, "polly.then", F);
+  BasicBlock *ElseBB = BasicBlock::Create(Context, "polly.else", F);
+
+  DT.addNewBlock(ThenBB, CondBB);
+  DT.addNewBlock(ElseBB, CondBB);
+  DT.changeImmediateDominator(MergeBB, CondBB);
+
+  Loop *L = LI.getLoopFor(CondBB);
+  if (L) {
+    L->addBasicBlockToLoop(ThenBB, LI.getBase());
+    L->addBasicBlockToLoop(ElseBB, LI.getBase());
+  }
+
+  CondBB->getTerminator()->eraseFromParent();
+
+  Builder.SetInsertPoint(CondBB);
+  Value *Predicate = ExprBuilder.create(Cond);
+  Builder.CreateCondBr(Predicate, ThenBB, ElseBB);
+  Builder.SetInsertPoint(ThenBB);
+  Builder.CreateBr(MergeBB);
+  Builder.SetInsertPoint(ElseBB);
+  Builder.CreateBr(MergeBB);
+  Builder.SetInsertPoint(ThenBB->begin());
+
+  create(isl_ast_node_if_get_then(If));
+
+  Builder.SetInsertPoint(ElseBB->begin());
+
+  if (isl_ast_node_if_has_else(If))
+    create(isl_ast_node_if_get_else(If));
+
+  Builder.SetInsertPoint(MergeBB->begin());
+
+  isl_ast_node_free(If);
+}
+
+void IslNodeBuilder::createSubstitutions(isl_ast_expr *Expr, ScopStmt *Stmt,
+                                         ValueMapT &VMap, LoopToScevMapT &LTS) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "Expression of type 'op' expected");
+  assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_call &&
+         "Opertation of type 'call' expected");
+  for (int i = 0; i < isl_ast_expr_get_op_n_arg(Expr) - 1; ++i) {
+    isl_ast_expr *SubExpr;
+    Value *V;
+
+    SubExpr = isl_ast_expr_get_op_arg(Expr, i + 1);
+    V = ExprBuilder.create(SubExpr);
+    ScalarEvolution *SE = Stmt->getParent()->getSE();
+    LTS[Stmt->getLoopForDimension(i)] = SE->getUnknown(V);
+  }
+
+  // Add the current ValueMap to our per-statement value map.
+  //
+  // This is needed e.g. to rewrite array base addresses when moving code
+  // into a parallely executed subfunction.
+  VMap.insert(ValueMap.begin(), ValueMap.end());
+
+  isl_ast_expr_free(Expr);
+}
+
+void IslNodeBuilder::createSubstitutionsVector(
+    __isl_take isl_ast_expr *Expr, ScopStmt *Stmt, VectorValueMapT &VMap,
+    std::vector<LoopToScevMapT> &VLTS, std::vector<Value *> &IVS,
+    __isl_take isl_id *IteratorID) {
+  int i = 0;
+
+  Value *OldValue = IDToValue[IteratorID];
+  for (Value *IV : IVS) {
+    IDToValue[IteratorID] = IV;
+    createSubstitutions(isl_ast_expr_copy(Expr), Stmt, VMap[i], VLTS[i]);
+    i++;
+  }
+
+  IDToValue[IteratorID] = OldValue;
+  isl_id_free(IteratorID);
+  isl_ast_expr_free(Expr);
+}
+
+void IslNodeBuilder::createUser(__isl_take isl_ast_node *User) {
+  ValueMapT VMap;
+  LoopToScevMapT LTS;
+  isl_id *Id;
+  ScopStmt *Stmt;
+
+  isl_ast_expr *Expr = isl_ast_node_user_get_expr(User);
+  isl_ast_expr *StmtExpr = isl_ast_expr_get_op_arg(Expr, 0);
+  Id = isl_ast_expr_get_id(StmtExpr);
+  isl_ast_expr_free(StmtExpr);
+
+  LTS.insert(OutsideLoopIterations.begin(), OutsideLoopIterations.end());
+
+  Stmt = (ScopStmt *)isl_id_get_user(Id);
+
+  createSubstitutions(Expr, Stmt, VMap, LTS);
+  BlockGenerator::generate(Builder, *Stmt, VMap, LTS, P, LI, SE,
+                           IslAstInfo::getBuild(User), &ExprBuilder);
+
+  isl_ast_node_free(User);
+  isl_id_free(Id);
+}
+
+void IslNodeBuilder::createBlock(__isl_take isl_ast_node *Block) {
+  isl_ast_node_list *List = isl_ast_node_block_get_children(Block);
+
+  for (int i = 0; i < isl_ast_node_list_n_ast_node(List); ++i)
+    create(isl_ast_node_list_get_ast_node(List, i));
+
+  isl_ast_node_free(Block);
+  isl_ast_node_list_free(List);
+}
+
+void IslNodeBuilder::create(__isl_take isl_ast_node *Node) {
+  switch (isl_ast_node_get_type(Node)) {
+  case isl_ast_node_error:
+    llvm_unreachable("code  generation error");
+  case isl_ast_node_for:
+    createFor(Node);
+    return;
+  case isl_ast_node_if:
+    createIf(Node);
+    return;
+  case isl_ast_node_user:
+    createUser(Node);
+    return;
+  case isl_ast_node_block:
+    createBlock(Node);
+    return;
+  }
+
+  llvm_unreachable("Unknown isl_ast_node type");
+}
+
+void IslNodeBuilder::addParameters(__isl_take isl_set *Context) {
+
+  for (unsigned i = 0; i < isl_set_dim(Context, isl_dim_param); ++i) {
+    isl_id *Id;
+
+    Id = isl_set_get_dim_id(Context, isl_dim_param, i);
+    IDToValue[Id] = generateSCEV((const SCEV *)isl_id_get_user(Id));
+
+    isl_id_free(Id);
+  }
+
+  // Generate values for the current loop iteration for all surrounding loops.
+  //
+  // We may also reference loops outside of the scop which do not contain the
+  // scop itself, but as the number of such scops may be arbitrarily large we do
+  // not generate code for them here, but only at the point of code generation
+  // where these values are needed.
+  Region &R = S.getRegion();
+  Loop *L = LI.getLoopFor(R.getEntry());
+
+  while (L != nullptr && R.contains(L))
+    L = L->getParentLoop();
+
+  while (L != nullptr) {
+    const SCEV *OuterLIV = SE.getAddRecExpr(SE.getUnknown(Builder.getInt64(0)),
+                                            SE.getUnknown(Builder.getInt64(1)),
+                                            L, SCEV::FlagAnyWrap);
+    Value *V = generateSCEV(OuterLIV);
+    OutsideLoopIterations[L] = SE.getUnknown(V);
+    L = L->getParentLoop();
+  }
+
+  isl_set_free(Context);
+}
+
+Value *IslNodeBuilder::generateSCEV(const SCEV *Expr) {
+  Instruction *InsertLocation = --(Builder.GetInsertBlock()->end());
+  return Rewriter->expandCodeFor(Expr, cast<IntegerType>(Expr->getType()),
+                                 InsertLocation);
+}
+
+namespace {
+class IslCodeGeneration : public ScopPass {
+public:
+  static char ID;
+
+  IslCodeGeneration() : ScopPass(ID) {}
+
+  /// @brief The datalayout used
+  const DataLayout *DL;
+
+  /// @name The analysis passes we need to generate code.
+  ///
+  ///{
+  LoopInfo *LI;
+  IslAstInfo *AI;
+  DominatorTree *DT;
+  ScalarEvolution *SE;
+  ///}
+
+  /// @brief The loop annotator to generate llvm.loop metadata.
+  ScopAnnotator Annotator;
+
+  /// @brief Build the runtime condition.
+  ///
+  /// Build the condition that evaluates at run-time to true iff all
+  /// assumptions taken for the SCoP hold, and to false otherwise.
+  ///
+  /// @return A value evaluating to true/false if execution is save/unsafe.
+  Value *buildRTC(PollyIRBuilder &Builder, IslExprBuilder &ExprBuilder) {
+    Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
+    Value *RTC = ExprBuilder.create(AI->getRunCondition());
+    if (!RTC->getType()->isIntegerTy(1))
+      RTC = Builder.CreateIsNotNull(RTC);
+    return RTC;
+  }
+
+  bool runOnScop(Scop &S) {
+    LI = &getAnalysis<LoopInfo>();
+    AI = &getAnalysis<IslAstInfo>();
+    DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+    SE = &getAnalysis<ScalarEvolution>();
+    DL = &getAnalysis<DataLayoutPass>().getDataLayout();
+
+    assert(!S.getRegion().isTopLevelRegion() &&
+           "Top level regions are not supported");
+
+    // Build the alias scopes for annotations first.
+    if (PollyAnnotateAliasScopes)
+      Annotator.buildAliasScopes(S);
+
+    BasicBlock *EnteringBB = simplifyRegion(&S, this);
+    PollyIRBuilder Builder = createPollyIRBuilder(EnteringBB, Annotator);
+
+    IslNodeBuilder NodeBuilder(Builder, Annotator, this, *DL, *LI, *SE, *DT, S);
+    NodeBuilder.addParameters(S.getContext());
+
+    Value *RTC = buildRTC(Builder, NodeBuilder.getExprBuilder());
+    BasicBlock *StartBlock = executeScopConditionally(S, this, RTC);
+    Builder.SetInsertPoint(StartBlock->begin());
+
+    NodeBuilder.create(AI->getAst());
+    return true;
+  }
+
+  virtual void printScop(raw_ostream &OS) const {}
+
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.addRequired<DataLayoutPass>();
+    AU.addRequired<DominatorTreeWrapperPass>();
+    AU.addRequired<IslAstInfo>();
+    AU.addRequired<RegionInfoPass>();
+    AU.addRequired<ScalarEvolution>();
+    AU.addRequired<ScopDetection>();
+    AU.addRequired<ScopInfo>();
+    AU.addRequired<LoopInfo>();
+
+    AU.addPreserved<Dependences>();
+
+    AU.addPreserved<LoopInfo>();
+    AU.addPreserved<DominatorTreeWrapperPass>();
+    AU.addPreserved<IslAstInfo>();
+    AU.addPreserved<ScopDetection>();
+    AU.addPreserved<ScalarEvolution>();
+
+    // FIXME: We do not yet add regions for the newly generated code to the
+    //        region tree.
+    AU.addPreserved<RegionInfoPass>();
+    AU.addPreserved<TempScopInfo>();
+    AU.addPreserved<ScopInfo>();
+    AU.addPreservedID(IndependentBlocksID);
+  }
+};
+}
+
+char IslCodeGeneration::ID = 1;
+
+Pass *polly::createIslCodeGenerationPass() { return new IslCodeGeneration(); }
+
+INITIALIZE_PASS_BEGIN(IslCodeGeneration, "polly-codegen-isl",
+                      "Polly - Create LLVM-IR from SCoPs", false, false);
+INITIALIZE_PASS_DEPENDENCY(Dependences);
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
+INITIALIZE_PASS_DEPENDENCY(LoopInfo);
+INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_DEPENDENCY(ScopDetection);
+INITIALIZE_PASS_END(IslCodeGeneration, "polly-codegen-isl",
+                    "Polly - Create LLVM-IR from SCoPs", false, false)
diff --git a/final/lib/CodeGen/IslExprBuilder.cpp b/final/lib/CodeGen/IslExprBuilder.cpp
new file mode 100644
index 0000000..1dc2ba6
--- /dev/null
+++ b/final/lib/CodeGen/IslExprBuilder.cpp
@@ -0,0 +1,501 @@
+//===------ IslExprBuilder.cpp ----- Code generate isl AST expressions ----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/IslExprBuilder.h"
+
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+using namespace polly;
+
+Type *IslExprBuilder::getWidestType(Type *T1, Type *T2) {
+  assert(isa<IntegerType>(T1) && isa<IntegerType>(T2));
+
+  if (T1->getPrimitiveSizeInBits() < T2->getPrimitiveSizeInBits())
+    return T2;
+  else
+    return T1;
+}
+
+Value *IslExprBuilder::createOpUnary(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_minus &&
+         "Unsupported unary operation");
+
+  Value *V;
+  Type *MaxType = getType(Expr);
+
+  V = create(isl_ast_expr_get_op_arg(Expr, 0));
+  MaxType = getWidestType(MaxType, V->getType());
+
+  if (MaxType != V->getType())
+    V = Builder.CreateSExt(V, MaxType);
+
+  isl_ast_expr_free(Expr);
+  return Builder.CreateNSWNeg(V);
+}
+
+Value *IslExprBuilder::createOpNAry(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "isl ast expression not of type isl_ast_op");
+  assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 &&
+         "We need at least two operands in an n-ary operation");
+
+  Value *V;
+
+  V = create(isl_ast_expr_get_op_arg(Expr, 0));
+
+  for (int i = 0; i < isl_ast_expr_get_op_n_arg(Expr); ++i) {
+    Value *OpV;
+    OpV = create(isl_ast_expr_get_op_arg(Expr, i));
+
+    Type *Ty = getWidestType(V->getType(), OpV->getType());
+
+    if (Ty != OpV->getType())
+      OpV = Builder.CreateSExt(OpV, Ty);
+
+    if (Ty != V->getType())
+      V = Builder.CreateSExt(V, Ty);
+
+    switch (isl_ast_expr_get_op_type(Expr)) {
+    default:
+      llvm_unreachable("This is no n-ary isl ast expression");
+
+    case isl_ast_op_max: {
+      Value *Cmp = Builder.CreateICmpSGT(V, OpV);
+      V = Builder.CreateSelect(Cmp, V, OpV);
+      continue;
+    }
+    case isl_ast_op_min: {
+      Value *Cmp = Builder.CreateICmpSLT(V, OpV);
+      V = Builder.CreateSelect(Cmp, V, OpV);
+      continue;
+    }
+    }
+  }
+
+  // TODO: We can truncate the result, if it fits into a smaller type. This can
+  // help in cases where we have larger operands (e.g. i67) but the result is
+  // known to fit into i64. Without the truncation, the larger i67 type may
+  // force all subsequent operations to be performed on a non-native type.
+  isl_ast_expr_free(Expr);
+  return V;
+}
+
+Value *IslExprBuilder::createAccessAddress(isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "isl ast expression not of type isl_ast_op");
+  assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_access &&
+         "not an access isl ast expression");
+  assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 &&
+         "We need at least two operands to create a member access.");
+
+  Value *Base, *IndexOp, *Access;
+  isl_ast_expr *BaseExpr;
+  isl_id *BaseId;
+
+  BaseExpr = isl_ast_expr_get_op_arg(Expr, 0);
+  BaseId = isl_ast_expr_get_id(BaseExpr);
+  isl_ast_expr_free(BaseExpr);
+
+  const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(BaseId);
+  Base = SAI->getBasePtr();
+  assert(Base->getType()->isPointerTy() && "Access base should be a pointer");
+  StringRef BaseName = Base->getName();
+
+  if (Base->getType() != SAI->getType())
+    Base = Builder.CreateBitCast(Base, SAI->getType(),
+                                 "polly.access.cast." + BaseName);
+
+  IndexOp = nullptr;
+  for (unsigned u = 1, e = isl_ast_expr_get_op_n_arg(Expr); u < e; u++) {
+    Value *NextIndex = create(isl_ast_expr_get_op_arg(Expr, u));
+    assert(NextIndex->getType()->isIntegerTy() &&
+           "Access index should be an integer");
+
+    if (!IndexOp)
+      IndexOp = NextIndex;
+    else
+      IndexOp =
+          Builder.CreateAdd(IndexOp, NextIndex, "polly.access.add." + BaseName);
+
+    // For every but the last dimension multiply the size, for the last
+    // dimension we can exit the loop.
+    if (u + 1 >= e)
+      break;
+
+    const SCEV *DimSCEV = SAI->getDimensionSize(u - 1);
+    Value *DimSize = Expander.expandCodeFor(DimSCEV, DimSCEV->getType(),
+                                            Builder.GetInsertPoint());
+
+    Type *Ty = getWidestType(DimSize->getType(), IndexOp->getType());
+
+    if (Ty != IndexOp->getType())
+      IndexOp = Builder.CreateSExtOrTrunc(IndexOp, Ty,
+                                          "polly.access.sext." + BaseName);
+
+    IndexOp =
+        Builder.CreateMul(IndexOp, DimSize, "polly.access.mul." + BaseName);
+  }
+
+  Access = Builder.CreateGEP(Base, IndexOp, "polly.access." + BaseName);
+
+  isl_ast_expr_free(Expr);
+  return Access;
+}
+
+Value *IslExprBuilder::createOpAccess(isl_ast_expr *Expr) {
+  Value *Addr = createAccessAddress(Expr);
+  assert(Addr && "Could not create op access address");
+  return Builder.CreateLoad(Addr, Addr->getName() + ".load");
+}
+
+Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) {
+  Value *LHS, *RHS, *Res;
+  Type *MaxType;
+  isl_ast_op_type OpType;
+
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "isl ast expression not of type isl_ast_op");
+  assert(isl_ast_expr_get_op_n_arg(Expr) == 2 &&
+         "not a binary isl ast expression");
+
+  OpType = isl_ast_expr_get_op_type(Expr);
+
+  LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
+  RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
+
+  MaxType = LHS->getType();
+  MaxType = getWidestType(MaxType, RHS->getType());
+
+  // Take the result into account when calculating the widest type.
+  //
+  // For operations such as '+' the result may require a type larger than
+  // the type of the individual operands. For other operations such as '/', the
+  // result type cannot be larger than the type of the individual operand. isl
+  // does not calculate correct types for these operations and we consequently
+  // exclude those operations here.
+  switch (OpType) {
+  case isl_ast_op_pdiv_q:
+  case isl_ast_op_pdiv_r:
+  case isl_ast_op_div:
+  case isl_ast_op_fdiv_q:
+    // Do nothing
+    break;
+  case isl_ast_op_add:
+  case isl_ast_op_sub:
+  case isl_ast_op_mul:
+    MaxType = getWidestType(MaxType, getType(Expr));
+    break;
+  default:
+    llvm_unreachable("This is no binary isl ast expression");
+  }
+
+  if (MaxType != RHS->getType())
+    RHS = Builder.CreateSExt(RHS, MaxType);
+
+  if (MaxType != LHS->getType())
+    LHS = Builder.CreateSExt(LHS, MaxType);
+
+  switch (OpType) {
+  default:
+    llvm_unreachable("This is no binary isl ast expression");
+  case isl_ast_op_add:
+    Res = Builder.CreateNSWAdd(LHS, RHS);
+    break;
+  case isl_ast_op_sub:
+    Res = Builder.CreateNSWSub(LHS, RHS);
+    break;
+  case isl_ast_op_mul:
+    Res = Builder.CreateNSWMul(LHS, RHS);
+    break;
+  case isl_ast_op_div:
+  case isl_ast_op_pdiv_q: // Dividend is non-negative
+    Res = Builder.CreateSDiv(LHS, RHS);
+    break;
+  case isl_ast_op_fdiv_q: { // Round towards -infty
+    // TODO: Review code and check that this calculation does not yield
+    //       incorrect overflow in some bordercases.
+    //
+    // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
+    Value *One = ConstantInt::get(MaxType, 1);
+    Value *Zero = ConstantInt::get(MaxType, 0);
+    Value *Sum1 = Builder.CreateSub(LHS, RHS);
+    Value *Sum2 = Builder.CreateAdd(Sum1, One);
+    Value *isNegative = Builder.CreateICmpSLT(LHS, Zero);
+    Value *Dividend = Builder.CreateSelect(isNegative, Sum2, LHS);
+    Res = Builder.CreateSDiv(Dividend, RHS);
+    break;
+  }
+  case isl_ast_op_pdiv_r: // Dividend is non-negative
+    Res = Builder.CreateSRem(LHS, RHS);
+    break;
+  }
+
+  // TODO: We can truncate the result, if it fits into a smaller type. This can
+  // help in cases where we have larger operands (e.g. i67) but the result is
+  // known to fit into i64. Without the truncation, the larger i67 type may
+  // force all subsequent operations to be performed on a non-native type.
+  isl_ast_expr_free(Expr);
+  return Res;
+}
+
+Value *IslExprBuilder::createOpSelect(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_select &&
+         "Unsupported unary isl ast expression");
+  Value *LHS, *RHS, *Cond;
+  Type *MaxType = getType(Expr);
+
+  Cond = create(isl_ast_expr_get_op_arg(Expr, 0));
+  if (!Cond->getType()->isIntegerTy(1))
+    Cond = Builder.CreateIsNotNull(Cond);
+
+  LHS = create(isl_ast_expr_get_op_arg(Expr, 1));
+  RHS = create(isl_ast_expr_get_op_arg(Expr, 2));
+
+  MaxType = getWidestType(MaxType, LHS->getType());
+  MaxType = getWidestType(MaxType, RHS->getType());
+
+  if (MaxType != RHS->getType())
+    RHS = Builder.CreateSExt(RHS, MaxType);
+
+  if (MaxType != LHS->getType())
+    LHS = Builder.CreateSExt(LHS, MaxType);
+
+  // TODO: Do we want to truncate the result?
+  isl_ast_expr_free(Expr);
+  return Builder.CreateSelect(Cond, LHS, RHS);
+}
+
+Value *IslExprBuilder::createOpICmp(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "Expected an isl_ast_expr_op expression");
+
+  Value *LHS, *RHS, *Res;
+
+  LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
+  RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
+
+  bool IsPtrType = LHS->getType()->isPointerTy();
+  assert((!IsPtrType || RHS->getType()->isPointerTy()) &&
+         "Both ICmp operators should be pointer types or none of them");
+
+  if (LHS->getType() != RHS->getType()) {
+    if (IsPtrType) {
+      Type *I8PtrTy = Builder.getInt8PtrTy();
+      if (LHS->getType() != I8PtrTy)
+        LHS = Builder.CreateBitCast(LHS, I8PtrTy);
+      if (RHS->getType() != I8PtrTy)
+        RHS = Builder.CreateBitCast(RHS, I8PtrTy);
+    } else {
+      Type *MaxType = LHS->getType();
+      MaxType = getWidestType(MaxType, RHS->getType());
+
+      if (MaxType != RHS->getType())
+        RHS = Builder.CreateSExt(RHS, MaxType);
+
+      if (MaxType != LHS->getType())
+        LHS = Builder.CreateSExt(LHS, MaxType);
+    }
+  }
+
+  isl_ast_op_type OpType = isl_ast_expr_get_op_type(Expr);
+  assert(OpType >= isl_ast_op_eq && OpType <= isl_ast_op_gt &&
+         "Unsupported ICmp isl ast expression");
+  assert(isl_ast_op_eq + 4 == isl_ast_op_gt &&
+         "Isl ast op type interface changed");
+
+  CmpInst::Predicate Predicates[5][2] = {
+      {CmpInst::ICMP_EQ, CmpInst::ICMP_EQ},
+      {CmpInst::ICMP_SLE, CmpInst::ICMP_ULE},
+      {CmpInst::ICMP_SLT, CmpInst::ICMP_ULT},
+      {CmpInst::ICMP_SGE, CmpInst::ICMP_UGE},
+      {CmpInst::ICMP_SGT, CmpInst::ICMP_UGT},
+  };
+
+  Res = Builder.CreateICmp(Predicates[OpType - isl_ast_op_eq][IsPtrType], LHS,
+                           RHS);
+
+  isl_ast_expr_free(Expr);
+  return Res;
+}
+
+Value *IslExprBuilder::createOpBoolean(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "Expected an isl_ast_expr_op expression");
+
+  Value *LHS, *RHS, *Res;
+  isl_ast_op_type OpType;
+
+  OpType = isl_ast_expr_get_op_type(Expr);
+
+  assert((OpType == isl_ast_op_and || OpType == isl_ast_op_or) &&
+         "Unsupported isl_ast_op_type");
+
+  LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
+  RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
+
+  // Even though the isl pretty printer prints the expressions as 'exp && exp'
+  // or 'exp || exp', we actually code generate the bitwise expressions
+  // 'exp & exp' or 'exp | exp'. This forces the evaluation of both branches,
+  // but it is, due to the use of i1 types, otherwise equivalent. The reason
+  // to go for bitwise operations is, that we assume the reduced control flow
+  // will outweight the overhead introduced by evaluating unneeded expressions.
+  // The isl code generation currently does not take advantage of the fact that
+  // the expression after an '||' or '&&' is in some cases not evaluated.
+  // Evaluating it anyways does not cause any undefined behaviour.
+  //
+  // TODO: Document in isl itself, that the unconditionally evaluating the
+  // second part of '||' or '&&' expressions is safe.
+  if (!LHS->getType()->isIntegerTy(1))
+    LHS = Builder.CreateIsNotNull(LHS);
+  if (!RHS->getType()->isIntegerTy(1))
+    RHS = Builder.CreateIsNotNull(RHS);
+
+  switch (OpType) {
+  default:
+    llvm_unreachable("Unsupported boolean expression");
+  case isl_ast_op_and:
+    Res = Builder.CreateAnd(LHS, RHS);
+    break;
+  case isl_ast_op_or:
+    Res = Builder.CreateOr(LHS, RHS);
+    break;
+  }
+
+  isl_ast_expr_free(Expr);
+  return Res;
+}
+
+Value *IslExprBuilder::createOp(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "Expression not of type isl_ast_expr_op");
+  switch (isl_ast_expr_get_op_type(Expr)) {
+  case isl_ast_op_error:
+  case isl_ast_op_cond:
+  case isl_ast_op_and_then:
+  case isl_ast_op_or_else:
+  case isl_ast_op_call:
+  case isl_ast_op_member:
+    llvm_unreachable("Unsupported isl ast expression");
+  case isl_ast_op_access:
+    return createOpAccess(Expr);
+  case isl_ast_op_max:
+  case isl_ast_op_min:
+    return createOpNAry(Expr);
+  case isl_ast_op_add:
+  case isl_ast_op_sub:
+  case isl_ast_op_mul:
+  case isl_ast_op_div:
+  case isl_ast_op_fdiv_q: // Round towards -infty
+  case isl_ast_op_pdiv_q: // Dividend is non-negative
+  case isl_ast_op_pdiv_r: // Dividend is non-negative
+    return createOpBin(Expr);
+  case isl_ast_op_minus:
+    return createOpUnary(Expr);
+  case isl_ast_op_select:
+    return createOpSelect(Expr);
+  case isl_ast_op_and:
+  case isl_ast_op_or:
+    return createOpBoolean(Expr);
+  case isl_ast_op_eq:
+  case isl_ast_op_le:
+  case isl_ast_op_lt:
+  case isl_ast_op_ge:
+  case isl_ast_op_gt:
+    return createOpICmp(Expr);
+  case isl_ast_op_address_of:
+    return createOpAddressOf(Expr);
+  }
+
+  llvm_unreachable("Unsupported isl_ast_expr_op kind.");
+}
+
+Value *IslExprBuilder::createOpAddressOf(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
+         "Expected an isl_ast_expr_op expression.");
+  assert(isl_ast_expr_get_op_n_arg(Expr) == 1 && "Address of should be unary.");
+
+  isl_ast_expr *Op = isl_ast_expr_get_op_arg(Expr, 0);
+  assert(isl_ast_expr_get_type(Op) == isl_ast_expr_op &&
+         "Expected address of operator to be an isl_ast_expr_op expression.");
+  assert(isl_ast_expr_get_op_type(Op) == isl_ast_op_access &&
+         "Expected address of operator to be an access expression.");
+
+  Value *V = createAccessAddress(Op);
+
+  isl_ast_expr_free(Expr);
+
+  return V;
+}
+
+Value *IslExprBuilder::createId(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_id &&
+         "Expression not of type isl_ast_expr_ident");
+
+  isl_id *Id;
+  Value *V;
+
+  Id = isl_ast_expr_get_id(Expr);
+
+  assert(IDToValue.count(Id) && "Identifier not found");
+
+  V = IDToValue[Id];
+
+  isl_id_free(Id);
+  isl_ast_expr_free(Expr);
+
+  return V;
+}
+
+IntegerType *IslExprBuilder::getType(__isl_keep isl_ast_expr *Expr) {
+  // XXX: We assume i64 is large enough. This is often true, but in general
+  //      incorrect. Also, on 32bit architectures, it would be beneficial to
+  //      use a smaller type. We can and should directly derive this information
+  //      during code generation.
+  return IntegerType::get(Builder.getContext(), 64);
+}
+
+Value *IslExprBuilder::createInt(__isl_take isl_ast_expr *Expr) {
+  assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_int &&
+         "Expression not of type isl_ast_expr_int");
+  isl_val *Val;
+  Value *V;
+  APInt APValue;
+  IntegerType *T;
+
+  Val = isl_ast_expr_get_val(Expr);
+  APValue = APIntFromVal(Val);
+  T = getType(Expr);
+  APValue = APValue.sextOrSelf(T->getBitWidth());
+  V = ConstantInt::get(T, APValue);
+
+  isl_ast_expr_free(Expr);
+  return V;
+}
+
+Value *IslExprBuilder::create(__isl_take isl_ast_expr *Expr) {
+  switch (isl_ast_expr_get_type(Expr)) {
+  case isl_ast_expr_error:
+    llvm_unreachable("Code generation error");
+  case isl_ast_expr_op:
+    return createOp(Expr);
+  case isl_ast_expr_id:
+    return createId(Expr);
+  case isl_ast_expr_int:
+    return createInt(Expr);
+  }
+
+  llvm_unreachable("Unexpected enum value");
+}
diff --git a/final/lib/CodeGen/LoopGenerators.cpp b/final/lib/CodeGen/LoopGenerators.cpp
new file mode 100644
index 0000000..af04137
--- /dev/null
+++ b/final/lib/CodeGen/LoopGenerators.cpp
@@ -0,0 +1,377 @@
+//===------ LoopGenerators.cpp -  IR helper to create loops ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions to create scalar and parallel loops as LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/ScopDetection.h"
+#include "polly/CodeGen/LoopGenerators.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace polly;
+
+static cl::opt<int>
+    PollyNumThreads("polly-num-threads",
+                    cl::desc("Number of threads to use (0 = auto)"), cl::Hidden,
+                    cl::init(0));
+
+// We generate a loop of either of the following structures:
+//
+//              BeforeBB                      BeforeBB
+//                 |                             |
+//                 v                             v
+//              GuardBB                      PreHeaderBB
+//              /      |                         |   _____
+//     __  PreHeaderBB  |                        v  \/    |
+//    /  \    /         |                     HeaderBB  latch
+// latch  HeaderBB      |                        |\       |
+//    \  /    \         /                        | \------/
+//     <       \       /                         |
+//              \     /                          v
+//              ExitBB                         ExitBB
+//
+// depending on whether or not we know that it is executed at least once. If
+// not, GuardBB checks if the loop is executed at least once. If this is the
+// case we branch to PreHeaderBB and subsequently to the HeaderBB, which
+// contains the loop iv 'polly.indvar', the incremented loop iv
+// 'polly.indvar_next' as well as the condition to check if we execute another
+// iteration of the loop. After the loop has finished, we branch to ExitBB.
+Value *polly::createLoop(Value *LB, Value *UB, Value *Stride,
+                         PollyIRBuilder &Builder, Pass *P, LoopInfo &LI,
+                         DominatorTree &DT, BasicBlock *&ExitBB,
+                         ICmpInst::Predicate Predicate,
+                         ScopAnnotator *Annotator, bool Parallel,
+                         bool UseGuard) {
+  Function *F = Builder.GetInsertBlock()->getParent();
+  LLVMContext &Context = F->getContext();
+
+  assert(LB->getType() == UB->getType() && "Types of loop bounds do not match");
+  IntegerType *LoopIVType = dyn_cast<IntegerType>(UB->getType());
+  assert(LoopIVType && "UB is not integer?");
+
+  BasicBlock *BeforeBB = Builder.GetInsertBlock();
+  BasicBlock *GuardBB =
+      UseGuard ? BasicBlock::Create(Context, "polly.loop_if", F) : nullptr;
+  BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F);
+  BasicBlock *PreHeaderBB =
+      BasicBlock::Create(Context, "polly.loop_preheader", F);
+
+  // Update LoopInfo
+  Loop *OuterLoop = LI.getLoopFor(BeforeBB);
+  Loop *NewLoop = new Loop();
+
+  if (OuterLoop)
+    OuterLoop->addChildLoop(NewLoop);
+  else
+    LI.addTopLevelLoop(NewLoop);
+
+  if (OuterLoop) {
+    if (GuardBB)
+      OuterLoop->addBasicBlockToLoop(GuardBB, LI.getBase());
+    OuterLoop->addBasicBlockToLoop(PreHeaderBB, LI.getBase());
+  }
+
+  NewLoop->addBasicBlockToLoop(HeaderBB, LI.getBase());
+
+  // Notify the annotator (if present) that we have a new loop, but only
+  // after the header block is set.
+  if (Annotator)
+    Annotator->pushLoop(NewLoop, Parallel);
+
+  // ExitBB
+  ExitBB = SplitBlock(BeforeBB, Builder.GetInsertPoint()++, P);
+  ExitBB->setName("polly.loop_exit");
+
+  // BeforeBB
+  if (GuardBB) {
+    BeforeBB->getTerminator()->setSuccessor(0, GuardBB);
+    DT.addNewBlock(GuardBB, BeforeBB);
+
+    // GuardBB
+    Builder.SetInsertPoint(GuardBB);
+    Value *LoopGuard;
+    LoopGuard = Builder.CreateICmp(Predicate, LB, UB);
+    LoopGuard->setName("polly.loop_guard");
+    Builder.CreateCondBr(LoopGuard, PreHeaderBB, ExitBB);
+    DT.addNewBlock(PreHeaderBB, GuardBB);
+  } else {
+    BeforeBB->getTerminator()->setSuccessor(0, PreHeaderBB);
+    DT.addNewBlock(PreHeaderBB, BeforeBB);
+  }
+
+  // PreHeaderBB
+  Builder.SetInsertPoint(PreHeaderBB);
+  Builder.CreateBr(HeaderBB);
+
+  // HeaderBB
+  DT.addNewBlock(HeaderBB, PreHeaderBB);
+  Builder.SetInsertPoint(HeaderBB);
+  PHINode *IV = Builder.CreatePHI(LoopIVType, 2, "polly.indvar");
+  IV->addIncoming(LB, PreHeaderBB);
+  Stride = Builder.CreateZExtOrBitCast(Stride, LoopIVType);
+  Value *IncrementedIV = Builder.CreateNSWAdd(IV, Stride, "polly.indvar_next");
+  Value *LoopCondition;
+  UB = Builder.CreateSub(UB, Stride, "polly.adjust_ub");
+  LoopCondition = Builder.CreateICmp(Predicate, IV, UB);
+  LoopCondition->setName("polly.loop_cond");
+
+  // Create the loop latch and annotate it as such.
+  BranchInst *B = Builder.CreateCondBr(LoopCondition, HeaderBB, ExitBB);
+  if (Annotator)
+    Annotator->annotateLoopLatch(B, NewLoop, Parallel);
+
+  IV->addIncoming(IncrementedIV, HeaderBB);
+  if (GuardBB)
+    DT.changeImmediateDominator(ExitBB, GuardBB);
+  else
+    DT.changeImmediateDominator(ExitBB, HeaderBB);
+
+  // The loop body should be added here.
+  Builder.SetInsertPoint(HeaderBB->getFirstNonPHI());
+  return IV;
+}
+
+Value *ParallelLoopGenerator::createParallelLoop(
+    Value *LB, Value *UB, Value *Stride, SetVector<Value *> &UsedValues,
+    ValueToValueMapTy &Map, BasicBlock::iterator *LoopBody) {
+  Value *Struct, *IV, *SubFnParam;
+  Function *SubFn;
+
+  Struct = storeValuesIntoStruct(UsedValues);
+
+  BasicBlock::iterator BeforeLoop = Builder.GetInsertPoint();
+  IV = createSubFn(Stride, Struct, UsedValues, Map, &SubFn);
+  *LoopBody = Builder.GetInsertPoint();
+  Builder.SetInsertPoint(BeforeLoop);
+
+  SubFnParam = Builder.CreateBitCast(Struct, Builder.getInt8PtrTy(),
+                                     "polly.par.userContext");
+
+  // Add one as the upper bound provided by openmp is a < comparison
+  // whereas the codegenForSequential function creates a <= comparison.
+  UB = Builder.CreateAdd(UB, ConstantInt::get(LongType, 1));
+
+  // Tell the runtime we start a parallel loop
+  createCallSpawnThreads(SubFn, SubFnParam, LB, UB, Stride);
+  Builder.CreateCall(SubFn, SubFnParam);
+  createCallJoinThreads();
+
+  // Mark the end of the lifetime for the parameter struct.
+  Type *Ty = Struct->getType();
+  ConstantInt *SizeOf = Builder.getInt64(DL.getTypeAllocSize(Ty));
+  Builder.CreateLifetimeEnd(Struct, SizeOf);
+
+  return IV;
+}
+
+void ParallelLoopGenerator::createCallSpawnThreads(Value *SubFn,
+                                                   Value *SubFnParam, Value *LB,
+                                                   Value *UB, Value *Stride) {
+  const std::string Name = "GOMP_parallel_loop_runtime_start";
+
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+    Type *Params[] = {PointerType::getUnqual(FunctionType::get(
+                          Builder.getVoidTy(), Builder.getInt8PtrTy(), false)),
+                      Builder.getInt8PtrTy(), Builder.getInt32Ty(), LongType,
+                      LongType, LongType};
+
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Value *NumberOfThreads = Builder.getInt32(PollyNumThreads);
+  Value *Args[] = {SubFn, SubFnParam, NumberOfThreads, LB, UB, Stride};
+
+  Builder.CreateCall(F, Args);
+}
+
+Value *ParallelLoopGenerator::createCallGetWorkItem(Value *LBPtr,
+                                                    Value *UBPtr) {
+  const std::string Name = "GOMP_loop_runtime_next";
+
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    Type *Params[] = {LongType->getPointerTo(), LongType->getPointerTo()};
+    FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Value *Args[] = {LBPtr, UBPtr};
+  Value *Return = Builder.CreateCall(F, Args);
+  Return = Builder.CreateICmpNE(
+      Return, Builder.CreateZExt(Builder.getFalse(), Return->getType()));
+  return Return;
+}
+
+void ParallelLoopGenerator::createCallJoinThreads() {
+  const std::string Name = "GOMP_parallel_end";
+
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall(F);
+}
+
+void ParallelLoopGenerator::createCallCleanupThread() {
+  const std::string Name = "GOMP_loop_end_nowait";
+
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall(F);
+}
+
+Function *ParallelLoopGenerator::createSubFnDefinition() {
+  Function *F = Builder.GetInsertBlock()->getParent();
+  std::vector<Type *> Arguments(1, Builder.getInt8PtrTy());
+  FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
+  Function *SubFn = Function::Create(FT, Function::InternalLinkage,
+                                     F->getName() + ".polly.subfn", M);
+
+  // Do not run any polly pass on the new function.
+  SubFn->addFnAttr(PollySkipFnAttr);
+
+  Function::arg_iterator AI = SubFn->arg_begin();
+  AI->setName("polly.par.userContext");
+
+  return SubFn;
+}
+
+Value *
+ParallelLoopGenerator::storeValuesIntoStruct(SetVector<Value *> &Values) {
+  SmallVector<Type *, 8> Members;
+
+  for (Value *V : Values)
+    Members.push_back(V->getType());
+
+  // We do not want to allocate the alloca inside any loop, thus we allocate it
+  // in the entry block of the function and use annotations to denote the actual
+  // live span (similar to clang).
+  BasicBlock &EntryBB = Builder.GetInsertBlock()->getParent()->getEntryBlock();
+  Instruction *IP = EntryBB.getFirstInsertionPt();
+  StructType *Ty = StructType::get(Builder.getContext(), Members);
+  Value *Struct = new AllocaInst(Ty, 0, "polly.par.userContext", IP);
+
+  // Mark the start of the lifetime for the parameter struct.
+  ConstantInt *SizeOf = Builder.getInt64(DL.getTypeAllocSize(Ty));
+  Builder.CreateLifetimeStart(Struct, SizeOf);
+
+  for (unsigned i = 0; i < Values.size(); i++) {
+    Value *Address = Builder.CreateStructGEP(Struct, i);
+    Builder.CreateStore(Values[i], Address);
+  }
+
+  return Struct;
+}
+
+void ParallelLoopGenerator::extractValuesFromStruct(
+    SetVector<Value *> OldValues, Value *Struct, ValueToValueMapTy &Map) {
+  for (unsigned i = 0; i < OldValues.size(); i++) {
+    Value *Address = Builder.CreateStructGEP(Struct, i);
+    Value *NewValue = Builder.CreateLoad(Address);
+    Map[OldValues[i]] = NewValue;
+  }
+}
+
+Value *ParallelLoopGenerator::createSubFn(Value *Stride, Value *StructData,
+                                          SetVector<Value *> Data,
+                                          ValueToValueMapTy &Map,
+                                          Function **SubFnPtr) {
+  BasicBlock *PrevBB, *HeaderBB, *ExitBB, *CheckNextBB, *PreHeaderBB, *AfterBB;
+  Value *LBPtr, *UBPtr, *UserContext, *Ret1, *HasNextSchedule, *LB, *UB, *IV;
+  Function *SubFn = createSubFnDefinition();
+  LLVMContext &Context = SubFn->getContext();
+
+  // Store the previous basic block.
+  PrevBB = Builder.GetInsertBlock();
+
+  // Create basic blocks.
+  HeaderBB = BasicBlock::Create(Context, "polly.par.setup", SubFn);
+  ExitBB = BasicBlock::Create(Context, "polly.par.exit", SubFn);
+  CheckNextBB = BasicBlock::Create(Context, "polly.par.checkNext", SubFn);
+  PreHeaderBB = BasicBlock::Create(Context, "polly.par.loadIVBounds", SubFn);
+
+  DT.addNewBlock(HeaderBB, PrevBB);
+  DT.addNewBlock(ExitBB, HeaderBB);
+  DT.addNewBlock(CheckNextBB, HeaderBB);
+  DT.addNewBlock(PreHeaderBB, HeaderBB);
+
+  // Fill up basic block HeaderBB.
+  Builder.SetInsertPoint(HeaderBB);
+  LBPtr = Builder.CreateAlloca(LongType, 0, "polly.par.LBPtr");
+  UBPtr = Builder.CreateAlloca(LongType, 0, "polly.par.UBPtr");
+  UserContext = Builder.CreateBitCast(SubFn->arg_begin(), StructData->getType(),
+                                      "polly.par.userContext");
+
+  extractValuesFromStruct(Data, UserContext, Map);
+  Builder.CreateBr(CheckNextBB);
+
+  // Add code to check if another set of iterations will be executed.
+  Builder.SetInsertPoint(CheckNextBB);
+  Ret1 = createCallGetWorkItem(LBPtr, UBPtr);
+  HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(),
+                                        "polly.par.hasNextScheduleBlock");
+  Builder.CreateCondBr(HasNextSchedule, PreHeaderBB, ExitBB);
+
+  // Add code to to load the iv bounds for this set of iterations.
+  Builder.SetInsertPoint(PreHeaderBB);
+  LB = Builder.CreateLoad(LBPtr, "polly.par.LB");
+  UB = Builder.CreateLoad(UBPtr, "polly.par.UB");
+
+  // Subtract one as the upper bound provided by openmp is a < comparison
+  // whereas the codegenForSequential function creates a <= comparison.
+  UB = Builder.CreateSub(UB, ConstantInt::get(LongType, 1),
+                         "polly.par.UBAdjusted");
+
+  Builder.CreateBr(CheckNextBB);
+  Builder.SetInsertPoint(--Builder.GetInsertPoint());
+  IV = createLoop(LB, UB, Stride, Builder, P, LI, DT, AfterBB,
+                  ICmpInst::ICMP_SLE, nullptr, true, /* UseGuard */ false);
+
+  BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
+
+  // Add code to terminate this subfunction.
+  Builder.SetInsertPoint(ExitBB);
+  createCallCleanupThread();
+  Builder.CreateRetVoid();
+
+  Builder.SetInsertPoint(LoopBody);
+  *SubFnPtr = SubFn;
+
+  return IV;
+}
diff --git a/final/lib/CodeGen/PTXGenerator.cpp b/final/lib/CodeGen/PTXGenerator.cpp
new file mode 100644
index 0000000..16da662
--- /dev/null
+++ b/final/lib/CodeGen/PTXGenerator.cpp
@@ -0,0 +1,712 @@
+//===------ PTXGenerator.cpp -  IR helper to create loops -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions to create GPU parallel codes as LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/PTXGenerator.h"
+
+#ifdef GPU_CODEGEN
+#include "polly/ScopDetection.h"
+#include "polly/ScopInfo.h"
+
+#include "llvm/PassManager.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Target/TargetLibraryInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+using namespace llvm;
+using namespace polly;
+
+PTXGenerator::PTXGenerator(PollyIRBuilder &Builder, Pass *P,
+                           const std::string &Triple)
+    : Builder(Builder), P(P), GPUTriple(Triple), GridWidth(1), GridHeight(1),
+      BlockWidth(1), BlockHeight(1), OutputBytes(0) {
+  InitializeGPUDataTypes();
+}
+
+Module *PTXGenerator::getModule() {
+  return Builder.GetInsertBlock()->getParent()->getParent();
+}
+
+Function *PTXGenerator::createSubfunctionDefinition(int NumArgs) {
+  assert(NumArgs == 1 && "we support only one array access now.");
+
+  Module *M = getModule();
+  Function *F = Builder.GetInsertBlock()->getParent();
+  std::vector<Type *> Arguments;
+  for (int i = 0; i < NumArgs; i++)
+    Arguments.push_back(Builder.getInt8PtrTy());
+  FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
+  Function *FN = Function::Create(FT, Function::InternalLinkage,
+                                  F->getName() + "_ptx_subfn", M);
+  FN->setCallingConv(CallingConv::PTX_Kernel);
+
+  // Do not run any optimization pass on the new function.
+  P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN);
+
+  for (Function::arg_iterator AI = FN->arg_begin(); AI != FN->arg_end(); ++AI)
+    AI->setName("ptx.Array");
+
+  return FN;
+}
+
+void PTXGenerator::createSubfunction(SetVector<Value *> &UsedValues,
+                                     SetVector<Value *> &OriginalIVS,
+                                     PTXGenerator::ValueToValueMapTy &VMap,
+                                     Function **SubFunction) {
+  Function *FN = createSubfunctionDefinition(UsedValues.size());
+  Module *M = getModule();
+  LLVMContext &Context = FN->getContext();
+  IntegerType *Ty = Builder.getInt64Ty();
+
+  // Store the previous basic block.
+  BasicBlock *PrevBB = Builder.GetInsertBlock();
+
+  // Create basic blocks.
+  BasicBlock *HeaderBB = BasicBlock::Create(Context, "ptx.setup", FN);
+  BasicBlock *ExitBB = BasicBlock::Create(Context, "ptx.exit", FN);
+  BasicBlock *BodyBB = BasicBlock::Create(Context, "ptx.loop_body", FN);
+
+  DominatorTree &DT = P->getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+  DT.addNewBlock(HeaderBB, PrevBB);
+  DT.addNewBlock(ExitBB, HeaderBB);
+  DT.addNewBlock(BodyBB, HeaderBB);
+
+  Builder.SetInsertPoint(HeaderBB);
+
+  // Insert VMap items with maps of array base address on the host to base
+  // address on the device.
+  Function::arg_iterator AI = FN->arg_begin();
+  for (unsigned j = 0; j < UsedValues.size(); j++) {
+    Value *BaseAddr = UsedValues[j];
+    Type *ArrayTy = BaseAddr->getType();
+    Value *Param = Builder.CreateBitCast(AI, ArrayTy);
+    VMap.insert(std::make_pair(BaseAddr, Param));
+    AI++;
+  }
+
+  // FIXME: These intrinsics should be inserted on-demand. However, we insert
+  // them all currently for simplicity.
+  Function *GetNctaidX =
+      Intrinsic::getDeclaration(M, Intrinsic::ptx_read_nctaid_x);
+  Function *GetNctaidY =
+      Intrinsic::getDeclaration(M, Intrinsic::ptx_read_nctaid_y);
+  Function *GetCtaidX =
+      Intrinsic::getDeclaration(M, Intrinsic::ptx_read_ctaid_x);
+  Function *GetCtaidY =
+      Intrinsic::getDeclaration(M, Intrinsic::ptx_read_ctaid_y);
+  Function *GetNtidX = Intrinsic::getDeclaration(M, Intrinsic::ptx_read_ntid_x);
+  Function *GetNtidY = Intrinsic::getDeclaration(M, Intrinsic::ptx_read_ntid_y);
+  Function *GetTidX = Intrinsic::getDeclaration(M, Intrinsic::ptx_read_tid_x);
+  Function *GetTidY = Intrinsic::getDeclaration(M, Intrinsic::ptx_read_tid_y);
+
+  Value *GridWidth = Builder.CreateCall(GetNctaidX);
+  GridWidth = Builder.CreateIntCast(GridWidth, Ty, false);
+  Value *GridHeight = Builder.CreateCall(GetNctaidY);
+  GridHeight = Builder.CreateIntCast(GridHeight, Ty, false);
+  Value *BlockWidth = Builder.CreateCall(GetNtidX);
+  BlockWidth = Builder.CreateIntCast(BlockWidth, Ty, false);
+  Value *BlockHeight = Builder.CreateCall(GetNtidY);
+  BlockHeight = Builder.CreateIntCast(BlockHeight, Ty, false);
+  Value *BIDx = Builder.CreateCall(GetCtaidX);
+  BIDx = Builder.CreateIntCast(BIDx, Ty, false);
+  Value *BIDy = Builder.CreateCall(GetCtaidY);
+  BIDy = Builder.CreateIntCast(BIDy, Ty, false);
+  Value *TIDx = Builder.CreateCall(GetTidX);
+  TIDx = Builder.CreateIntCast(TIDx, Ty, false);
+  Value *TIDy = Builder.CreateCall(GetTidY);
+  TIDy = Builder.CreateIntCast(TIDy, Ty, false);
+
+  Builder.CreateBr(BodyBB);
+  Builder.SetInsertPoint(BodyBB);
+
+  unsigned NumDims = OriginalIVS.size();
+  std::vector<Value *> Substitutions;
+  Value *BlockID, *ThreadID;
+  switch (NumDims) {
+  case 1: {
+    Value *BlockSize =
+        Builder.CreateMul(BlockWidth, BlockHeight, "p_gpu_blocksize");
+    BlockID = Builder.CreateMul(BIDy, GridWidth, "p_gpu_index_i");
+    BlockID = Builder.CreateAdd(BlockID, BIDx);
+    BlockID = Builder.CreateMul(BlockID, BlockSize);
+    ThreadID = Builder.CreateMul(TIDy, BlockWidth, "p_gpu_index_j");
+    ThreadID = Builder.CreateAdd(ThreadID, TIDx);
+    ThreadID = Builder.CreateAdd(ThreadID, BlockID);
+    Substitutions.push_back(ThreadID);
+    break;
+  }
+  case 2: {
+    BlockID = Builder.CreateMul(BIDy, GridWidth, "p_gpu_index_i");
+    BlockID = Builder.CreateAdd(BlockID, BIDx);
+    Substitutions.push_back(BlockID);
+    ThreadID = Builder.CreateMul(TIDy, BlockWidth, "p_gpu_index_j");
+    ThreadID = Builder.CreateAdd(ThreadID, TIDx);
+    Substitutions.push_back(ThreadID);
+    break;
+  }
+  case 3: {
+    BlockID = Builder.CreateMul(BIDy, GridWidth, "p_gpu_index_i");
+    BlockID = Builder.CreateAdd(BlockID, BIDx);
+    Substitutions.push_back(BlockID);
+    Substitutions.push_back(TIDy);
+    Substitutions.push_back(TIDx);
+    break;
+  }
+  case 4: {
+    Substitutions.push_back(BIDy);
+    Substitutions.push_back(BIDx);
+    Substitutions.push_back(TIDy);
+    Substitutions.push_back(TIDx);
+    break;
+  }
+  default:
+    assert(true &&
+           "We cannot transform parallel loops whose depth is larger than 4.");
+    return;
+  }
+
+  assert(OriginalIVS.size() == Substitutions.size() &&
+         "The size of IVS should be equal to the size of substitutions.");
+  for (unsigned i = 0; i < OriginalIVS.size(); ++i) {
+    VMap.insert(std::make_pair(OriginalIVS[i], Substitutions[i]));
+  }
+
+  Builder.CreateBr(ExitBB);
+  Builder.SetInsertPoint(--Builder.GetInsertPoint());
+  BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
+
+  // Add the termination of the ptx-device subfunction.
+  Builder.SetInsertPoint(ExitBB);
+  Builder.CreateRetVoid();
+
+  Builder.SetInsertPoint(LoopBody);
+  *SubFunction = FN;
+}
+
+void PTXGenerator::startGeneration(SetVector<Value *> &UsedValues,
+                                   SetVector<Value *> &OriginalIVS,
+                                   ValueToValueMapTy &VMap,
+                                   BasicBlock::iterator *LoopBody) {
+  Function *SubFunction;
+  BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint();
+  createSubfunction(UsedValues, OriginalIVS, VMap, &SubFunction);
+  *LoopBody = Builder.GetInsertPoint();
+  Builder.SetInsertPoint(PrevInsertPoint);
+}
+
+IntegerType *PTXGenerator::getInt64Type() { return Builder.getInt64Ty(); }
+
+PointerType *PTXGenerator::getI8PtrType() {
+  return PointerType::getUnqual(Builder.getInt8Ty());
+}
+
+PointerType *PTXGenerator::getPtrI8PtrType() {
+  return PointerType::getUnqual(getI8PtrType());
+}
+
+PointerType *PTXGenerator::getFloatPtrType() {
+  return llvm::Type::getFloatPtrTy(getModule()->getContext());
+}
+
+PointerType *PTXGenerator::getGPUContextPtrType() {
+  return PointerType::getUnqual(ContextTy);
+}
+
+PointerType *PTXGenerator::getGPUModulePtrType() {
+  return PointerType::getUnqual(ModuleTy);
+}
+
+PointerType *PTXGenerator::getGPUDevicePtrType() {
+  return PointerType::getUnqual(DeviceTy);
+}
+
+PointerType *PTXGenerator::getPtrGPUDevicePtrType() {
+  return PointerType::getUnqual(DevDataTy);
+}
+
+PointerType *PTXGenerator::getGPUFunctionPtrType() {
+  return PointerType::getUnqual(KernelTy);
+}
+
+PointerType *PTXGenerator::getGPUEventPtrType() {
+  return PointerType::getUnqual(EventTy);
+}
+
+void PTXGenerator::InitializeGPUDataTypes() {
+  LLVMContext &Context = getModule()->getContext();
+
+  ContextTy = StructType::create(Context, "struct.PollyGPUContextT");
+  ModuleTy = StructType::create(Context, "struct.PollyGPUModuleT");
+  KernelTy = StructType::create(Context, "struct.PollyGPUFunctionT");
+  DeviceTy = StructType::create(Context, "struct.PollyGPUDeviceT");
+  DevDataTy = StructType::create(Context, "struct.PollyGPUDevicePtrT");
+  EventTy = StructType::create(Context, "struct.PollyGPUEventT");
+}
+
+void PTXGenerator::createCallInitDevice(Value *Context, Value *Device) {
+  const char *Name = "polly_initDevice";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(PointerType::getUnqual(getGPUContextPtrType()));
+    Args.push_back(PointerType::getUnqual(getGPUDevicePtrType()));
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall2(F, Context, Device);
+}
+
+void PTXGenerator::createCallGetPTXModule(Value *Buffer, Value *Module) {
+  const char *Name = "polly_getPTXModule";
+  llvm::Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getI8PtrType());
+    Args.push_back(PointerType::getUnqual(getGPUModulePtrType()));
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall2(F, Buffer, Module);
+}
+
+void PTXGenerator::createCallGetPTXKernelEntry(Value *Entry, Value *Module,
+                                               Value *Kernel) {
+  const char *Name = "polly_getPTXKernelEntry";
+  llvm::Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getI8PtrType());
+    Args.push_back(getGPUModulePtrType());
+    Args.push_back(PointerType::getUnqual(getGPUFunctionPtrType()));
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall3(F, Entry, Module, Kernel);
+}
+
+void PTXGenerator::createCallAllocateMemoryForHostAndDevice(Value *HostData,
+                                                            Value *DeviceData,
+                                                            Value *Size) {
+  const char *Name = "polly_allocateMemoryForHostAndDevice";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getPtrI8PtrType());
+    Args.push_back(PointerType::getUnqual(getPtrGPUDevicePtrType()));
+    Args.push_back(getInt64Type());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall3(F, HostData, DeviceData, Size);
+}
+
+void PTXGenerator::createCallCopyFromHostToDevice(Value *DeviceData,
+                                                  Value *HostData,
+                                                  Value *Size) {
+  const char *Name = "polly_copyFromHostToDevice";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getPtrGPUDevicePtrType());
+    Args.push_back(getI8PtrType());
+    Args.push_back(getInt64Type());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall3(F, DeviceData, HostData, Size);
+}
+
+void PTXGenerator::createCallCopyFromDeviceToHost(Value *HostData,
+                                                  Value *DeviceData,
+                                                  Value *Size) {
+  const char *Name = "polly_copyFromDeviceToHost";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getI8PtrType());
+    Args.push_back(getPtrGPUDevicePtrType());
+    Args.push_back(getInt64Type());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall3(F, HostData, DeviceData, Size);
+}
+
+void PTXGenerator::createCallSetKernelParameters(Value *Kernel,
+                                                 Value *BlockWidth,
+                                                 Value *BlockHeight,
+                                                 Value *DeviceData) {
+  const char *Name = "polly_setKernelParameters";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getGPUFunctionPtrType());
+    Args.push_back(getInt64Type());
+    Args.push_back(getInt64Type());
+    Args.push_back(getPtrGPUDevicePtrType());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall4(F, Kernel, BlockWidth, BlockHeight, DeviceData);
+}
+
+void PTXGenerator::createCallLaunchKernel(Value *Kernel, Value *GridWidth,
+                                          Value *GridHeight) {
+  const char *Name = "polly_launchKernel";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getGPUFunctionPtrType());
+    Args.push_back(getInt64Type());
+    Args.push_back(getInt64Type());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall3(F, Kernel, GridWidth, GridHeight);
+}
+
+void PTXGenerator::createCallStartTimerByCudaEvent(Value *StartEvent,
+                                                   Value *StopEvent) {
+  const char *Name = "polly_startTimerByCudaEvent";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(PointerType::getUnqual(getGPUEventPtrType()));
+    Args.push_back(PointerType::getUnqual(getGPUEventPtrType()));
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall2(F, StartEvent, StopEvent);
+}
+
+void PTXGenerator::createCallStopTimerByCudaEvent(Value *StartEvent,
+                                                  Value *StopEvent,
+                                                  Value *Timer) {
+  const char *Name = "polly_stopTimerByCudaEvent";
+  Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getGPUEventPtrType());
+    Args.push_back(getGPUEventPtrType());
+    Args.push_back(getFloatPtrType());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall3(F, StartEvent, StopEvent, Timer);
+}
+
+void PTXGenerator::createCallCleanupGPGPUResources(Value *HostData,
+                                                   Value *DeviceData,
+                                                   Value *Module,
+                                                   Value *Context,
+                                                   Value *Kernel) {
+  const char *Name = "polly_cleanupGPGPUResources";
+  llvm::Module *M = getModule();
+  Function *F = M->getFunction(Name);
+
+  // If F is not available, declare it.
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    std::vector<Type *> Args;
+    Args.push_back(getI8PtrType());
+    Args.push_back(getPtrGPUDevicePtrType());
+    Args.push_back(getGPUModulePtrType());
+    Args.push_back(getGPUContextPtrType());
+    Args.push_back(getGPUFunctionPtrType());
+    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  Builder.CreateCall5(F, HostData, DeviceData, Module, Context, Kernel);
+}
+
+Value *PTXGenerator::getCUDAGridWidth() {
+  return ConstantInt::get(getInt64Type(), GridWidth);
+}
+
+Value *PTXGenerator::getCUDAGridHeight() {
+  return ConstantInt::get(getInt64Type(), GridHeight);
+}
+
+Value *PTXGenerator::getCUDABlockWidth() {
+  return ConstantInt::get(getInt64Type(), BlockWidth);
+}
+
+Value *PTXGenerator::getCUDABlockHeight() {
+  return ConstantInt::get(getInt64Type(), BlockHeight);
+}
+
+Value *PTXGenerator::getOutputArraySizeInBytes() {
+  return ConstantInt::get(getInt64Type(), OutputBytes);
+}
+
+static Module *extractPTXFunctionsFromModule(const Module *M,
+                                             const StringRef &Triple) {
+  llvm::ValueToValueMapTy VMap;
+  Module *New = new Module("TempGPUModule", M->getContext());
+  New->setTargetTriple(Triple::normalize(Triple));
+
+  // Loop over the functions in the module, making external functions as before
+  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
+    if (!I->isDeclaration() &&
+        (I->getCallingConv() == CallingConv::PTX_Device ||
+         I->getCallingConv() == CallingConv::PTX_Kernel)) {
+      Function *NF =
+          Function::Create(cast<FunctionType>(I->getType()->getElementType()),
+                           I->getLinkage(), I->getName(), New);
+      NF->copyAttributesFrom(I);
+      VMap[I] = NF;
+
+      Function::arg_iterator DestI = NF->arg_begin();
+      for (Function::const_arg_iterator J = I->arg_begin(); J != I->arg_end();
+           ++J) {
+        DestI->setName(J->getName());
+        VMap[J] = DestI++;
+      }
+      SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
+      CloneFunctionInto(NF, I, VMap, /*ModuleLevelChanges=*/true, Returns);
+    }
+  }
+
+  return New;
+}
+
+static bool createASMAsString(Module *New, const StringRef &Triple,
+                              const StringRef &MCPU, const StringRef &Features,
+                              std::string &ASM) {
+  llvm::Triple TheTriple(Triple::normalize(Triple));
+  std::string ErrMsg;
+  const Target *TheTarget =
+      TargetRegistry::lookupTarget(TheTriple.getTriple(), ErrMsg);
+  if (!TheTarget) {
+    errs() << ErrMsg << "\n";
+    return false;
+  }
+
+  TargetOptions Options;
+  std::unique_ptr<TargetMachine> target(TheTarget->createTargetMachine(
+      TheTriple.getTriple(), MCPU, Features, Options));
+  assert(target.get() && "Could not allocate target machine!");
+  TargetMachine &Target = *target.get();
+
+  // Build up all of the passes that we want to do to the module.
+  PassManager PM;
+
+  TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple);
+  PM.add(TLI);
+
+  PM.add(new DataLayoutPass(*Target.getDataLayout()));
+  Target.addAnalysisPasses(PM);
+
+  {
+    raw_string_ostream NameROS(ASM);
+    formatted_raw_ostream FOS(NameROS);
+
+    // Ask the target to add backend passes as necessary.
+    int UseVerifier = true;
+    if (Target.addPassesToEmitFile(PM, FOS, TargetMachine::CGFT_AssemblyFile,
+                                   UseVerifier)) {
+      errs() << "The target does not support generation of this file type!\n";
+      return false;
+    }
+
+    PM.run(*New);
+    FOS.flush();
+  }
+
+  return true;
+}
+
+Value *PTXGenerator::createPTXKernelFunction(Function *SubFunction) {
+  Module *M = getModule();
+  Module *GPUModule = extractPTXFunctionsFromModule(M, GPUTriple);
+  std::string LLVMKernelStr;
+  if (!createASMAsString(GPUModule, GPUTriple, "sm_20" /*MCPU*/,
+                         "" /*Features*/, LLVMKernelStr)) {
+    errs() << "Generate ptx string failed!\n";
+    return NULL;
+  }
+
+  Value *LLVMKernel =
+      Builder.CreateGlobalStringPtr(LLVMKernelStr, "llvm_kernel");
+
+  delete GPUModule;
+  return LLVMKernel;
+}
+
+Value *PTXGenerator::getPTXKernelEntryName(Function *SubFunction) {
+  StringRef Entry = SubFunction->getName();
+  return Builder.CreateGlobalStringPtr(Entry, "ptx_entry");
+}
+
+void PTXGenerator::eraseUnusedFunctions(Function *SubFunction) {
+  Module *M = getModule();
+  SubFunction->eraseFromParent();
+
+  if (Function *FuncPTXReadNCtaidX = M->getFunction("llvm.ptx.read.nctaid.x")) {
+    FuncPTXReadNCtaidX->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadNCtaidY = M->getFunction("llvm.ptx.read.nctaid.y")) {
+    FuncPTXReadNCtaidY->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadCtaidX = M->getFunction("llvm.ptx.read.ctaid.x")) {
+    FuncPTXReadCtaidX->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadCtaidY = M->getFunction("llvm.ptx.read.ctaid.y")) {
+    FuncPTXReadCtaidY->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadNTidX = M->getFunction("llvm.ptx.read.ntid.x")) {
+    FuncPTXReadNTidX->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadNTidY = M->getFunction("llvm.ptx.read.ntid.y")) {
+    FuncPTXReadNTidY->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadTidX = M->getFunction("llvm.ptx.read.tid.x")) {
+    FuncPTXReadTidX->eraseFromParent();
+  }
+
+  if (Function *FuncPTXReadTidY = M->getFunction("llvm.ptx.read.tid.y")) {
+    FuncPTXReadTidY->eraseFromParent();
+  }
+}
+
+void PTXGenerator::finishGeneration(Function *F) {
+  // Define data used by the GPURuntime library.
+  AllocaInst *PtrCUContext =
+      Builder.CreateAlloca(getGPUContextPtrType(), 0, "phcontext");
+  AllocaInst *PtrCUDevice =
+      Builder.CreateAlloca(getGPUDevicePtrType(), 0, "phdevice");
+  AllocaInst *PtrCUModule =
+      Builder.CreateAlloca(getGPUModulePtrType(), 0, "phmodule");
+  AllocaInst *PtrCUKernel =
+      Builder.CreateAlloca(getGPUFunctionPtrType(), 0, "phkernel");
+  AllocaInst *PtrCUStartEvent =
+      Builder.CreateAlloca(getGPUEventPtrType(), 0, "pstart_timer");
+  AllocaInst *PtrCUStopEvent =
+      Builder.CreateAlloca(getGPUEventPtrType(), 0, "pstop_timer");
+  AllocaInst *PtrDevData =
+      Builder.CreateAlloca(getPtrGPUDevicePtrType(), 0, "pdevice_data");
+  AllocaInst *PtrHostData =
+      Builder.CreateAlloca(getI8PtrType(), 0, "phost_data");
+  Type *FloatTy = llvm::Type::getFloatTy(getModule()->getContext());
+  AllocaInst *PtrElapsedTimes = Builder.CreateAlloca(FloatTy, 0, "ptimer");
+
+  // Initialize the GPU device.
+  createCallInitDevice(PtrCUContext, PtrCUDevice);
+
+  // Create the GPU kernel module and entry function.
+  Value *PTXString = createPTXKernelFunction(F);
+  Value *PTXEntry = getPTXKernelEntryName(F);
+  createCallGetPTXModule(PTXString, PtrCUModule);
+  LoadInst *CUModule = Builder.CreateLoad(PtrCUModule, "cumodule");
+  createCallGetPTXKernelEntry(PTXEntry, CUModule, PtrCUKernel);
+
+  // Allocate device memory and its corresponding host memory.
+  createCallAllocateMemoryForHostAndDevice(PtrHostData, PtrDevData,
+                                           getOutputArraySizeInBytes());
+
+  // Get the pointer to the device memory and set the GPU execution parameters.
+  LoadInst *DData = Builder.CreateLoad(PtrDevData, "device_data");
+  LoadInst *CUKernel = Builder.CreateLoad(PtrCUKernel, "cukernel");
+  createCallSetKernelParameters(CUKernel, getCUDABlockWidth(),
+                                getCUDABlockHeight(), DData);
+
+  // Create the start and end timer and record the start time.
+  createCallStartTimerByCudaEvent(PtrCUStartEvent, PtrCUStopEvent);
+
+  // Launch the GPU kernel.
+  createCallLaunchKernel(CUKernel, getCUDAGridWidth(), getCUDAGridHeight());
+
+  // Copy the results back from the GPU to the host.
+  LoadInst *HData = Builder.CreateLoad(PtrHostData, "host_data");
+  createCallCopyFromDeviceToHost(HData, DData, getOutputArraySizeInBytes());
+
+  // Record the end time.
+  LoadInst *CUStartEvent = Builder.CreateLoad(PtrCUStartEvent, "start_timer");
+  LoadInst *CUStopEvent = Builder.CreateLoad(PtrCUStopEvent, "stop_timer");
+  createCallStopTimerByCudaEvent(CUStartEvent, CUStopEvent, PtrElapsedTimes);
+
+  // Cleanup all the resources used.
+  LoadInst *CUContext = Builder.CreateLoad(PtrCUContext, "cucontext");
+  createCallCleanupGPGPUResources(HData, DData, CUModule, CUContext, CUKernel);
+
+  // Erase the ptx kernel and device subfunctions and ptx intrinsics from
+  // current module.
+  eraseUnusedFunctions(F);
+}
+#endif /* GPU_CODEGEN */
diff --git a/final/lib/CodeGen/RuntimeDebugBuilder.cpp b/final/lib/CodeGen/RuntimeDebugBuilder.cpp
new file mode 100644
index 0000000..7794c91
--- /dev/null
+++ b/final/lib/CodeGen/RuntimeDebugBuilder.cpp
@@ -0,0 +1,80 @@
+//===--- RuntimeDebugBuilder.cpp - Helper to insert prints into LLVM-IR ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/RuntimeDebugBuilder.h"
+
+#include "llvm/IR/Module.h"
+
+using namespace llvm;
+using namespace polly;
+
+Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) {
+  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
+  const char *Name = "printf";
+  Function *F = M->getFunction(Name);
+
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    FunctionType *Ty =
+        FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), true);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  return F;
+}
+
+void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) {
+  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
+  const char *Name = "fflush";
+  Function *F = M->getFunction(Name);
+
+  if (!F) {
+    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+    FunctionType *Ty =
+        FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), false);
+    F = Function::Create(Ty, Linkage, Name, M);
+  }
+
+  // fflush(NULL) flushes _all_ open output streams.
+  //
+  // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
+  // pointer, the type we point to does conceptually not matter. However, if
+  // fflush is already declared in this translation unit, we use the very same
+  // type to ensure that LLVM does not complain about mismatching types.
+  Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));
+}
+
+void RuntimeDebugBuilder::createStrPrinter(PollyIRBuilder &Builder,
+                                           const std::string &String) {
+  Value *StringValue = Builder.CreateGlobalStringPtr(String);
+  Builder.CreateCall(getPrintF(Builder), StringValue);
+
+  createFlush(Builder);
+}
+
+void RuntimeDebugBuilder::createValuePrinter(PollyIRBuilder &Builder,
+                                             Value *V) {
+  const char *Format = nullptr;
+
+  Type *Ty = V->getType();
+  if (Ty->isIntegerTy())
+    Format = "%ld";
+  else if (Ty->isFloatingPointTy())
+    Format = "%lf";
+  else if (Ty->isPointerTy())
+    Format = "%p";
+
+  assert(Format && Ty->getPrimitiveSizeInBits() <= 64 && "Bad type to print.");
+
+  Value *FormatString = Builder.CreateGlobalStringPtr(Format);
+  Builder.CreateCall2(getPrintF(Builder), FormatString, V);
+  createFlush(Builder);
+}
diff --git a/final/lib/CodeGen/Utils.cpp b/final/lib/CodeGen/Utils.cpp
new file mode 100644
index 0000000..8ea9a4a
--- /dev/null
+++ b/final/lib/CodeGen/Utils.cpp
@@ -0,0 +1,87 @@
+//===--- Utils.cpp - Utility functions for the code generation --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions for the code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/CodeGen/Utils.h"
+#include "polly/CodeGen/IRBuilder.h"
+#include "polly/ScopInfo.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+using namespace llvm;
+
+BasicBlock *polly::executeScopConditionally(Scop &S, Pass *P, Value *RTC) {
+  BasicBlock *StartBlock, *SplitBlock, *NewBlock;
+  Region &R = S.getRegion();
+  PollyIRBuilder Builder(R.getEntry());
+  DominatorTree &DT = P->getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+  RegionInfo &RI = P->getAnalysis<RegionInfoPass>().getRegionInfo();
+  LoopInfo &LI = P->getAnalysis<LoopInfo>();
+
+  // Split the entry edge of the region and generate a new basic block on this
+  // edge. This function also updates ScopInfo and RegionInfo.
+  NewBlock = SplitEdge(R.getEnteringBlock(), R.getEntry(), P);
+  if (DT.dominates(R.getEntry(), NewBlock)) {
+    BasicBlock *OldBlock = R.getEntry();
+    std::string OldName = OldBlock->getName();
+
+    // Update ScopInfo.
+    for (ScopStmt *Stmt : S)
+      if (Stmt->getBasicBlock() == OldBlock) {
+        Stmt->setBasicBlock(NewBlock);
+        break;
+      }
+
+    // Update RegionInfo.
+    SplitBlock = OldBlock;
+    OldBlock->setName("polly.split");
+    NewBlock->setName(OldName);
+    R.replaceEntryRecursive(NewBlock);
+    RI.setRegionFor(NewBlock, &R);
+  } else {
+    RI.setRegionFor(NewBlock, R.getParent());
+    SplitBlock = NewBlock;
+  }
+
+  SplitBlock->setName("polly.split_new_and_old");
+  Function *F = SplitBlock->getParent();
+  StartBlock = BasicBlock::Create(F->getContext(), "polly.start", F);
+  SplitBlock->getTerminator()->eraseFromParent();
+  Builder.SetInsertPoint(SplitBlock);
+  Builder.CreateCondBr(RTC, StartBlock, R.getEntry());
+  if (Loop *L = LI.getLoopFor(SplitBlock))
+    L->addBasicBlockToLoop(StartBlock, LI.getBase());
+  DT.addNewBlock(StartBlock, SplitBlock);
+  Builder.SetInsertPoint(StartBlock);
+
+  BasicBlock *MergeBlock;
+
+  if (R.getExit()->getSinglePredecessor())
+    // No splitEdge required.  A block with a single predecessor cannot have
+    // PHI nodes that would complicate life.
+    MergeBlock = R.getExit();
+  else {
+    MergeBlock = SplitEdge(R.getExitingBlock(), R.getExit(), P);
+    // SplitEdge will never split R.getExit(), as R.getExit() has more than
+    // one predecessor. Hence, mergeBlock is always a newly generated block.
+    R.replaceExitRecursive(MergeBlock);
+    RI.setRegionFor(MergeBlock, &R);
+  }
+
+  Builder.CreateBr(MergeBlock);
+  MergeBlock->setName("polly.merge_new_and_old");
+
+  if (DT.dominates(SplitBlock, MergeBlock))
+    DT.changeImmediateDominator(MergeBlock, SplitBlock);
+  return StartBlock;
+}
diff --git a/final/lib/Exchange/JSONExporter.cpp b/final/lib/Exchange/JSONExporter.cpp
new file mode 100644
index 0000000..21f7bf8
--- /dev/null
+++ b/final/lib/Exchange/JSONExporter.cpp
@@ -0,0 +1,384 @@
+//===-- JSONExporter.cpp  - Export Scops as JSON  -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Export the Scops build by ScopInfo pass as a JSON file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/LinkAllPasses.h"
+#include "polly/Dependences.h"
+#include "polly/Options.h"
+#include "polly/ScopInfo.h"
+#include "polly/ScopPass.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+#include "json/reader.h"
+#include "json/writer.h"
+
+#include "isl/set.h"
+#include "isl/map.h"
+#include "isl/constraint.h"
+#include "isl/printer.h"
+
+#include <memory>
+#include <string>
+#include <system_error>
+
+using namespace llvm;
+using namespace polly;
+
+#define DEBUG_TYPE "polly-import-jscop"
+
+STATISTIC(NewAccessMapFound, "Number of updated access functions");
+
+namespace {
+static cl::opt<std::string>
+    ImportDir("polly-import-jscop-dir",
+              cl::desc("The directory to import the .jscop files from."),
+              cl::Hidden, cl::value_desc("Directory path"), cl::ValueRequired,
+              cl::init("."), cl::cat(PollyCategory));
+
+static cl::opt<std::string>
+    ImportPostfix("polly-import-jscop-postfix",
+                  cl::desc("Postfix to append to the import .jsop files."),
+                  cl::Hidden, cl::value_desc("File postfix"), cl::ValueRequired,
+                  cl::init(""), cl::cat(PollyCategory));
+
+struct JSONExporter : public ScopPass {
+  static char ID;
+  Scop *S;
+  explicit JSONExporter() : ScopPass(ID) {}
+
+  std::string getFileName(Scop *S) const;
+  Json::Value getJSON(Scop &scop) const;
+  virtual bool runOnScop(Scop &S);
+  void printScop(raw_ostream &OS) const;
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+};
+
+struct JSONImporter : public ScopPass {
+  static char ID;
+  Scop *S;
+  std::vector<std::string> newAccessStrings;
+  explicit JSONImporter() : ScopPass(ID) {}
+
+  std::string getFileName(Scop *S) const;
+  virtual bool runOnScop(Scop &S);
+  void printScop(raw_ostream &OS) const;
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+};
+}
+
+char JSONExporter::ID = 0;
+std::string JSONExporter::getFileName(Scop *S) const {
+  std::string FunctionName = S->getRegion().getEntry()->getParent()->getName();
+  std::string FileName = FunctionName + "___" + S->getNameStr() + ".jscop";
+  return FileName;
+}
+
+void JSONExporter::printScop(raw_ostream &OS) const { S->print(OS); }
+
+Json::Value JSONExporter::getJSON(Scop &scop) const {
+  Json::Value root;
+
+  root["name"] = S->getRegion().getNameStr();
+  root["context"] = S->getContextStr();
+  root["statements"];
+
+  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
+    ScopStmt *Stmt = *SI;
+
+    Json::Value statement;
+
+    statement["name"] = Stmt->getBaseName();
+    statement["domain"] = Stmt->getDomainStr();
+    statement["schedule"] = Stmt->getScatteringStr();
+    statement["accesses"];
+
+    for (MemoryAccess *MA : *Stmt) {
+      Json::Value access;
+
+      access["kind"] = MA->isRead() ? "read" : "write";
+      access["relation"] = MA->getOriginalAccessRelationStr();
+
+      statement["accesses"].append(access);
+    }
+
+    root["statements"].append(statement);
+  }
+
+  return root;
+}
+
+bool JSONExporter::runOnScop(Scop &scop) {
+  S = &scop;
+  Region &R = S->getRegion();
+
+  std::string FileName = ImportDir + "/" + getFileName(S);
+
+  Json::Value jscop = getJSON(scop);
+  Json::StyledWriter writer;
+  std::string fileContent = writer.write(jscop);
+
+  // Write to file.
+  std::error_code EC;
+  tool_output_file F(FileName, EC, llvm::sys::fs::F_Text);
+
+  std::string FunctionName = R.getEntry()->getParent()->getName();
+  errs() << "Writing JScop '" << R.getNameStr() << "' in function '"
+         << FunctionName << "' to '" << FileName << "'.\n";
+
+  if (!EC) {
+    F.os() << fileContent;
+    F.os().close();
+    if (!F.os().has_error()) {
+      errs() << "\n";
+      F.keep();
+      return false;
+    }
+  }
+
+  errs() << "  error opening file for writing!\n";
+  F.os().clear_error();
+
+  return false;
+}
+
+void JSONExporter::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.setPreservesAll();
+  AU.addRequired<ScopInfo>();
+}
+
+Pass *polly::createJSONExporterPass() { return new JSONExporter(); }
+
+char JSONImporter::ID = 0;
+std::string JSONImporter::getFileName(Scop *S) const {
+  std::string FunctionName = S->getRegion().getEntry()->getParent()->getName();
+  std::string FileName = FunctionName + "___" + S->getNameStr() + ".jscop";
+
+  if (ImportPostfix != "")
+    FileName += "." + ImportPostfix;
+
+  return FileName;
+}
+
+void JSONImporter::printScop(raw_ostream &OS) const {
+  S->print(OS);
+  for (std::vector<std::string>::const_iterator I = newAccessStrings.begin(),
+                                                E = newAccessStrings.end();
+       I != E; I++)
+    OS << "New access function '" << *I << "'detected in JSCOP file\n";
+}
+
+typedef Dependences::StatementToIslMapTy StatementToIslMapTy;
+
+bool JSONImporter::runOnScop(Scop &scop) {
+  S = &scop;
+  Region &R = S->getRegion();
+  Dependences *D = &getAnalysis<Dependences>();
+  const DataLayout &DL = getAnalysis<DataLayoutPass>().getDataLayout();
+
+  std::string FileName = ImportDir + "/" + getFileName(S);
+
+  std::string FunctionName = R.getEntry()->getParent()->getName();
+  errs() << "Reading JScop '" << R.getNameStr() << "' in function '"
+         << FunctionName << "' from '" << FileName << "'.\n";
+  ErrorOr<std::unique_ptr<MemoryBuffer>> result =
+      MemoryBuffer::getFile(FileName);
+  std::error_code ec = result.getError();
+
+  if (ec) {
+    errs() << "File could not be read: " << ec.message() << "\n";
+    return false;
+  }
+
+  Json::Reader reader;
+  Json::Value jscop;
+
+  bool parsingSuccessful = reader.parse(result.get()->getBufferStart(), jscop);
+
+  if (!parsingSuccessful) {
+    errs() << "JSCoP file could not be parsed\n";
+    return false;
+  }
+
+  isl_set *OldContext = S->getContext();
+  isl_set *NewContext =
+      isl_set_read_from_str(S->getIslCtx(), jscop["context"].asCString());
+
+  for (unsigned i = 0; i < isl_set_dim(OldContext, isl_dim_param); i++) {
+    isl_id *id = isl_set_get_dim_id(OldContext, isl_dim_param, i);
+    NewContext = isl_set_set_dim_id(NewContext, isl_dim_param, i, id);
+  }
+
+  isl_set_free(OldContext);
+  S->setContext(NewContext);
+
+  StatementToIslMapTy &NewScattering = *(new StatementToIslMapTy());
+
+  int index = 0;
+
+  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
+    Json::Value schedule = jscop["statements"][index]["schedule"];
+    isl_map *m = isl_map_read_from_str(S->getIslCtx(), schedule.asCString());
+    isl_space *Space = (*SI)->getDomainSpace();
+
+    // Copy the old tuple id. This is necessary to retain the user pointer,
+    // that stores the reference to the ScopStmt this scattering belongs to.
+    m = isl_map_set_tuple_id(m, isl_dim_in,
+                             isl_space_get_tuple_id(Space, isl_dim_set));
+    isl_space_free(Space);
+    NewScattering[*SI] = m;
+    index++;
+  }
+
+  if (!D->isValidScattering(&NewScattering)) {
+    errs() << "JScop file contains a scattering that changes the "
+           << "dependences. Use -disable-polly-legality to continue anyways\n";
+    for (StatementToIslMapTy::iterator SI = NewScattering.begin(),
+                                       SE = NewScattering.end();
+         SI != SE; ++SI)
+      isl_map_free(SI->second);
+    return false;
+  }
+
+  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
+    ScopStmt *Stmt = *SI;
+
+    if (NewScattering.find(Stmt) != NewScattering.end())
+      Stmt->setScattering(NewScattering[Stmt]);
+  }
+
+  int statementIdx = 0;
+  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
+    ScopStmt *Stmt = *SI;
+
+    int memoryAccessIdx = 0;
+    for (MemoryAccess *MA : *Stmt) {
+      Json::Value accesses = jscop["statements"][statementIdx]["accesses"]
+                                  [memoryAccessIdx]["relation"];
+      isl_map *newAccessMap =
+          isl_map_read_from_str(S->getIslCtx(), accesses.asCString());
+      isl_map *currentAccessMap = MA->getAccessRelation();
+
+      if (isl_map_dim(newAccessMap, isl_dim_param) !=
+          isl_map_dim(currentAccessMap, isl_dim_param)) {
+        errs() << "JScop file changes the number of parameter dimensions\n";
+        isl_map_free(currentAccessMap);
+        isl_map_free(newAccessMap);
+        return false;
+      }
+
+      isl_id *OutId = isl_map_get_tuple_id(currentAccessMap, isl_dim_out);
+      newAccessMap = isl_map_set_tuple_id(newAccessMap, isl_dim_out, OutId);
+
+      // We keep the old alignment, thus we cannot allow accesses to memory
+      // locations that were not accessed before if the alignment of the access
+      // is not the default alignment.
+      bool SpecialAlignment = true;
+      if (LoadInst *LoadI = dyn_cast<LoadInst>(MA->getAccessInstruction())) {
+        SpecialAlignment =
+            DL.getABITypeAlignment(LoadI->getType()) != LoadI->getAlignment();
+      } else if (StoreInst *StoreI =
+                     dyn_cast<StoreInst>(MA->getAccessInstruction())) {
+        SpecialAlignment =
+            DL.getABITypeAlignment(StoreI->getValueOperand()->getType()) !=
+            StoreI->getAlignment();
+      }
+
+      if (SpecialAlignment) {
+        isl_set *newAccessSet = isl_map_range(isl_map_copy(newAccessMap));
+        isl_set *currentAccessSet =
+            isl_map_range(isl_map_copy(currentAccessMap));
+        bool isSubset = isl_set_is_subset(newAccessSet, currentAccessSet);
+        isl_set_free(newAccessSet);
+        isl_set_free(currentAccessSet);
+
+        if (!isSubset) {
+          errs() << "JScop file changes the accessed memory\n";
+          isl_map_free(currentAccessMap);
+          isl_map_free(newAccessMap);
+          return false;
+        }
+      }
+
+      // We need to copy the isl_ids for the parameter dimensions to the new
+      // map. Without doing this the current map would have different
+      // ids then the new one, even though both are named identically.
+      for (unsigned i = 0; i < isl_map_dim(currentAccessMap, isl_dim_param);
+           i++) {
+        isl_id *id = isl_map_get_dim_id(currentAccessMap, isl_dim_param, i);
+        newAccessMap = isl_map_set_dim_id(newAccessMap, isl_dim_param, i, id);
+      }
+
+      // Copy the old tuple id. This is necessary to retain the user pointer,
+      // that stores the reference to the ScopStmt this access belongs to.
+      isl_id *Id = isl_map_get_tuple_id(currentAccessMap, isl_dim_in);
+      newAccessMap = isl_map_set_tuple_id(newAccessMap, isl_dim_in, Id);
+
+      if (!isl_map_has_equal_space(currentAccessMap, newAccessMap)) {
+        errs() << "JScop file contains access function with incompatible "
+               << "dimensions\n";
+        isl_map_free(currentAccessMap);
+        isl_map_free(newAccessMap);
+        return false;
+      }
+      if (isl_map_dim(newAccessMap, isl_dim_out) != 1) {
+        errs() << "New access map in JScop file should be single dimensional\n";
+        isl_map_free(currentAccessMap);
+        isl_map_free(newAccessMap);
+        return false;
+      }
+      if (!isl_map_is_equal(newAccessMap, currentAccessMap)) {
+        // Statistics.
+        ++NewAccessMapFound;
+        newAccessStrings.push_back(accesses.asCString());
+        MA->setNewAccessRelation(newAccessMap);
+      } else {
+        isl_map_free(newAccessMap);
+      }
+      isl_map_free(currentAccessMap);
+      memoryAccessIdx++;
+    }
+    statementIdx++;
+  }
+
+  return false;
+}
+
+void JSONImporter::getAnalysisUsage(AnalysisUsage &AU) const {
+  ScopPass::getAnalysisUsage(AU);
+  AU.addRequired<Dependences>();
+  AU.addRequired<DataLayoutPass>();
+}
+Pass *polly::createJSONImporterPass() { return new JSONImporter(); }
+
+INITIALIZE_PASS_BEGIN(JSONExporter, "polly-export-jscop",
+                      "Polly - Export Scops as JSON"
+                      " (Writes a .jscop file for each Scop)",
+                      false, false);
+INITIALIZE_PASS_DEPENDENCY(Dependences)
+INITIALIZE_PASS_END(JSONExporter, "polly-export-jscop",
+                    "Polly - Export Scops as JSON"
+                    " (Writes a .jscop file for each Scop)",
+                    false, false)
+
+INITIALIZE_PASS_BEGIN(JSONImporter, "polly-import-jscop",
+                      "Polly - Import Scops from JSON"
+                      " (Reads a .jscop file for each Scop)",
+                      false, false);
+INITIALIZE_PASS_DEPENDENCY(Dependences)
+INITIALIZE_PASS_DEPENDENCY(DataLayoutPass)
+INITIALIZE_PASS_END(JSONImporter, "polly-import-jscop",
+                    "Polly - Import Scops from JSON"
+                    " (Reads a .jscop file for each Scop)",
+                    false, false)
diff --git a/final/lib/JSON/LICENSE.txt b/final/lib/JSON/LICENSE.txt
new file mode 100644
index 0000000..1c37b11
--- /dev/null
+++ b/final/lib/JSON/LICENSE.txt
@@ -0,0 +1 @@
+The json-cpp library and this documentation are in Public Domain.
diff --git a/final/lib/JSON/include/json/autolink.h b/final/lib/JSON/include/json/autolink.h
new file mode 100644
index 0000000..37c9258
--- /dev/null
+++ b/final/lib/JSON/include/json/autolink.h
@@ -0,0 +1,19 @@
+#ifndef JSON_AUTOLINK_H_INCLUDED
+# define JSON_AUTOLINK_H_INCLUDED
+
+# include "config.h"
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/cpptl_autolink.h>
+# endif
+
+# if !defined(JSON_NO_AUTOLINK)  &&  !defined(JSON_DLL_BUILD)  &&  !defined(JSON_IN_CPPTL)
+#  define CPPTL_AUTOLINK_NAME "json"
+#  undef CPPTL_AUTOLINK_DLL
+#  ifdef JSON_DLL
+#   define CPPTL_AUTOLINK_DLL
+#  endif
+#  include "autolink.h"
+# endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED
diff --git a/final/lib/JSON/include/json/config.h b/final/lib/JSON/include/json/config.h
new file mode 100644
index 0000000..b6dde91
--- /dev/null
+++ b/final/lib/JSON/include/json/config.h
@@ -0,0 +1,43 @@
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL!
+//#  define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 0
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/config.h>
+#  ifndef JSON_USE_CPPTL
+#   define JSON_USE_CPPTL 1
+#  endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+#  define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+#  define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+#  define JSON_API __declspec(dllimport)
+# else
+#  define JSON_API
+# endif
+
+#endif // JSON_CONFIG_H_INCLUDED
diff --git a/final/lib/JSON/include/json/features.h b/final/lib/JSON/include/json/features.h
new file mode 100644
index 0000000..5a9adec
--- /dev/null
+++ b/final/lib/JSON/include/json/features.h
@@ -0,0 +1,42 @@
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+# define CPPTL_JSON_FEATURES_H_INCLUDED
+
+# include "forwards.h"
+
+namespace Json {
+
+   /** \brief Configuration passed to reader and writer.
+    * This configuration object can be used to force the Reader or Writer
+    * to behave in a standard conforming way.
+    */
+   class JSON_API Features
+   {
+   public:
+      /** \brief A configuration that allows all features and assumes all strings are UTF-8.
+       * - C & C++ comments are allowed
+       * - Root object can be any JSON value
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features all();
+
+      /** \brief A configuration that is strictly compatible with the JSON specification.
+       * - Comments are forbidden.
+       * - Root object must be either an array or an object value.
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features strictMode();
+
+      /** \brief Initialize the configuration like JsonConfig::allFeatures;
+       */
+      Features();
+
+      /// \c true if comments are allowed. Default: \c true.
+      bool allowComments_;
+
+      /// \c true if root must be either an array or an object value. Default: \c false.
+      bool strictRoot_;
+   };
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
diff --git a/final/lib/JSON/include/json/forwards.h b/final/lib/JSON/include/json/forwards.h
new file mode 100644
index 0000000..d0ce830
--- /dev/null
+++ b/final/lib/JSON/include/json/forwards.h
@@ -0,0 +1,39 @@
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+# include "config.h"
+
+namespace Json {
+
+   // writer.h
+   class FastWriter;
+   class StyledWriter;
+
+   // reader.h
+   class Reader;
+
+   // features.h
+   class Features;
+
+   // value.h
+   typedef int Int;
+   typedef unsigned int UInt;
+   class StaticString;
+   class Path;
+   class PathArgument;
+   class Value;
+   class ValueIteratorBase;
+   class ValueIterator;
+   class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   class ValueAllocator;
+   class ValueMapAllocator;
+   class ValueInternalLink;
+   class ValueInternalArray;
+   class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED
diff --git a/final/lib/JSON/include/json/json.h b/final/lib/JSON/include/json/json.h
new file mode 100644
index 0000000..c71ed65
--- /dev/null
+++ b/final/lib/JSON/include/json/json.h
@@ -0,0 +1,10 @@
+#ifndef JSON_JSON_H_INCLUDED
+# define JSON_JSON_H_INCLUDED
+
+# include "autolink.h"
+# include "value.h"
+# include "reader.h"
+# include "writer.h"
+# include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED
diff --git a/final/lib/JSON/include/json/reader.h b/final/lib/JSON/include/json/reader.h
new file mode 100644
index 0000000..0fea022
--- /dev/null
+++ b/final/lib/JSON/include/json/reader.h
@@ -0,0 +1,195 @@
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+# include "features.h"
+# include "value.h"
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+    *
+    */
+   class JSON_API Reader
+   {
+   public:
+      typedef char Char;
+      typedef const Char *Location;
+
+      /** \brief Constructs a Reader allowing all features
+       * for parsing.
+       */
+      Reader();
+
+      /** \brief Constructs a Reader allowing the specified feature set
+       * for parsing.
+       */
+      Reader( const Features &features );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const std::string &document, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const char *beginDoc, const char *endDoc, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /// \brief Parse from input stream.
+      /// \see Json::operator>>(std::istream&, Json::Value&).
+      bool parse( std::istream &is,
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Returns a user friendly string that list errors in the parsed document.
+       * \return Formatted error message with the list of errors with their location in 
+       *         the parsed document. An empty string is returned if no error occurred
+       *         during parsing.
+       */
+      std::string getFormatedErrorMessages() const;
+
+   private:
+      enum TokenType
+      {
+         tokenEndOfStream = 0,
+         tokenObjectBegin,
+         tokenObjectEnd,
+         tokenArrayBegin,
+         tokenArrayEnd,
+         tokenString,
+         tokenNumber,
+         tokenTrue,
+         tokenFalse,
+         tokenNull,
+         tokenArraySeparator,
+         tokenMemberSeparator,
+         tokenComment,
+         tokenError
+      };
+
+      class Token
+      {
+      public:
+         TokenType type_;
+         Location start_;
+         Location end_;
+      };
+
+      class ErrorInfo
+      {
+      public:
+         Token token_;
+         std::string message_;
+         Location extra_;
+      };
+
+      typedef std::deque<ErrorInfo> Errors;
+
+      bool expectToken( TokenType type, Token &token, const char *message );
+      bool readToken( Token &token );
+      void skipSpaces();
+      bool match( Location pattern, 
+                  int patternLength );
+      bool readComment();
+      bool readCStyleComment();
+      bool readCppStyleComment();
+      bool readString();
+      void readNumber();
+      bool readValue();
+      bool readObject( Token &token );
+      bool readArray( Token &token );
+      bool decodeNumber( Token &token );
+      bool decodeString( Token &token );
+      bool decodeString( Token &token, std::string &decoded );
+      bool decodeDouble( Token &token );
+      bool decodeUnicodeCodePoint( Token &token, 
+                                   Location &current, 
+                                   Location end, 
+                                   unsigned int &unicode );
+      bool decodeUnicodeEscapeSequence( Token &token, 
+                                        Location &current, 
+                                        Location end, 
+                                        unsigned int &unicode );
+      bool addError( const std::string &message, 
+                     Token &token,
+                     Location extra = 0 );
+      bool recoverFromError( TokenType skipUntilToken );
+      bool addErrorAndRecover( const std::string &message, 
+                               Token &token,
+                               TokenType skipUntilToken );
+      void skipUntilSpace();
+      Value &currentValue();
+      Char getNextChar();
+      void getLocationLineAndColumn( Location location,
+                                     int &line,
+                                     int &column ) const;
+      std::string getLocationLineAndColumn( Location location ) const;
+      void addComment( Location begin, 
+                       Location end, 
+                       CommentPlacement placement );
+      void skipCommentTokens( Token &token );
+   
+      typedef std::stack<Value *> Nodes;
+      Nodes nodes_;
+      Errors errors_;
+      std::string document_;
+      Location begin_;
+      Location end_;
+      Location current_;
+      Location lastValueEnd_;
+      Value *lastValue_;
+      std::string commentsBefore_;
+      Features features_;
+      bool collectComments_;
+   };
+
+   /** \brief Read from 'sin' into 'root'.
+
+    Always keep comments from the input JSON.
+
+    This can be used to read a file into a particular sub-object.
+    For example:
+    \code
+    Json::Value root;
+    cin >> root["dir"]["file"];
+    cout << root;
+    \endcode
+    Result:
+    \verbatim
+    {
+	"dir": {
+	    "file": {
+		// The input stream JSON would be nested here.
+	    }
+	}
+    }
+    \endverbatim
+    \throw std::exception on parse error.
+    \see Json::operator<<()
+   */
+   std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
diff --git a/final/lib/JSON/include/json/value.h b/final/lib/JSON/include/json/value.h
new file mode 100644
index 0000000..aa25e3b
--- /dev/null
+++ b/final/lib/JSON/include/json/value.h
@@ -0,0 +1,1069 @@
+#ifndef CPPTL_JSON_H_INCLUDED
+# define CPPTL_JSON_H_INCLUDED
+
+# include "forwards.h"
+# include <string>
+# include <vector>
+
+# ifndef JSON_USE_CPPTL_SMALLMAP
+#  include <map>
+# else
+#  include <cpptl/smallmap.h>
+# endif
+# ifdef JSON_USE_CPPTL
+#  include <cpptl/forwards.h>
+# endif
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+   /** \brief Type of the value held by a Value object.
+    */
+   enum ValueType
+   {
+      nullValue = 0, ///< 'null' value
+      intValue,      ///< signed integer value
+      uintValue,     ///< unsigned integer value
+      realValue,     ///< double value
+      stringValue,   ///< UTF-8 string value
+      booleanValue,  ///< bool value
+      arrayValue,    ///< array value (ordered list)
+      objectValue    ///< object value (collection of name/value pairs).
+   };
+
+   enum CommentPlacement
+   {
+      commentBefore = 0,        ///< a comment placed on the line before a value
+      commentAfterOnSameLine,   ///< a comment just after a value on the same line
+      commentAfter,             ///< a comment on the line after a value (only make sense for root value)
+      numberOfCommentPlacement
+   };
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+   /** \brief Lightweight wrapper to tag static string.
+    *
+    * Value constructor and objectValue member assignement takes advantage of the
+    * StaticString and avoid the cost of string duplication when storing the
+    * string or the member name.
+    *
+    * Example of usage:
+    * \code
+    * Json::Value aValue( StaticString("some text") );
+    * Json::Value object;
+    * static const StaticString code("code");
+    * object[code] = 1234;
+    * \endcode
+    */
+   class JSON_API StaticString
+   {
+   public:
+      explicit StaticString( const char *czstring )
+         : str_( czstring )
+      {
+      }
+
+      operator const char *() const
+      {
+         return str_;
+      }
+
+      const char *c_str() const
+      {
+         return str_;
+      }
+
+   private:
+      const char *str_;
+   };
+
+   /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+    *
+    * This class is a discriminated union wrapper that can represents a:
+    * - signed integer [range: Value::minInt - Value::maxInt]
+    * - unsigned integer (range: 0 - Value::maxUInt)
+    * - double
+    * - UTF-8 string
+    * - boolean
+    * - 'null'
+    * - an ordered list of Value
+    * - collection of name/value pairs (javascript object)
+    *
+    * The type of the held value is represented by a #ValueType and 
+    * can be obtained using type().
+    *
+    * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. 
+    * Non const methods will automatically create the a #nullValue element 
+    * if it does not exist. 
+    * The sequence of an #arrayValue will be automatically resize and initialized 
+    * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+    *
+    * The get() methods can be used to obtanis default value in the case the required element
+    * does not exist.
+    *
+    * It is possible to iterate over the list of a #objectValue values using 
+    * the getMemberNames() method.
+    */
+   class JSON_API Value 
+   {
+      friend class ValueIteratorBase;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      friend class ValueInternalLink;
+      friend class ValueInternalMap;
+# endif
+   public:
+      typedef std::vector<std::string> Members;
+      typedef ValueIterator iterator;
+      typedef ValueConstIterator const_iterator;
+      typedef Json::UInt UInt;
+      typedef Json::Int Int;
+      typedef UInt ArrayIndex;
+
+      static const Value null;
+      static const Int minInt;
+      static const Int maxInt;
+      static const UInt maxUInt;
+
+   private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+      class CZString 
+      {
+      public:
+         enum DuplicationPolicy 
+         {
+            noDuplication = 0,
+            duplicate,
+            duplicateOnCopy
+         };
+         CZString( int index );
+         CZString( const char *cstr, DuplicationPolicy allocate );
+         CZString( const CZString &other );
+         ~CZString();
+         CZString &operator =( const CZString &other );
+         bool operator<( const CZString &other ) const;
+         bool operator==( const CZString &other ) const;
+         int index() const;
+         const char *c_str() const;
+         bool isStaticString() const;
+      private:
+         void swap( CZString &other );
+         const char *cstr_;
+         int index_;
+      };
+
+   public:
+#  ifndef JSON_USE_CPPTL_SMALLMAP
+      typedef std::map<CZString, Value> ObjectValues;
+#  else
+      typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#  endif // ifndef JSON_USE_CPPTL_SMALLMAP
+# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+   public:
+      /** \brief Create a default Value of the given type.
+
+        This is a very useful constructor.
+        To create an empty array, pass arrayValue.
+        To create an empty object, pass objectValue.
+        Another Value can then be set to this one by assignment.
+	This is useful since clear() and resize() will not alter types.
+
+        Examples:
+	\code
+	Json::Value null_value; // null
+	Json::Value arr_value(Json::arrayValue); // []
+	Json::Value obj_value(Json::objectValue); // {}
+	\endcode
+      */
+      Value( ValueType type = nullValue );
+      Value( Int value );
+      Value( UInt value );
+      Value( double value );
+      Value( const char *value );
+      Value( const char *beginValue, const char *endValue );
+      /** \brief Constructs a value from a static string.
+
+       * Like other value string constructor but do not duplicate the string for
+       * internal storage. The given string must remain alive after the call to this
+       * constructor.
+       * Example of usage:
+       * \code
+       * Json::Value aValue( StaticString("some text") );
+       * \endcode
+       */
+      Value( const StaticString &value );
+      Value( const std::string &value );
+# ifdef JSON_USE_CPPTL
+      Value( const CppTL::ConstString &value );
+# endif
+      Value( bool value );
+      Value( const Value &other );
+      ~Value();
+
+      Value &operator=( const Value &other );
+      /// Swap values.
+      /// \note Currently, comments are intentionally not swapped, for
+      /// both logic and efficiency.
+      void swap( Value &other );
+
+      ValueType type() const;
+
+      bool operator <( const Value &other ) const;
+      bool operator <=( const Value &other ) const;
+      bool operator >=( const Value &other ) const;
+      bool operator >( const Value &other ) const;
+
+      bool operator ==( const Value &other ) const;
+      bool operator !=( const Value &other ) const;
+
+      int compare( const Value &other );
+
+      const char *asCString() const;
+      std::string asString() const;
+# ifdef JSON_USE_CPPTL
+      CppTL::ConstString asConstString() const;
+# endif
+      Int asInt() const;
+      UInt asUInt() const;
+      double asDouble() const;
+      bool asBool() const;
+
+      bool isNull() const;
+      bool isBool() const;
+      bool isInt() const;
+      bool isUInt() const;
+      bool isIntegral() const;
+      bool isDouble() const;
+      bool isNumeric() const;
+      bool isString() const;
+      bool isArray() const;
+      bool isObject() const;
+
+      bool isConvertibleTo( ValueType other ) const;
+
+      /// Number of values in array or object
+      UInt size() const;
+
+      /// \brief Return true if empty array, empty object, or null;
+      /// otherwise, false.
+      bool empty() const;
+
+      /// Return isNull()
+      bool operator!() const;
+
+      /// Remove all object members and array elements.
+      /// \pre type() is arrayValue, objectValue, or nullValue
+      /// \post type() is unchanged
+      void clear();
+
+      /// Resize the array to size elements. 
+      /// New elements are initialized to null.
+      /// May only be called on nullValue or arrayValue.
+      /// \pre type() is arrayValue or nullValue
+      /// \post type() is arrayValue
+      void resize( UInt size );
+
+      /// Access an array element (zero based index ).
+      /// If the array contains less than index element, then null value are inserted
+      /// in the array so that its size is index+1.
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      Value &operator[]( UInt index );
+      /// Access an array element (zero based index )
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      const Value &operator[]( UInt index ) const;
+      /// If the array contains at least index+1 elements, returns the element value, 
+      /// otherwise returns defaultValue.
+      Value get( UInt index, 
+                 const Value &defaultValue ) const;
+      /// Return true if index < size().
+      bool isValidIndex( UInt index ) const;
+      /// \brief Append value to array at the end.
+      ///
+      /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+      Value &append( const Value &value );
+
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const char *key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const char *key ) const;
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const std::string &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const std::string &key ) const;
+      /** \brief Access an object value by name, create a null member if it does not exist.
+
+       * If the object as no entry for that name, then the member name used to store
+       * the new entry is not duplicated.
+       * Example of use:
+       * \code
+       * Json::Value object;
+       * static const StaticString code("code");
+       * object[code] = 1234;
+       * \endcode
+       */
+      Value &operator[]( const StaticString &key );
+# ifdef JSON_USE_CPPTL
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const CppTL::ConstString &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const CppTL::ConstString &key ) const;
+# endif
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const char *key, 
+                 const Value &defaultValue ) const;
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const std::string &key,
+                 const Value &defaultValue ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const CppTL::ConstString &key,
+                 const Value &defaultValue ) const;
+# endif
+      /// \brief Remove and return the named member.  
+      ///
+      /// Do nothing if it did not exist.
+      /// \return the removed Value, or null.
+      /// \pre type() is objectValue or nullValue
+      /// \post type() is unchanged
+      Value removeMember( const char* key );
+      /// Same as removeMember(const char*)
+      Value removeMember( const std::string &key );
+
+      /// Return true if the object has a member named key.
+      bool isMember( const char *key ) const;
+      /// Return true if the object has a member named key.
+      bool isMember( const std::string &key ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return true if the object has a member named key.
+      bool isMember( const CppTL::ConstString &key ) const;
+# endif
+
+      /// \brief Return a list of the member names.
+      ///
+      /// If null, return an empty list.
+      /// \pre type() is objectValue or nullValue
+      /// \post if type() was nullValue, it remains nullValue
+      Members getMemberNames() const;
+
+//# ifdef JSON_USE_CPPTL
+//      EnumMemberNames enumMemberNames() const;
+//      EnumValues enumValues() const;
+//# endif
+
+      /// Comments must be //... or /* ... */
+      void setComment( const char *comment,
+                       CommentPlacement placement );
+      /// Comments must be //... or /* ... */
+      void setComment( const std::string &comment,
+                       CommentPlacement placement );
+      bool hasComment( CommentPlacement placement ) const;
+      /// Include delimiters and embedded newlines.
+      std::string getComment( CommentPlacement placement ) const;
+
+      std::string toStyledString() const;
+
+      const_iterator begin() const;
+      const_iterator end() const;
+
+      iterator begin();
+      iterator end();
+
+   private:
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      inline bool isItemAvailable() const
+      {
+         return itemIsUsed_ == 0;
+      }
+
+      inline void setItemUsed( bool isUsed = true )
+      {
+         itemIsUsed_ = isUsed ? 1 : 0;
+      }
+
+      inline bool isMemberNameStatic() const
+      {
+         return memberNameIsStatic_ == 0;
+      }
+
+      inline void setMemberNameIsStatic( bool isStatic )
+      {
+         memberNameIsStatic_ = isStatic ? 1 : 0;
+      }
+# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+   private:
+      struct CommentInfo
+      {
+         CommentInfo();
+         ~CommentInfo();
+
+         void setComment( const char *text );
+
+         char *comment_;
+      };
+
+      //struct MemberNamesTransform
+      //{
+      //   typedef const char *result_type;
+      //   const char *operator()( const CZString &name ) const
+      //   {
+      //      return name.c_str();
+      //   }
+      //};
+
+      union ValueHolder
+      {
+         Int int_;
+         UInt uint_;
+         double real_;
+         bool bool_;
+         char *string_;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+         ValueInternalArray *array_;
+         ValueInternalMap *map_;
+#else
+         ObjectValues *map_;
+# endif
+      } value_;
+      ValueType type_ : 8;
+      int allocated_ : 1;     // Notes: if declared as bool, bitfield is useless.
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
+      int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
+# endif
+      CommentInfo *comments_;
+   };
+
+
+   /** \brief Experimental and untested: represents an element of the "path" to access a node.
+    */
+   class PathArgument
+   {
+   public:
+      friend class Path;
+
+      PathArgument();
+      PathArgument( UInt index );
+      PathArgument( const char *key );
+      PathArgument( const std::string &key );
+
+   private:
+      enum Kind
+      {
+         kindNone = 0,
+         kindIndex,
+         kindKey
+      };
+      std::string key_;
+      UInt index_;
+      Kind kind_;
+   };
+
+   /** \brief Experimental and untested: represents a "path" to access a node.
+    *
+    * Syntax:
+    * - "." => root node
+    * - ".[n]" => elements at index 'n' of root node (an array value)
+    * - ".name" => member named 'name' of root node (an object value)
+    * - ".name1.name2.name3"
+    * - ".[0][1][2].name1[3]"
+    * - ".%" => member name is provided as parameter
+    * - ".[%]" => index is provied as parameter
+    */
+   class Path
+   {
+   public:
+      Path( const std::string &path,
+            const PathArgument &a1 = PathArgument(),
+            const PathArgument &a2 = PathArgument(),
+            const PathArgument &a3 = PathArgument(),
+            const PathArgument &a4 = PathArgument(),
+            const PathArgument &a5 = PathArgument() );
+
+      const Value &resolve( const Value &root ) const;
+      Value resolve( const Value &root, 
+                     const Value &defaultValue ) const;
+      /// Creates the "path" to access the specified node and returns a reference on the node.
+      Value &make( Value &root ) const;
+
+   private:
+      typedef std::vector<const PathArgument *> InArgs;
+      typedef std::vector<PathArgument> Args;
+
+      void makePath( const std::string &path,
+                     const InArgs &in );
+      void addPathInArg( const std::string &path, 
+                         const InArgs &in, 
+                         InArgs::const_iterator &itInArg, 
+                         PathArgument::Kind kind );
+      void invalidPath( const std::string &path, 
+                        int location );
+
+      Args args_;
+   };
+
+   /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
+    *
+    * - makeMemberName() and releaseMemberName() are called to respectively duplicate and
+    *   free an Json::objectValue member name.
+    * - duplicateStringValue() and releaseStringValue() are called similarly to
+    *   duplicate and free a Json::stringValue value.
+    */
+   class ValueAllocator
+   {
+   public:
+      enum { unknown = (unsigned)-1 };
+
+      virtual ~ValueAllocator();
+
+      virtual char *makeMemberName( const char *memberName ) = 0;
+      virtual void releaseMemberName( char *memberName ) = 0;
+      virtual char *duplicateStringValue( const char *value, 
+                                          unsigned int length = unknown ) = 0;
+      virtual void releaseStringValue( char *value ) = 0;
+   };
+
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   /** \brief Allocator to customize Value internal map.
+    * Below is an example of a simple implementation (default implementation actually
+    * use memory pool for speed).
+    * \code
+      class DefaultValueMapAllocator : public ValueMapAllocator
+      {
+      public: // overridden from ValueMapAllocator
+         virtual ValueInternalMap *newMap()
+         {
+            return new ValueInternalMap();
+         }
+
+         virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+         {
+            return new ValueInternalMap( other );
+         }
+
+         virtual void destructMap( ValueInternalMap *map )
+         {
+            delete map;
+         }
+
+         virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+         {
+            return new ValueInternalLink[size];
+         }
+
+         virtual void releaseMapBuckets( ValueInternalLink *links )
+         {
+            delete [] links;
+         }
+
+         virtual ValueInternalLink *allocateMapLink()
+         {
+            return new ValueInternalLink();
+         }
+
+         virtual void releaseMapLink( ValueInternalLink *link )
+         {
+            delete link;
+         }
+      };
+    * \endcode
+    */ 
+   class JSON_API ValueMapAllocator
+   {
+   public:
+      virtual ~ValueMapAllocator();
+      virtual ValueInternalMap *newMap() = 0;
+      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
+      virtual void destructMap( ValueInternalMap *map ) = 0;
+      virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
+      virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
+      virtual ValueInternalLink *allocateMapLink() = 0;
+      virtual void releaseMapLink( ValueInternalLink *link ) = 0;
+   };
+
+   /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
+    * \internal previous_ & next_ allows for bidirectional traversal.
+    */
+   class JSON_API ValueInternalLink
+   {
+   public:
+      enum { itemPerLink = 6 };  // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
+      enum InternalFlags { 
+         flagAvailable = 0,
+         flagUsed = 1
+      };
+
+      ValueInternalLink();
+
+      ~ValueInternalLink();
+
+      Value items_[itemPerLink];
+      char *keys_[itemPerLink];
+      ValueInternalLink *previous_;
+      ValueInternalLink *next_;
+   };
+
+
+   /** \brief A linked page based hash-table implementation used internally by Value.
+    * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
+    * list in each bucket to handle collision. There is an additional twist in that
+    * each node of the collision linked list is a page containing a fixed amount of
+    * value. This provides a better compromise between memory usage and speed.
+    * 
+    * Each bucket is made up of a chained list of ValueInternalLink. The last
+    * link of a given bucket can be found in the 'previous_' field of the following bucket.
+    * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
+    * Only the last link of a bucket may contains 'available' item. The last link always
+    * contains at least one element unless is it the bucket one very first link.
+    */
+   class JSON_API ValueInternalMap
+   {
+      friend class ValueIteratorBase;
+      friend class Value;
+   public:
+      typedef unsigned int HashKey;
+      typedef unsigned int BucketIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState
+      {
+         IteratorState() 
+            : map_(0)
+            , link_(0)
+            , itemIndex_(0)
+            , bucketIndex_(0) 
+         {
+         }
+         ValueInternalMap *map_;
+         ValueInternalLink *link_;
+         BucketIndex itemIndex_;
+         BucketIndex bucketIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalMap();
+      ValueInternalMap( const ValueInternalMap &other );
+      ValueInternalMap &operator =( const ValueInternalMap &other );
+      ~ValueInternalMap();
+
+      void swap( ValueInternalMap &other );
+
+      BucketIndex size() const;
+
+      void clear();
+
+      bool reserveDelta( BucketIndex growth );
+
+      bool reserve( BucketIndex newItemCount );
+
+      const Value *find( const char *key ) const;
+
+      Value *find( const char *key );
+
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+      void remove( const char *key );
+
+      void doActualRemove( ValueInternalLink *link, 
+                           BucketIndex index,
+                           BucketIndex bucketIndex );
+
+      ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
+
+      Value &setNewItem( const char *key, 
+                         bool isStatic, 
+                         ValueInternalLink *link, 
+                         BucketIndex index );
+
+      Value &unsafeAdd( const char *key, 
+                        bool isStatic, 
+                        HashKey hashedKey );
+
+      HashKey hash( const char *key ) const;
+
+      int compare( const ValueInternalMap &other ) const;
+
+   private:
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void incrementBucket( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static const char *key( const IteratorState &iterator );
+      static const char *key( const IteratorState &iterator, bool &isStatic );
+      static Value &value( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+
+   private:
+      ValueInternalLink *buckets_;
+      ValueInternalLink *tailLink_;
+      BucketIndex bucketsSize_;
+      BucketIndex itemCount_;
+   };
+
+   /** \brief A simplified deque implementation used internally by Value.
+   * \internal
+   * It is based on a list of fixed "page", each page contains a fixed number of items.
+   * Instead of using a linked-list, a array of pointer is used for fast item look-up.
+   * Look-up for an element is as follow:
+   * - compute page index: pageIndex = itemIndex / itemsPerPage
+   * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
+   *
+   * Insertion is amortized constant time (only the array containing the index of pointers
+   * need to be reallocated when items are appended).
+   */
+   class JSON_API ValueInternalArray
+   {
+      friend class Value;
+      friend class ValueIteratorBase;
+   public:
+      enum { itemsPerPage = 8 };    // should be a power of 2 for fast divide and modulo.
+      typedef Value::ArrayIndex ArrayIndex;
+      typedef unsigned int PageIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState // Must be a POD
+      {
+         IteratorState() 
+            : array_(0)
+            , currentPageIndex_(0)
+            , currentItemIndex_(0) 
+         {
+         }
+         ValueInternalArray *array_;
+         Value **currentPageIndex_;
+         unsigned int currentItemIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalArray();
+      ValueInternalArray( const ValueInternalArray &other );
+      ValueInternalArray &operator =( const ValueInternalArray &other );
+      ~ValueInternalArray();
+      void swap( ValueInternalArray &other );
+
+      void clear();
+      void resize( ArrayIndex newSize );
+
+      Value &resolveReference( ArrayIndex index );
+
+      Value *find( ArrayIndex index ) const;
+
+      ArrayIndex size() const;
+
+      int compare( const ValueInternalArray &other ) const;
+
+   private:
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static Value &dereference( const IteratorState &iterator );
+      static Value &unsafeDereference( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+      static ArrayIndex indexOf( const IteratorState &iterator );
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      void makeIterator( IteratorState &it, ArrayIndex index ) const;
+
+      void makeIndexValid( ArrayIndex index );
+
+      Value **pages_;
+      ArrayIndex size_;
+      PageIndex pageCount_;
+   };
+
+   /** \brief Experimental: do not use. Allocator to customize Value internal array.
+    * Below is an example of a simple implementation (actual implementation use
+    * memory pool).
+      \code
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destruct( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+      \endcode
+    */ 
+   class JSON_API ValueArrayAllocator
+   {
+   public:
+      virtual ~ValueArrayAllocator();
+      virtual ValueInternalArray *newArray() = 0;
+      virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
+      virtual void destructArray( ValueInternalArray *array ) = 0;
+      /** \brief Reallocate array page index.
+       * Reallocates an array of pointer on each page.
+       * \param indexes [input] pointer on the current index. May be \c NULL.
+       *                [output] pointer on the new index of at least 
+       *                         \a minNewIndexCount pages. 
+       * \param indexCount [input] current number of pages in the index.
+       *                   [output] number of page the reallocated index can handle.
+       *                            \b MUST be >= \a minNewIndexCount.
+       * \param minNewIndexCount Minimum number of page the new index must be able to
+       *                         handle.
+       */
+      virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                             ValueInternalArray::PageIndex &indexCount,
+                                             ValueInternalArray::PageIndex minNewIndexCount ) = 0;
+      virtual void releaseArrayPageIndex( Value **indexes, 
+                                          ValueInternalArray::PageIndex indexCount ) = 0;
+      virtual Value *allocateArrayPage() = 0;
+      virtual void releaseArrayPage( Value *value ) = 0;
+   };
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+
+   /** \brief base class for Value iterators.
+    *
+    */
+   class ValueIteratorBase
+   {
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef ValueIteratorBase SelfType;
+
+      ValueIteratorBase();
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
+#else
+      ValueIteratorBase( const ValueInternalArray::IteratorState &state );
+      ValueIteratorBase( const ValueInternalMap::IteratorState &state );
+#endif
+
+      bool operator ==( const SelfType &other ) const
+      {
+         return isEqual( other );
+      }
+
+      bool operator !=( const SelfType &other ) const
+      {
+         return !isEqual( other );
+      }
+
+      difference_type operator -( const SelfType &other ) const
+      {
+         return computeDistance( other );
+      }
+
+      /// Return either the index or the member name of the referenced value as a Value.
+      Value key() const;
+
+      /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+      UInt index() const;
+
+      /// Return the member name of the referenced Value. "" if it is not an objectValue.
+      const char *memberName() const;
+
+   protected:
+      Value &deref() const;
+
+      void increment();
+
+      void decrement();
+
+      difference_type computeDistance( const SelfType &other ) const;
+
+      bool isEqual( const SelfType &other ) const;
+
+      void copy( const SelfType &other );
+
+   private:
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      Value::ObjectValues::iterator current_;
+      // Indicates that iterator is for a null value.
+      bool isNull_;
+#else
+      union
+      {
+         ValueInternalArray::IteratorState array_;
+         ValueInternalMap::IteratorState map_;
+      } iterator_;
+      bool isArray_;
+#endif
+   };
+
+   /** \brief const iterator for object and array value.
+    *
+    */
+   class ValueConstIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef const Value &reference;
+      typedef const Value *pointer;
+      typedef ValueConstIterator SelfType;
+
+      ValueConstIterator();
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueConstIterator( const ValueInternalArray::IteratorState &state );
+      ValueConstIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+      SelfType &operator =( const ValueIteratorBase &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+   /** \brief Iterator for object and array value.
+    */
+   class ValueIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef Value &reference;
+      typedef Value *pointer;
+      typedef ValueIterator SelfType;
+
+      ValueIterator();
+      ValueIterator( const ValueConstIterator &other );
+      ValueIterator( const ValueIterator &other );
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueIterator( const ValueInternalArray::IteratorState &state );
+      ValueIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+
+      SelfType &operator =( const SelfType &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+} // namespace Json
+
+
+#endif // CPPTL_JSON_H_INCLUDED
diff --git a/final/lib/JSON/include/json/writer.h b/final/lib/JSON/include/json/writer.h
new file mode 100644
index 0000000..83def71
--- /dev/null
+++ b/final/lib/JSON/include/json/writer.h
@@ -0,0 +1,173 @@
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+# include "value.h"
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   class Value;
+
+   /** \brief Abstract class for writers.
+    */
+   class JSON_API Writer
+   {
+   public:
+      virtual ~Writer();
+
+      virtual std::string write( const Value &root ) = 0;
+   };
+
+   /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+    *
+    * The JSON document is written in a single line. It is not intended for 'human' consumption,
+    * but may be useful to support feature such as RPC where bandwidth is limited.
+    * \sa Reader, Value
+    */
+   class JSON_API FastWriter : public Writer
+   {
+   public:
+      FastWriter();
+      virtual ~FastWriter(){}
+
+      void enableYAMLCompatibility();
+
+   public: // overridden from Writer
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+
+      std::string document_;
+      bool yamlCompatiblityEnabled_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledWriter: public Writer
+   {
+   public:
+      StyledWriter();
+      virtual ~StyledWriter(){}
+
+   public: // overridden from Writer
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param root Value to serialize.
+       * \return String containing the JSON document that represents the root value.
+       */
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::string document_;
+      std::string indentString_;
+      int rightMargin_;
+      int indentSize_;
+      bool addChildValues_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+        to a stream rather than to a string.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledStreamWriter
+   {
+   public:
+      StyledStreamWriter( std::string indentation="\t" );
+      ~StyledStreamWriter(){}
+
+   public:
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param out Stream to write to. (Can be ostringstream, e.g.)
+       * \param root Value to serialize.
+       * \note There is no point in deriving from Writer, since write() should not return a value.
+       */
+      void write( std::ostream &out, const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::ostream* document_;
+      std::string indentString_;
+      int rightMargin_;
+      std::string indentation_;
+      bool addChildValues_;
+   };
+
+   std::string JSON_API valueToString( Int value );
+   std::string JSON_API valueToString( UInt value );
+   std::string JSON_API valueToString( double value );
+   std::string JSON_API valueToString( bool value );
+   std::string JSON_API valueToQuotedString( const char *value );
+
+   /// \brief Output using the StyledStreamWriter.
+   /// \see Json::operator>>()
+   std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED
diff --git a/final/lib/JSON/json_batchallocator.h b/final/lib/JSON/json_batchallocator.h
new file mode 100644
index 0000000..87ea5ed
--- /dev/null
+++ b/final/lib/JSON/json_batchallocator.h
@@ -0,0 +1,125 @@
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ * 
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType
+        ,const unsigned int objectPerAllocation>
+class BatchAllocator
+{
+public:
+   typedef AllocatedType Type;
+
+   BatchAllocator( unsigned int objectsPerPage = 255 )
+      : freeHead_( 0 )
+      , objectsPerPage_( objectsPerPage )
+   {
+//      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+      assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
+      assert( objectsPerPage >= 16 );
+      batches_ = allocateBatch( 0 );   // allocated a dummy page
+      currentBatch_ = batches_;
+   }
+
+   ~BatchAllocator()
+   {
+      for ( BatchInfo *batch = batches_; batch;  )
+      {
+         BatchInfo *nextBatch = batch->next_;
+         free( batch );
+         batch = nextBatch;
+      }
+   }
+
+   /// allocate space for an array of objectPerAllocation object.
+   /// @warning it is the responsability of the caller to call objects constructors.
+   AllocatedType *allocate()
+   {
+      if ( freeHead_ ) // returns node from free list.
+      {
+         AllocatedType *object = freeHead_;
+         freeHead_ = *(AllocatedType **)object;
+         return object;
+      }
+      if ( currentBatch_->used_ == currentBatch_->end_ )
+      {
+         currentBatch_ = currentBatch_->next_;
+         while ( currentBatch_  &&  currentBatch_->used_ == currentBatch_->end_ )
+            currentBatch_ = currentBatch_->next_;
+
+         if ( !currentBatch_  ) // no free batch found, allocate a new one
+         { 
+            currentBatch_ = allocateBatch( objectsPerPage_ );
+            currentBatch_->next_ = batches_; // insert at the head of the list
+            batches_ = currentBatch_;
+         }
+      }
+      AllocatedType *allocated = currentBatch_->used_;
+      currentBatch_->used_ += objectPerAllocation;
+      return allocated;
+   }
+
+   /// Release the object.
+   /// @warning it is the responsability of the caller to actually destruct the object.
+   void release( AllocatedType *object )
+   {
+      assert( object != 0 );
+      *(AllocatedType **)object = freeHead_;
+      freeHead_ = object;
+   }
+
+private:
+   struct BatchInfo
+   {
+      BatchInfo *next_;
+      AllocatedType *used_;
+      AllocatedType *end_;
+      AllocatedType buffer_[objectPerAllocation];
+   };
+
+   // disabled copy constructor and assignement operator.
+   BatchAllocator( const BatchAllocator & );
+   void operator =( const BatchAllocator &);
+
+   static BatchInfo *allocateBatch( unsigned int objectsPerPage )
+   {
+      const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+                                + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+      BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
+      batch->next_ = 0;
+      batch->used_ = batch->buffer_;
+      batch->end_ = batch->buffer_ + objectsPerPage;
+      return batch;
+   }
+
+   BatchInfo *batches_;
+   BatchInfo *currentBatch_;
+   /// Head of a single linked list within the allocated space of freeed object
+   AllocatedType *freeHead_;
+   unsigned int objectsPerPage_;
+};
+
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
diff --git a/final/lib/JSON/json_internalarray.inl b/final/lib/JSON/json_internalarray.inl
new file mode 100644
index 0000000..9b985d2
--- /dev/null
+++ b/final/lib/JSON/json_internalarray.inl
@@ -0,0 +1,448 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueArrayAllocator::~ValueArrayAllocator()
+{
+}
+
+// //////////////////////////////////////////////////////////////////
+// class DefaultValueArrayAllocator
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destructArray( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+
+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      ValueInternalArray *array = arraysAllocator_.allocate();
+      new (array) ValueInternalArray(); // placement new
+      return array;
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      ValueInternalArray *array = arraysAllocator_.allocate();
+      new (array) ValueInternalArray( other ); // placement new
+      return array;
+   }
+
+   virtual void destructArray( ValueInternalArray *array )
+   {
+      if ( array )
+      {
+         array->~ValueInternalArray();
+         arraysAllocator_.release( array );
+      }
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( pagesAllocator_.allocate() );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         pagesAllocator_.release( value );
+   }
+private:
+   BatchAllocator<ValueInternalArray,1> arraysAllocator_;
+   BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
+};
+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+static ValueArrayAllocator *&arrayAllocator()
+{
+   static DefaultValueArrayAllocator defaultAllocator;
+   static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
+   return arrayAllocator;
+}
+
+static struct DummyArrayAllocatorInitializer {
+   DummyArrayAllocatorInitializer() 
+   {
+      arrayAllocator();      // ensure arrayAllocator() statics are initialized before main().
+   }
+} dummyArrayAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+bool 
+ValueInternalArray::equals( const IteratorState &x, 
+                            const IteratorState &other )
+{
+   return x.array_ == other.array_  
+          &&  x.currentItemIndex_ == other.currentItemIndex_  
+          &&  x.currentPageIndex_ == other.currentPageIndex_;
+}
+
+
+void 
+ValueInternalArray::increment( IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&
+      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+      != it.array_->size_,
+      "ValueInternalArray::increment(): moving iterator beyond end" );
+   ++(it.currentItemIndex_);
+   if ( it.currentItemIndex_ == itemsPerPage )
+   {
+      it.currentItemIndex_ = 0;
+      ++(it.currentPageIndex_);
+   }
+}
+
+
+void 
+ValueInternalArray::decrement( IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&  it.currentPageIndex_ == it.array_->pages_ 
+                        &&  it.currentItemIndex_ == 0,
+      "ValueInternalArray::decrement(): moving iterator beyond end" );
+   if ( it.currentItemIndex_ == 0 )
+   {
+      it.currentItemIndex_ = itemsPerPage-1;
+      --(it.currentPageIndex_);
+   }
+   else
+   {
+      --(it.currentItemIndex_);
+   }
+}
+
+
+Value &
+ValueInternalArray::unsafeDereference( const IteratorState &it )
+{
+   return (*(it.currentPageIndex_))[it.currentItemIndex_];
+}
+
+
+Value &
+ValueInternalArray::dereference( const IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&
+      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+      < it.array_->size_,
+      "ValueInternalArray::dereference(): dereferencing invalid iterator" );
+   return unsafeDereference( it );
+}
+
+void 
+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
+{
+   it.array_ = const_cast<ValueInternalArray *>( this );
+   it.currentItemIndex_ = 0;
+   it.currentPageIndex_ = pages_;
+}
+
+
+void 
+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
+{
+   it.array_ = const_cast<ValueInternalArray *>( this );
+   it.currentItemIndex_ = index % itemsPerPage;
+   it.currentPageIndex_ = pages_ + index / itemsPerPage;
+}
+
+
+void 
+ValueInternalArray::makeEndIterator( IteratorState &it ) const
+{
+   makeIterator( it, size_ );
+}
+
+
+ValueInternalArray::ValueInternalArray()
+   : pages_( 0 )
+   , size_( 0 )
+   , pageCount_( 0 )
+{
+}
+
+
+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
+   : pages_( 0 )
+   , pageCount_( 0 )
+   , size_( other.size_ )
+{
+   PageIndex minNewPages = other.size_ / itemsPerPage;
+   arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+   JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, 
+                        "ValueInternalArray::reserve(): bad reallocation" );
+   IteratorState itOther;
+   other.makeBeginIterator( itOther );
+   Value *value;
+   for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
+   {
+      if ( index % itemsPerPage == 0 )
+      {
+         PageIndex pageIndex = index / itemsPerPage;
+         value = arrayAllocator()->allocateArrayPage();
+         pages_[pageIndex] = value;
+      }
+      new (value) Value( dereference( itOther ) );
+   }
+}
+
+
+ValueInternalArray &
+ValueInternalArray::operator =( const ValueInternalArray &other )
+{
+   ValueInternalArray temp( other );
+   swap( temp );
+   return *this;
+}
+
+
+ValueInternalArray::~ValueInternalArray()
+{
+   // destroy all constructed items
+   IteratorState it;
+   IteratorState itEnd;
+   makeBeginIterator( it);
+   makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      Value *value = &dereference(it);
+      value->~Value();
+   }
+   // release all pages
+   PageIndex lastPageIndex = size_ / itemsPerPage;
+   for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
+      arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+   // release pages index
+   arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
+}
+
+
+void 
+ValueInternalArray::swap( ValueInternalArray &other )
+{
+   Value **tempPages = pages_;
+   pages_ = other.pages_;
+   other.pages_ = tempPages;
+   ArrayIndex tempSize = size_;
+   size_ = other.size_;
+   other.size_ = tempSize;
+   PageIndex tempPageCount = pageCount_;
+   pageCount_ = other.pageCount_;
+   other.pageCount_ = tempPageCount;
+}
+
+void 
+ValueInternalArray::clear()
+{
+   ValueInternalArray dummy;
+   swap( dummy );
+}
+
+
+void 
+ValueInternalArray::resize( ArrayIndex newSize )
+{
+   if ( newSize == 0 )
+      clear();
+   else if ( newSize < size_ )
+   {
+      IteratorState it;
+      IteratorState itEnd;
+      makeIterator( it, newSize );
+      makeIterator( itEnd, size_ );
+      for ( ; !equals(it,itEnd); increment(it) )
+      {
+         Value *value = &dereference(it);
+         value->~Value();
+      }
+      PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
+      PageIndex lastPageIndex = size_ / itemsPerPage;
+      for ( ; pageIndex < lastPageIndex; ++pageIndex )
+         arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+      size_ = newSize;
+   }
+   else if ( newSize > size_ )
+      resolveReference( newSize );
+}
+
+
+void 
+ValueInternalArray::makeIndexValid( ArrayIndex index )
+{
+   // Need to enlarge page index ?
+   if ( index >= pageCount_ * itemsPerPage )
+   {
+      PageIndex minNewPages = (index + 1) / itemsPerPage;
+      arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+      JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
+   }
+
+   // Need to allocate new pages ?
+   ArrayIndex nextPageIndex = 
+      (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
+                                  : size_;
+   if ( nextPageIndex <= index )
+   {
+      PageIndex pageIndex = nextPageIndex / itemsPerPage;
+      PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
+      for ( ; pageToAllocate-- > 0; ++pageIndex )
+         pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
+   }
+
+   // Initialize all new entries
+   IteratorState it;
+   IteratorState itEnd;
+   makeIterator( it, size_ );
+   size_ = index + 1;
+   makeIterator( itEnd, size_ );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      Value *value = &dereference(it);
+      new (value) Value(); // Construct a default value using placement new
+   }
+}
+
+Value &
+ValueInternalArray::resolveReference( ArrayIndex index )
+{
+   if ( index >= size_ )
+      makeIndexValid( index );
+   return pages_[index/itemsPerPage][index%itemsPerPage];
+}
+
+Value *
+ValueInternalArray::find( ArrayIndex index ) const
+{
+   if ( index >= size_ )
+      return 0;
+   return &(pages_[index/itemsPerPage][index%itemsPerPage]);
+}
+
+ValueInternalArray::ArrayIndex 
+ValueInternalArray::size() const
+{
+   return size_;
+}
+
+int 
+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
+{
+   return indexOf(y) - indexOf(x);
+}
+
+
+ValueInternalArray::ArrayIndex 
+ValueInternalArray::indexOf( const IteratorState &iterator )
+{
+   if ( !iterator.array_ )
+      return ArrayIndex(-1);
+   return ArrayIndex(
+      (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage 
+      + iterator.currentItemIndex_ );
+}
+
+
+int 
+ValueInternalArray::compare( const ValueInternalArray &other ) const
+{
+   int sizeDiff( size_ - other.size_ );
+   if ( sizeDiff != 0 )
+      return sizeDiff;
+   
+   for ( ArrayIndex index =0; index < size_; ++index )
+   {
+      int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( 
+         other.pages_[index/itemsPerPage][index%itemsPerPage] );
+      if ( diff != 0 )
+         return diff;
+   }
+   return 0;
+}
diff --git a/final/lib/JSON/json_internalmap.inl b/final/lib/JSON/json_internalmap.inl
new file mode 100644
index 0000000..1977148
--- /dev/null
+++ b/final/lib/JSON/json_internalmap.inl
@@ -0,0 +1,607 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalMap
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
+   * This optimization is used by the fast allocator.
+   */
+ValueInternalLink::ValueInternalLink()
+   : previous_( 0 )
+   , next_( 0 )
+{
+}
+
+ValueInternalLink::~ValueInternalLink()
+{ 
+   for ( int index =0; index < itemPerLink; ++index )
+   {
+      if ( !items_[index].isItemAvailable() )
+      {
+         if ( !items_[index].isMemberNameStatic() )
+            free( keys_[index] );
+      }
+      else
+         break;
+   }
+}
+
+
+
+ValueMapAllocator::~ValueMapAllocator()
+{
+}
+
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+   virtual ValueInternalMap *newMap()
+   {
+      return new ValueInternalMap();
+   }
+
+   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+   {
+      return new ValueInternalMap( other );
+   }
+
+   virtual void destructMap( ValueInternalMap *map )
+   {
+      delete map;
+   }
+
+   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+   {
+      return new ValueInternalLink[size];
+   }
+
+   virtual void releaseMapBuckets( ValueInternalLink *links )
+   {
+      delete [] links;
+   }
+
+   virtual ValueInternalLink *allocateMapLink()
+   {
+      return new ValueInternalLink();
+   }
+
+   virtual void releaseMapLink( ValueInternalLink *link )
+   {
+      delete link;
+   }
+};
+#else
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+   virtual ValueInternalMap *newMap()
+   {
+      ValueInternalMap *map = mapsAllocator_.allocate();
+      new (map) ValueInternalMap(); // placement new
+      return map;
+   }
+
+   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+   {
+      ValueInternalMap *map = mapsAllocator_.allocate();
+      new (map) ValueInternalMap( other ); // placement new
+      return map;
+   }
+
+   virtual void destructMap( ValueInternalMap *map )
+   {
+      if ( map )
+      {
+         map->~ValueInternalMap();
+         mapsAllocator_.release( map );
+      }
+   }
+
+   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+   {
+      return new ValueInternalLink[size];
+   }
+
+   virtual void releaseMapBuckets( ValueInternalLink *links )
+   {
+      delete [] links;
+   }
+
+   virtual ValueInternalLink *allocateMapLink()
+   {
+      ValueInternalLink *link = linksAllocator_.allocate();
+      memset( link, 0, sizeof(ValueInternalLink) );
+      return link;
+   }
+
+   virtual void releaseMapLink( ValueInternalLink *link )
+   {
+      link->~ValueInternalLink();
+      linksAllocator_.release( link );
+   }
+private:
+   BatchAllocator<ValueInternalMap,1> mapsAllocator_;
+   BatchAllocator<ValueInternalLink,1> linksAllocator_;
+};
+#endif
+
+static ValueMapAllocator *&mapAllocator()
+{
+   static DefaultValueMapAllocator defaultAllocator;
+   static ValueMapAllocator *mapAllocator = &defaultAllocator;
+   return mapAllocator;
+}
+
+static struct DummyMapAllocatorInitializer {
+   DummyMapAllocatorInitializer() 
+   {
+      mapAllocator();      // ensure mapAllocator() statics are initialized before main().
+   }
+} dummyMapAllocatorInitializer;
+
+
+
+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
+
+/*
+use linked list hash map. 
+buckets array is a container.
+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
+value have extra state: valid, available, deleted
+*/
+
+
+ValueInternalMap::ValueInternalMap()
+   : buckets_( 0 )
+   , tailLink_( 0 )
+   , bucketsSize_( 0 )
+   , itemCount_( 0 )
+{
+}
+
+
+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
+   : buckets_( 0 )
+   , tailLink_( 0 )
+   , bucketsSize_( 0 )
+   , itemCount_( 0 )
+{
+   reserve( other.itemCount_ );
+   IteratorState it;
+   IteratorState itEnd;
+   other.makeBeginIterator( it );
+   other.makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      bool isStatic;
+      const char *memberName = key( it, isStatic );
+      const Value &aValue = value( it );
+      resolveReference(memberName, isStatic) = aValue;
+   }
+}
+
+
+ValueInternalMap &
+ValueInternalMap::operator =( const ValueInternalMap &other )
+{
+   ValueInternalMap dummy( other );
+   swap( dummy );
+   return *this;
+}
+
+
+ValueInternalMap::~ValueInternalMap()
+{
+   if ( buckets_ )
+   {
+      for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
+      {
+         ValueInternalLink *link = buckets_[bucketIndex].next_;
+         while ( link )
+         {
+            ValueInternalLink *linkToRelease = link;
+            link = link->next_;
+            mapAllocator()->releaseMapLink( linkToRelease );
+         }
+      }
+      mapAllocator()->releaseMapBuckets( buckets_ );
+   }
+}
+
+
+void 
+ValueInternalMap::swap( ValueInternalMap &other )
+{
+   ValueInternalLink *tempBuckets = buckets_;
+   buckets_ = other.buckets_;
+   other.buckets_ = tempBuckets;
+   ValueInternalLink *tempTailLink = tailLink_;
+   tailLink_ = other.tailLink_;
+   other.tailLink_ = tempTailLink;
+   BucketIndex tempBucketsSize = bucketsSize_;
+   bucketsSize_ = other.bucketsSize_;
+   other.bucketsSize_ = tempBucketsSize;
+   BucketIndex tempItemCount = itemCount_;
+   itemCount_ = other.itemCount_;
+   other.itemCount_ = tempItemCount;
+}
+
+
+void 
+ValueInternalMap::clear()
+{
+   ValueInternalMap dummy;
+   swap( dummy );
+}
+
+
+ValueInternalMap::BucketIndex 
+ValueInternalMap::size() const
+{
+   return itemCount_;
+}
+
+bool 
+ValueInternalMap::reserveDelta( BucketIndex growth )
+{
+   return reserve( itemCount_ + growth );
+}
+
+bool 
+ValueInternalMap::reserve( BucketIndex newItemCount )
+{
+   if ( !buckets_  &&  newItemCount > 0 )
+   {
+      buckets_ = mapAllocator()->allocateMapBuckets( 1 );
+      bucketsSize_ = 1;
+      tailLink_ = &buckets_[0];
+   }
+//   BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
+   return true;
+}
+
+
+const Value *
+ValueInternalMap::find( const char *key ) const
+{
+   if ( !bucketsSize_ )
+      return 0;
+   HashKey hashedKey = hash( key );
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   for ( const ValueInternalLink *current = &buckets_[bucketIndex]; 
+         current != 0; 
+         current = current->next_ )
+   {
+      for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
+      {
+         if ( current->items_[index].isItemAvailable() )
+            return 0;
+         if ( strcmp( key, current->keys_[index] ) == 0 )
+            return &current->items_[index];
+      }
+   }
+   return 0;
+}
+
+
+Value *
+ValueInternalMap::find( const char *key )
+{
+   const ValueInternalMap *constThis = this;
+   return const_cast<Value *>( constThis->find( key ) );
+}
+
+
+Value &
+ValueInternalMap::resolveReference( const char *key,
+                                    bool isStatic )
+{
+   HashKey hashedKey = hash( key );
+   if ( bucketsSize_ )
+   {
+      BucketIndex bucketIndex = hashedKey % bucketsSize_;
+      ValueInternalLink **previous = 0;
+      BucketIndex index;
+      for ( ValueInternalLink *current = &buckets_[bucketIndex]; 
+            current != 0; 
+            previous = &current->next_, current = current->next_ )
+      {
+         for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
+         {
+            if ( current->items_[index].isItemAvailable() )
+               return setNewItem( key, isStatic, current, index );
+            if ( strcmp( key, current->keys_[index] ) == 0 )
+               return current->items_[index];
+         }
+      }
+   }
+
+   reserveDelta( 1 );
+   return unsafeAdd( key, isStatic, hashedKey );
+}
+
+
+void 
+ValueInternalMap::remove( const char *key )
+{
+   HashKey hashedKey = hash( key );
+   if ( !bucketsSize_ )
+      return;
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   for ( ValueInternalLink *link = &buckets_[bucketIndex]; 
+         link != 0; 
+         link = link->next_ )
+   {
+      BucketIndex index;
+      for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+      {
+         if ( link->items_[index].isItemAvailable() )
+            return;
+         if ( strcmp( key, link->keys_[index] ) == 0 )
+         {
+            doActualRemove( link, index, bucketIndex );
+            return;
+         }
+      }
+   }
+}
+
+void 
+ValueInternalMap::doActualRemove( ValueInternalLink *link, 
+                                  BucketIndex index,
+                                  BucketIndex bucketIndex )
+{
+   // find last item of the bucket and swap it with the 'removed' one.
+   // set removed items flags to 'available'.
+   // if last page only contains 'available' items, then desallocate it (it's empty)
+   ValueInternalLink *&lastLink = getLastLinkInBucket( index );
+   BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
+   for ( ;   
+         lastItemIndex < ValueInternalLink::itemPerLink; 
+         ++lastItemIndex ) // may be optimized with dicotomic search
+   {
+      if ( lastLink->items_[lastItemIndex].isItemAvailable() )
+         break;
+   }
+   
+   BucketIndex lastUsedIndex = lastItemIndex - 1;
+   Value *valueToDelete = &link->items_[index];
+   Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
+   if ( valueToDelete != valueToPreserve )
+      valueToDelete->swap( *valueToPreserve );
+   if ( lastUsedIndex == 0 )  // page is now empty
+   {  // remove it from bucket linked list and delete it.
+      ValueInternalLink *linkPreviousToLast = lastLink->previous_;
+      if ( linkPreviousToLast != 0 )   // can not deleted bucket link.
+      {
+         mapAllocator()->releaseMapLink( lastLink );
+         linkPreviousToLast->next_ = 0;
+         lastLink = linkPreviousToLast;
+      }
+   }
+   else
+   {
+      Value dummy;
+      valueToPreserve->swap( dummy ); // restore deleted to default Value.
+      valueToPreserve->setItemUsed( false );
+   }
+   --itemCount_;
+}
+
+
+ValueInternalLink *&
+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
+{
+   if ( bucketIndex == bucketsSize_ - 1 )
+      return tailLink_;
+   ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
+   if ( !previous )
+      previous = &buckets_[bucketIndex];
+   return previous;
+}
+
+
+Value &
+ValueInternalMap::setNewItem( const char *key, 
+                              bool isStatic,
+                              ValueInternalLink *link, 
+                              BucketIndex index )
+{
+   char *duplicatedKey = valueAllocator()->makeMemberName( key );
+   ++itemCount_;
+   link->keys_[index] = duplicatedKey;
+   link->items_[index].setItemUsed();
+   link->items_[index].setMemberNameIsStatic( isStatic );
+   return link->items_[index]; // items already default constructed.
+}
+
+
+Value &
+ValueInternalMap::unsafeAdd( const char *key, 
+                             bool isStatic, 
+                             HashKey hashedKey )
+{
+   JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
+   ValueInternalLink *link = previousLink;
+   BucketIndex index;
+   for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+   {
+      if ( link->items_[index].isItemAvailable() )
+         break;
+   }
+   if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
+   {
+      ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
+      index = 0;
+      link->next_ = newLink;
+      previousLink = newLink;
+      link = newLink;
+   }
+   return setNewItem( key, isStatic, link, index );
+}
+
+
+ValueInternalMap::HashKey 
+ValueInternalMap::hash( const char *key ) const
+{
+   HashKey hash = 0;
+   while ( *key )
+      hash += *key++ * 37;
+   return hash;
+}
+
+
+int 
+ValueInternalMap::compare( const ValueInternalMap &other ) const
+{
+   int sizeDiff( itemCount_ - other.itemCount_ );
+   if ( sizeDiff != 0 )
+      return sizeDiff;
+   // Strict order guaranty is required. Compare all keys FIRST, then compare values.
+   IteratorState it;
+   IteratorState itEnd;
+   makeBeginIterator( it );
+   makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      if ( !other.find( key( it ) ) )
+         return 1;
+   }
+
+   // All keys are equals, let's compare values
+   makeBeginIterator( it );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      const Value *otherValue = other.find( key( it ) );
+      int valueDiff = value(it).compare( *otherValue );
+      if ( valueDiff != 0 )
+         return valueDiff;
+   }
+   return 0;
+}
+
+
+void 
+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
+{
+   it.map_ = const_cast<ValueInternalMap *>( this );
+   it.bucketIndex_ = 0;
+   it.itemIndex_ = 0;
+   it.link_ = buckets_;
+}
+
+
+void 
+ValueInternalMap::makeEndIterator( IteratorState &it ) const
+{
+   it.map_ = const_cast<ValueInternalMap *>( this );
+   it.bucketIndex_ = bucketsSize_;
+   it.itemIndex_ = 0;
+   it.link_ = 0;
+}
+
+
+bool 
+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
+{
+   return x.map_ == other.map_  
+          &&  x.bucketIndex_ == other.bucketIndex_  
+          &&  x.link_ == other.link_
+          &&  x.itemIndex_ == other.itemIndex_;
+}
+
+
+void 
+ValueInternalMap::incrementBucket( IteratorState &iterator )
+{
+   ++iterator.bucketIndex_;
+   JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
+      "ValueInternalMap::increment(): attempting to iterate beyond end." );
+   if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
+      iterator.link_ = 0;
+   else
+      iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
+   iterator.itemIndex_ = 0;
+}
+
+
+void 
+ValueInternalMap::increment( IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
+   ++iterator.itemIndex_;
+   if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
+   {
+      JSON_ASSERT_MESSAGE( iterator.link_ != 0,
+         "ValueInternalMap::increment(): attempting to iterate beyond end." );
+      iterator.link_ = iterator.link_->next_;
+      if ( iterator.link_ == 0 )
+         incrementBucket( iterator );
+   }
+   else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
+   {
+      incrementBucket( iterator );
+   }
+}
+
+
+void 
+ValueInternalMap::decrement( IteratorState &iterator )
+{
+   if ( iterator.itemIndex_ == 0 )
+   {
+      JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
+      if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
+      {
+         JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
+         --(iterator.bucketIndex_);
+      }
+      iterator.link_ = iterator.link_->previous_;
+      iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
+   }
+}
+
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
+   return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+
+Value &
+ValueInternalMap::value( const IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   return iterator.link_->items_[iterator.itemIndex_];
+}
+
+
+int 
+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
+{
+   int offset = 0;
+   IteratorState it = x;
+   while ( !equals( it, y ) )
+      increment( it );
+   return offset;
+}
diff --git a/final/lib/JSON/json_reader.cpp b/final/lib/JSON/json_reader.cpp
new file mode 100644
index 0000000..680c2b6
--- /dev/null
+++ b/final/lib/JSON/json_reader.cpp
@@ -0,0 +1,890 @@
+#include <json/reader.h>
+#include <json/value.h>
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+   : allowComments_( true )
+   , strictRoot_( false )
+{
+}
+
+
+Features 
+Features::all()
+{
+   return Features();
+}
+
+
+Features 
+Features::strictMode()
+{
+   Features features;
+   features.allowComments_ = false;
+   features.strictRoot_ = true;
+   return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4;
+}
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4  ||  c == c5;
+}
+
+
+static bool 
+containsNewLine( Reader::Location begin, 
+                 Reader::Location end )
+{
+   for ( ;begin < end; ++begin )
+      if ( *begin == '\n'  ||  *begin == '\r' )
+         return true;
+   return false;
+}
+
+static std::string codePointToUTF8(unsigned int cp)
+{
+   std::string result;
+   
+   // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+   if (cp <= 0x7f) 
+   {
+      result.resize(1);
+      result[0] = static_cast<char>(cp);
+   } 
+   else if (cp <= 0x7FF) 
+   {
+      result.resize(2);
+      result[1] = static_cast<char>(0x80 | (0x3f & cp));
+      result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+   } 
+   else if (cp <= 0xFFFF) 
+   {
+      result.resize(3);
+      result[2] = static_cast<char>(0x80 | (0x3f & cp));
+      result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
+      result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+   }
+   else if (cp <= 0x10FFFF) 
+   {
+      result.resize(4);
+      result[3] = static_cast<char>(0x80 | (0x3f & cp));
+      result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+      result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+      result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+   }
+
+   return result;
+}
+
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+   : features_( Features::all() )
+{
+}
+
+
+Reader::Reader( const Features &features )
+   : features_( features )
+{
+}
+
+
+bool
+Reader::parse( const std::string &document, 
+               Value &root,
+               bool collectComments )
+{
+   document_ = document;
+   const char *begin = document_.c_str();
+   const char *end = begin + document_.length();
+   return parse( begin, end, root, collectComments );
+}
+
+
+bool
+Reader::parse( std::istream& sin,
+               Value &root,
+               bool collectComments )
+{
+   //std::istream_iterator<char> begin(sin);
+   //std::istream_iterator<char> end;
+   // Those would allow streamed input from a file, if parse() were a
+   // template function.
+
+   // Since std::string is reference-counted, this at least does not
+   // create an extra copy.
+   std::string doc;
+   std::getline(sin, doc, (char)EOF);
+   return parse( doc, root, collectComments );
+}
+
+bool 
+Reader::parse( const char *beginDoc, const char *endDoc, 
+               Value &root,
+               bool collectComments )
+{
+   if ( !features_.allowComments_ )
+   {
+      collectComments = false;
+   }
+
+   begin_ = beginDoc;
+   end_ = endDoc;
+   collectComments_ = collectComments;
+   current_ = begin_;
+   lastValueEnd_ = 0;
+   lastValue_ = 0;
+   commentsBefore_ = "";
+   errors_.clear();
+   while ( !nodes_.empty() )
+      nodes_.pop();
+   nodes_.push( &root );
+   
+   bool successful = readValue();
+   Token token;
+   skipCommentTokens( token );
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+      root.setComment( commentsBefore_, commentAfter );
+   if ( features_.strictRoot_ )
+   {
+      if ( !root.isArray()  &&  !root.isObject() )
+      {
+         // Set error location to start of doc, ideally should be first token found in doc
+         token.type_ = tokenError;
+         token.start_ = beginDoc;
+         token.end_ = endDoc;
+         addError( "A valid JSON document must be either an array or an object value.",
+                   token );
+         return false;
+      }
+   }
+   return successful;
+}
+
+
+bool
+Reader::readValue()
+{
+   Token token;
+   skipCommentTokens( token );
+   bool successful = true;
+
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+   {
+      currentValue().setComment( commentsBefore_, commentBefore );
+      commentsBefore_ = "";
+   }
+
+
+   switch ( token.type_ )
+   {
+   case tokenObjectBegin:
+      successful = readObject( token );
+      break;
+   case tokenArrayBegin:
+      successful = readArray( token );
+      break;
+   case tokenNumber:
+      successful = decodeNumber( token );
+      break;
+   case tokenString:
+      successful = decodeString( token );
+      break;
+   case tokenTrue:
+      currentValue() = true;
+      break;
+   case tokenFalse:
+      currentValue() = false;
+      break;
+   case tokenNull:
+      currentValue() = Value();
+      break;
+   default:
+      return addError( "Syntax error: value, object or array expected.", token );
+   }
+
+   if ( collectComments_ )
+   {
+      lastValueEnd_ = current_;
+      lastValue_ = &currentValue();
+   }
+
+   return successful;
+}
+
+
+void 
+Reader::skipCommentTokens( Token &token )
+{
+   if ( features_.allowComments_ )
+   {
+      do
+      {
+         readToken( token );
+      }
+      while ( token.type_ == tokenComment );
+   }
+   else
+   {
+      readToken( token );
+   }
+}
+
+
+bool 
+Reader::expectToken( TokenType type, Token &token, const char *message )
+{
+   readToken( token );
+   if ( token.type_ != type )
+      return addError( message, token );
+   return true;
+}
+
+
+bool 
+Reader::readToken( Token &token )
+{
+   skipSpaces();
+   token.start_ = current_;
+   Char c = getNextChar();
+   bool ok = true;
+   switch ( c )
+   {
+   case '{':
+      token.type_ = tokenObjectBegin;
+      break;
+   case '}':
+      token.type_ = tokenObjectEnd;
+      break;
+   case '[':
+      token.type_ = tokenArrayBegin;
+      break;
+   case ']':
+      token.type_ = tokenArrayEnd;
+      break;
+   case '"':
+      token.type_ = tokenString;
+      ok = readString();
+      break;
+   case '/':
+      token.type_ = tokenComment;
+      ok = readComment();
+      break;
+   case '0':
+   case '1':
+   case '2':
+   case '3':
+   case '4':
+   case '5':
+   case '6':
+   case '7':
+   case '8':
+   case '9':
+   case '-':
+      token.type_ = tokenNumber;
+      readNumber();
+      break;
+   case 't':
+      token.type_ = tokenTrue;
+      ok = match( "rue", 3 );
+      break;
+   case 'f':
+      token.type_ = tokenFalse;
+      ok = match( "alse", 4 );
+      break;
+   case 'n':
+      token.type_ = tokenNull;
+      ok = match( "ull", 3 );
+      break;
+   case ',':
+      token.type_ = tokenArraySeparator;
+      break;
+   case ':':
+      token.type_ = tokenMemberSeparator;
+      break;
+   case 0:
+      token.type_ = tokenEndOfStream;
+      break;
+   default:
+      ok = false;
+      break;
+   }
+   if ( !ok )
+      token.type_ = tokenError;
+   token.end_ = current_;
+   return true;
+}
+
+
+void 
+Reader::skipSpaces()
+{
+   while ( current_ != end_ )
+   {
+      Char c = *current_;
+      if ( c == ' '  ||  c == '\t'  ||  c == '\r'  ||  c == '\n' )
+         ++current_;
+      else
+         break;
+   }
+}
+
+
+bool 
+Reader::match( Location pattern, 
+               int patternLength )
+{
+   if ( end_ - current_ < patternLength )
+      return false;
+   int index = patternLength;
+   while ( index-- )
+      if ( current_[index] != pattern[index] )
+         return false;
+   current_ += patternLength;
+   return true;
+}
+
+
+bool
+Reader::readComment()
+{
+   Location commentBegin = current_ - 1;
+   Char c = getNextChar();
+   bool successful = false;
+   if ( c == '*' )
+      successful = readCStyleComment();
+   else if ( c == '/' )
+      successful = readCppStyleComment();
+   if ( !successful )
+      return false;
+
+   if ( collectComments_ )
+   {
+      CommentPlacement placement = commentBefore;
+      if ( lastValueEnd_  &&  !containsNewLine( lastValueEnd_, commentBegin ) )
+      {
+         if ( c != '*'  ||  !containsNewLine( commentBegin, current_ ) )
+            placement = commentAfterOnSameLine;
+      }
+
+      addComment( commentBegin, current_, placement );
+   }
+   return true;
+}
+
+
+void 
+Reader::addComment( Location begin, 
+                    Location end, 
+                    CommentPlacement placement )
+{
+   assert( collectComments_ );
+   if ( placement == commentAfterOnSameLine )
+   {
+      assert( lastValue_ != 0 );
+      lastValue_->setComment( std::string( begin, end ), placement );
+   }
+   else
+   {
+      if ( !commentsBefore_.empty() )
+         commentsBefore_ += "\n";
+      commentsBefore_ += std::string( begin, end );
+   }
+}
+
+
+bool 
+Reader::readCStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if ( c == '*'  &&  *current_ == '/' )
+         break;
+   }
+   return getNextChar() == '/';
+}
+
+
+bool 
+Reader::readCppStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if (  c == '\r'  ||  c == '\n' )
+         break;
+   }
+   return true;
+}
+
+
+void 
+Reader::readNumber()
+{
+   while ( current_ != end_ )
+   {
+      if ( !(*current_ >= '0'  &&  *current_ <= '9')  &&
+           !in( *current_, '.', 'e', 'E', '+', '-' ) )
+         break;
+      ++current_;
+   }
+}
+
+bool
+Reader::readString()
+{
+   Char c = 0;
+   while ( current_ != end_ )
+   {
+      c = getNextChar();
+      if ( c == '\\' )
+         getNextChar();
+      else if ( c == '"' )
+         break;
+   }
+   return c == '"';
+}
+
+
+bool 
+Reader::readObject( Token &tokenStart )
+{
+   Token tokenName;
+   std::string name;
+   currentValue() = Value( objectValue );
+   while ( readToken( tokenName ) )
+   {
+      bool initialTokenOk = true;
+      while ( tokenName.type_ == tokenComment  &&  initialTokenOk )
+         initialTokenOk = readToken( tokenName );
+      if  ( !initialTokenOk )
+         break;
+      if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
+         return true;
+      if ( tokenName.type_ != tokenString )
+         break;
+      
+      name = "";
+      if ( !decodeString( tokenName, name ) )
+         return recoverFromError( tokenObjectEnd );
+
+      Token colon;
+      if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
+      {
+         return addErrorAndRecover( "Missing ':' after object member name", 
+                                    colon, 
+                                    tokenObjectEnd );
+      }
+      Value &value = currentValue()[ name ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenObjectEnd );
+
+      Token comma;
+      if ( !readToken( comma )
+            ||  ( comma.type_ != tokenObjectEnd  &&  
+                  comma.type_ != tokenArraySeparator &&
+		  comma.type_ != tokenComment ) )
+      {
+         return addErrorAndRecover( "Missing ',' or '}' in object declaration", 
+                                    comma, 
+                                    tokenObjectEnd );
+      }
+      bool finalizeTokenOk = true;
+      while ( comma.type_ == tokenComment &&
+              finalizeTokenOk )
+         finalizeTokenOk = readToken( comma );
+      if ( comma.type_ == tokenObjectEnd )
+         return true;
+   }
+   return addErrorAndRecover( "Missing '}' or object member name", 
+                              tokenName, 
+                              tokenObjectEnd );
+}
+
+
+bool 
+Reader::readArray( Token &tokenStart )
+{
+   currentValue() = Value( arrayValue );
+   skipSpaces();
+   if ( *current_ == ']' ) // empty array
+   {
+      Token endArray;
+      readToken( endArray );
+      return true;
+   }
+   int index = 0;
+   while ( true )
+   {
+      Value &value = currentValue()[ index++ ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenArrayEnd );
+
+      Token token;
+      // Accept Comment after last item in the array.
+      ok = readToken( token );
+      while ( token.type_ == tokenComment  &&  ok )
+      {
+         ok = readToken( token );
+      }
+      bool badTokenType = ( token.type_ == tokenArraySeparator  &&  
+                            token.type_ == tokenArrayEnd );
+      if ( !ok  ||  badTokenType )
+      {
+         return addErrorAndRecover( "Missing ',' or ']' in array declaration", 
+                                    token, 
+                                    tokenArrayEnd );
+      }
+      if ( token.type_ == tokenArrayEnd )
+         break;
+   }
+   return true;
+}
+
+
+bool 
+Reader::decodeNumber( Token &token )
+{
+   bool isDouble = false;
+   for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
+   {
+      isDouble = isDouble  
+                 ||  in( *inspect, '.', 'e', 'E', '+' )  
+                 ||  ( *inspect == '-'  &&  inspect != token.start_ );
+   }
+   if ( isDouble )
+      return decodeDouble( token );
+   Location current = token.start_;
+   bool isNegative = *current == '-';
+   if ( isNegative )
+      ++current;
+   Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) 
+                                       : Value::maxUInt) / 10;
+   Value::UInt value = 0;
+   while ( current < token.end_ )
+   {
+      Char c = *current++;
+      if ( c < '0'  ||  c > '9' )
+         return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+      if ( value >= threshold )
+         return decodeDouble( token );
+      value = value * 10 + Value::UInt(c - '0');
+   }
+   if ( isNegative )
+      currentValue() = -Value::Int( value );
+   else if ( value <= Value::UInt(Value::maxInt) )
+      currentValue() = Value::Int( value );
+   else
+      currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeDouble( Token &token )
+{
+   double value = 0;
+   const int bufferSize = 32;
+   int count;
+   int length = int(token.end_ - token.start_);
+   if ( length <= bufferSize )
+   {
+      Char buffer[bufferSize];
+      memcpy( buffer, token.start_, length );
+      buffer[length] = 0;
+      count = sscanf( buffer, "%lf", &value );
+   }
+   else
+   {
+      std::string buffer( token.start_, token.end_ );
+      count = sscanf( buffer.c_str(), "%lf", &value );
+   }
+
+   if ( count != 1 )
+      return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+   currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token )
+{
+   std::string decoded;
+   if ( !decodeString( token, decoded ) )
+      return false;
+   currentValue() = decoded;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token, std::string &decoded )
+{
+   decoded.reserve( token.end_ - token.start_ - 2 );
+   Location current = token.start_ + 1; // skip '"'
+   Location end = token.end_ - 1;      // do not include '"'
+   while ( current != end )
+   {
+      Char c = *current++;
+      if ( c == '"' )
+         break;
+      else if ( c == '\\' )
+      {
+         if ( current == end )
+            return addError( "Empty escape sequence in string", token, current );
+         Char escape = *current++;
+         switch ( escape )
+         {
+         case '"': decoded += '"'; break;
+         case '/': decoded += '/'; break;
+         case '\\': decoded += '\\'; break;
+         case 'b': decoded += '\b'; break;
+         case 'f': decoded += '\f'; break;
+         case 'n': decoded += '\n'; break;
+         case 'r': decoded += '\r'; break;
+         case 't': decoded += '\t'; break;
+         case 'u':
+            {
+               unsigned int unicode;
+               if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
+                  return false;
+               decoded += codePointToUTF8(unicode);
+            }
+            break;
+         default:
+            return addError( "Bad escape sequence in string", token, current );
+         }
+      }
+      else
+      {
+         decoded += c;
+      }
+   }
+   return true;
+}
+
+bool
+Reader::decodeUnicodeCodePoint( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+
+   if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
+      return false;
+   if (unicode >= 0xD800 && unicode <= 0xDBFF)
+   {
+      // surrogate pairs
+      if (end - current < 6)
+         return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
+      unsigned int surrogatePair;
+      if (*(current++) == '\\' && *(current++)== 'u')
+      {
+         if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
+         {
+            unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+         } 
+         else
+            return false;
+      } 
+      else
+         return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
+   }
+   return true;
+}
+
+bool 
+Reader::decodeUnicodeEscapeSequence( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+   if ( end - current < 4 )
+      return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
+   unicode = 0;
+   for ( int index =0; index < 4; ++index )
+   {
+      Char c = *current++;
+      unicode *= 16;
+      if ( c >= '0'  &&  c <= '9' )
+         unicode += c - '0';
+      else if ( c >= 'a'  &&  c <= 'f' )
+         unicode += c - 'a' + 10;
+      else if ( c >= 'A'  &&  c <= 'F' )
+         unicode += c - 'A' + 10;
+      else
+         return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
+   }
+   return true;
+}
+
+
+bool 
+Reader::addError( const std::string &message, 
+                  Token &token,
+                  Location extra )
+{
+   ErrorInfo info;
+   info.token_ = token;
+   info.message_ = message;
+   info.extra_ = extra;
+   errors_.push_back( info );
+   return false;
+}
+
+
+bool 
+Reader::recoverFromError( TokenType skipUntilToken )
+{
+   int errorCount = int(errors_.size());
+   Token skip;
+   while ( true )
+   {
+      if ( !readToken(skip) )
+         errors_.resize( errorCount ); // discard errors caused by recovery
+      if ( skip.type_ == skipUntilToken  ||  skip.type_ == tokenEndOfStream )
+         break;
+   }
+   errors_.resize( errorCount );
+   return false;
+}
+
+
+bool 
+Reader::addErrorAndRecover( const std::string &message, 
+                            Token &token,
+                            TokenType skipUntilToken )
+{
+   addError( message, token );
+   return recoverFromError( skipUntilToken );
+}
+
+
+Value &
+Reader::currentValue()
+{
+   return *(nodes_.top());
+}
+
+
+Reader::Char 
+Reader::getNextChar()
+{
+   if ( current_ == end_ )
+      return 0;
+   return *current_++;
+}
+
+
+void 
+Reader::getLocationLineAndColumn( Location location,
+                                  int &line,
+                                  int &column ) const
+{
+   Location current = begin_;
+   Location lastLineStart = current;
+   line = 0;
+   while ( current < location  &&  current != end_ )
+   {
+      Char c = *current++;
+      if ( c == '\r' )
+      {
+         if ( *current == '\n' )
+            ++current;
+         lastLineStart = current;
+         ++line;
+      }
+      else if ( c == '\n' )
+      {
+         lastLineStart = current;
+         ++line;
+      }
+   }
+   // column & line start at 1
+   column = int(location - lastLineStart) + 1;
+   ++line;
+}
+
+
+std::string
+Reader::getLocationLineAndColumn( Location location ) const
+{
+   int line, column;
+   getLocationLineAndColumn( location, line, column );
+   char buffer[18+16+16+1];
+   sprintf( buffer, "Line %d, Column %d", line, column );
+   return buffer;
+}
+
+
+std::string 
+Reader::getFormatedErrorMessages() const
+{
+   std::string formattedMessage;
+   for ( Errors::const_iterator itError = errors_.begin();
+         itError != errors_.end();
+         ++itError )
+   {
+      const ErrorInfo &error = *itError;
+      formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
+      formattedMessage += "  " + error.message_ + "\n";
+      if ( error.extra_ )
+         formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
+   }
+   return formattedMessage;
+}
+
+
+std::istream& operator>>( std::istream &sin, Value &root )
+{
+    Json::Reader reader;
+    bool ok = reader.parse(sin, root, true);
+    //JSON_ASSERT( ok );
+#if JSON_USE_EXCEPTION
+    if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
+#else
+    assert(ok && "Bad Format!");
+    (void) ok;
+#endif
+    return sin;
+}
+
+
+} // namespace Json
diff --git a/final/lib/JSON/json_value.cpp b/final/lib/JSON/json_value.cpp
new file mode 100644
index 0000000..691e418
--- /dev/null
+++ b/final/lib/JSON/json_value.cpp
@@ -0,0 +1,1732 @@
+#include <iostream>
+#include <json/value.h>
+#include <json/writer.h>
+#include <utility>
+#include <stdexcept>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+# include <cpptl/conststring.h>
+#endif
+#include <cstddef>    // size_t
+#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+# include "json_batchallocator.h"
+#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+// Disable warnings.  We do not fix these warnings, as this is a file imported
+// into Polly and we do not want to diverge from the original source.
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wcovered-switch-default"
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Woverflow"
+#endif
+
+#define JSON_ASSERT_UNREACHABLE assert( false )
+#define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
+// Do not use throw when exception is disable.
+#if JSON_USE_EXCEPTION
+#	define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
+#else
+#	define JSON_ASSERT_MESSAGE( condition, message ) JSON_ASSERT( condition ) // @todo <= provide the message
+#endif
+
+namespace Json {
+
+const Value Value::null;
+const Int Value::minInt = Int( ~(UInt(-1)/2) );
+const Int Value::maxInt = Int( UInt(-1)/2 );
+const UInt Value::maxUInt = UInt(-1);
+
+// A "safe" implementation of strdup. Allow null pointer to be passed.
+// Also avoid warning on msvc80.
+//
+//inline char *safeStringDup( const char *czstring )
+//{
+//   if ( czstring )
+//   {
+//      const size_t length = (unsigned int)( strlen(czstring) + 1 );
+//      char *newString = static_cast<char *>( malloc( length ) );
+//      memcpy( newString, czstring, length );
+//      return newString;
+//   }
+//   return 0;
+//}
+//
+//inline char *safeStringDup( const std::string &str )
+//{
+//   if ( !str.empty() )
+//   {
+//      const size_t length = str.length();
+//      char *newString = static_cast<char *>( malloc( length + 1 ) );
+//      memcpy( newString, str.c_str(), length );
+//      newString[length] = 0;
+//      return newString;
+//   }
+//   return 0;
+//}
+
+ValueAllocator::~ValueAllocator()
+{
+}
+
+class DefaultValueAllocator : public ValueAllocator
+{
+public:
+   virtual ~DefaultValueAllocator()
+   {
+   }
+
+   virtual char *makeMemberName( const char *memberName )
+   {
+      return duplicateStringValue( memberName );
+   }
+
+   virtual void releaseMemberName( char *memberName )
+   {
+      releaseStringValue( memberName );
+   }
+
+   virtual char *duplicateStringValue( const char *value,
+                                       unsigned int length = unknown )
+   {
+      //@todo invesgate this old optimization
+      //if ( !value  ||  value[0] == 0 )
+      //   return 0;
+
+      if ( length == unknown )
+         length = (unsigned int)strlen(value);
+      char *newString = static_cast<char *>( malloc( length + 1 ) );
+      memcpy( newString, value, length );
+      newString[length] = 0;
+      return newString;
+   }
+
+   virtual void releaseStringValue( char *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+
+static ValueAllocator *&valueAllocator()
+{
+   static DefaultValueAllocator defaultAllocator;
+   static ValueAllocator *valueAllocator = &defaultAllocator;
+   return valueAllocator;
+}
+
+static struct DummyValueAllocatorInitializer {
+   DummyValueAllocatorInitializer()
+   {
+      valueAllocator();      // ensure valueAllocator() statics are initialized before main().
+   }
+} dummyValueAllocatorInitializer;
+
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+# include "json_internalarray.inl"
+# include "json_internalmap.inl"
+#endif // JSON_VALUE_USE_INTERNAL_MAP
+
+# include "json_valueiterator.inl"
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+Value::CommentInfo::CommentInfo()
+   : comment_( 0 )
+{
+}
+
+Value::CommentInfo::~CommentInfo()
+{
+   if ( comment_ )
+      valueAllocator()->releaseStringValue( comment_ );
+}
+
+
+void
+Value::CommentInfo::setComment( const char *text )
+{
+   if ( comment_ )
+      valueAllocator()->releaseStringValue( comment_ );
+   JSON_ASSERT( text );
+   JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
+   // It seems that /**/ style comments are acceptable as well.
+   comment_ = valueAllocator()->duplicateStringValue( text );
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// Notes: index_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString( int index )
+   : cstr_( 0 )
+   , index_( index )
+{
+}
+
+Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
+   : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
+                                  : cstr )
+   , index_( allocate )
+{
+}
+
+Value::CZString::CZString( const CZString &other )
+: cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
+                ?  valueAllocator()->makeMemberName( other.cstr_ )
+                : other.cstr_ )
+   , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
+                         : other.index_ )
+{
+}
+
+Value::CZString::~CZString()
+{
+   if ( cstr_  &&  index_ == duplicate )
+      valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
+}
+
+void
+Value::CZString::swap( CZString &other )
+{
+   std::swap( cstr_, other.cstr_ );
+   std::swap( index_, other.index_ );
+}
+
+Value::CZString &
+Value::CZString::operator =( const CZString &other )
+{
+   CZString temp( other );
+   swap( temp );
+   return *this;
+}
+
+bool
+Value::CZString::operator<( const CZString &other ) const
+{
+   if ( cstr_ )
+      return strcmp( cstr_, other.cstr_ ) < 0;
+   return index_ < other.index_;
+}
+
+bool
+Value::CZString::operator==( const CZString &other ) const
+{
+   if ( cstr_ )
+      return strcmp( cstr_, other.cstr_ ) == 0;
+   return index_ == other.index_;
+}
+
+
+int
+Value::CZString::index() const
+{
+   return index_;
+}
+
+
+const char *
+Value::CZString::c_str() const
+{
+   return cstr_;
+}
+
+bool
+Value::CZString::isStaticString() const
+{
+   return index_ == noDuplication;
+}
+
+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value( ValueType type )
+   : type_( type )
+   , allocated_( 0 )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   switch ( type )
+   {
+   case nullValue:
+      break;
+   case intValue:
+   case uintValue:
+      value_.int_ = 0;
+      break;
+   case realValue:
+      value_.real_ = 0.0;
+      break;
+   case stringValue:
+      value_.string_ = 0;
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_ = new ObjectValues();
+      break;
+#else
+   case arrayValue:
+      value_.array_ = arrayAllocator()->newArray();
+      break;
+   case objectValue:
+      value_.map_ = mapAllocator()->newMap();
+      break;
+#endif
+   case booleanValue:
+      value_.bool_ = false;
+      break;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+}
+
+
+Value::Value( Int value )
+   : type_( intValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.int_ = value;
+}
+
+
+Value::Value( UInt value )
+   : type_( uintValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.uint_ = value;
+}
+
+Value::Value( double value )
+   : type_( realValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.real_ = value;
+}
+
+Value::Value( const char *value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( value );
+}
+
+
+Value::Value( const char *beginValue,
+              const char *endValue )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( beginValue,
+                                                            UInt(endValue - beginValue) );
+}
+
+
+Value::Value( const std::string &value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
+                                                            (unsigned int)value.length() );
+
+}
+
+Value::Value( const StaticString &value )
+   : type_( stringValue )
+   , allocated_( false )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = const_cast<char *>( value.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value::Value( const CppTL::ConstString &value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
+}
+# endif
+
+Value::Value( bool value )
+   : type_( booleanValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.bool_ = value;
+}
+
+
+Value::Value( const Value &other )
+   : type_( other.type_ )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      value_ = other.value_;
+      break;
+   case stringValue:
+      if ( other.value_.string_ )
+      {
+         value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
+         allocated_ = true;
+      }
+      else
+         value_.string_ = 0;
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_ = new ObjectValues( *other.value_.map_ );
+      break;
+#else
+   case arrayValue:
+      value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
+      break;
+   case objectValue:
+      value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
+      break;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   if ( other.comments_ )
+   {
+      comments_ = new CommentInfo[numberOfCommentPlacement];
+      for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
+      {
+         const CommentInfo &otherComment = other.comments_[comment];
+         if ( otherComment.comment_ )
+            comments_[comment].setComment( otherComment.comment_ );
+      }
+   }
+}
+
+
+Value::~Value()
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      break;
+   case stringValue:
+      if ( allocated_ )
+         valueAllocator()->releaseStringValue( value_.string_ );
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      delete value_.map_;
+      break;
+#else
+   case arrayValue:
+      arrayAllocator()->destructArray( value_.array_ );
+      break;
+   case objectValue:
+      mapAllocator()->destructMap( value_.map_ );
+      break;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+
+   if ( comments_ )
+      delete[] comments_;
+}
+
+Value &
+Value::operator=( const Value &other )
+{
+   Value temp( other );
+   swap( temp );
+   return *this;
+}
+
+void
+Value::swap( Value &other )
+{
+   ValueType temp = type_;
+   type_ = other.type_;
+   other.type_ = temp;
+   std::swap( value_, other.value_ );
+   int temp2 = allocated_;
+   allocated_ = other.allocated_;
+   other.allocated_ = temp2;
+}
+
+ValueType
+Value::type() const
+{
+   return type_;
+}
+
+
+int
+Value::compare( const Value &other )
+{
+   /*
+   int typeDelta = other.type_ - type_;
+   switch ( type_ )
+   {
+   case nullValue:
+
+      return other.type_ == type_;
+   case intValue:
+      if ( other.type_.isNumeric()
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      break;
+   case stringValue,
+      break;
+   case arrayValue:
+      delete value_.array_;
+      break;
+   case objectValue:
+      delete value_.map_;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   */
+   return 0;  // unreachable
+}
+
+bool
+Value::operator <( const Value &other ) const
+{
+   int typeDelta = type_ - other.type_;
+   if ( typeDelta )
+      return typeDelta < 0 ? true : false;
+   switch ( type_ )
+   {
+   case nullValue:
+      return false;
+   case intValue:
+      return value_.int_ < other.value_.int_;
+   case uintValue:
+      return value_.uint_ < other.value_.uint_;
+   case realValue:
+      return value_.real_ < other.value_.real_;
+   case booleanValue:
+      return value_.bool_ < other.value_.bool_;
+   case stringValue:
+      return ( value_.string_ == 0  &&  other.value_.string_ )
+             || ( other.value_.string_
+                  &&  value_.string_
+                  && strcmp( value_.string_, other.value_.string_ ) < 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      {
+         int delta = int( value_.map_->size() - other.value_.map_->size() );
+         if ( delta )
+            return delta < 0;
+         return (*value_.map_) < (*other.value_.map_);
+      }
+#else
+   case arrayValue:
+      return value_.array_->compare( *(other.value_.array_) ) < 0;
+   case objectValue:
+      return value_.map_->compare( *(other.value_.map_) ) < 0;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0;  // unreachable
+}
+
+bool
+Value::operator <=( const Value &other ) const
+{
+   return !(other > *this);
+}
+
+bool
+Value::operator >=( const Value &other ) const
+{
+   return !(*this < other);
+}
+
+bool
+Value::operator >( const Value &other ) const
+{
+   return other < *this;
+}
+
+bool
+Value::operator ==( const Value &other ) const
+{
+   //if ( type_ != other.type_ )
+   // GCC 2.95.3 says:
+   // attempt to take address of bit-field structure member `Json::Value::type_'
+   // Beats me, but a temp solves the problem.
+   int temp = other.type_;
+   if ( type_ != temp )
+      return false;
+   switch ( type_ )
+   {
+   case nullValue:
+      return true;
+   case intValue:
+      return value_.int_ == other.value_.int_;
+   case uintValue:
+      return value_.uint_ == other.value_.uint_;
+   case realValue:
+      return value_.real_ == other.value_.real_;
+   case booleanValue:
+      return value_.bool_ == other.value_.bool_;
+   case stringValue:
+      return ( value_.string_ == other.value_.string_ )
+             || ( other.value_.string_
+                  &&  value_.string_
+                  && strcmp( value_.string_, other.value_.string_ ) == 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      return value_.map_->size() == other.value_.map_->size()
+             && (*value_.map_) == (*other.value_.map_);
+#else
+   case arrayValue:
+      return value_.array_->compare( *(other.value_.array_) ) == 0;
+   case objectValue:
+      return value_.map_->compare( *(other.value_.map_) ) == 0;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0;  // unreachable
+}
+
+bool
+Value::operator !=( const Value &other ) const
+{
+   return !( *this == other );
+}
+
+const char *
+Value::asCString() const
+{
+   JSON_ASSERT( type_ == stringValue );
+   return value_.string_;
+}
+
+
+std::string
+Value::asString() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return "";
+   case stringValue:
+      return value_.string_ ? value_.string_ : "";
+   case booleanValue:
+      return value_.bool_ ? "true" : "false";
+   case intValue:
+   case uintValue:
+   case realValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return ""; // unreachable
+}
+
+# ifdef JSON_USE_CPPTL
+CppTL::ConstString
+Value::asConstString() const
+{
+   return CppTL::ConstString( asString().c_str() );
+}
+# endif
+
+Value::Int
+Value::asInt() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      return value_.int_;
+   case uintValue:
+      JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
+      return Int( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+Value::UInt
+Value::asUInt() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
+      return value_.int_;
+   case uintValue:
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
+      return UInt( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+double
+Value::asDouble() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0.0;
+   case intValue:
+      return value_.int_;
+   case uintValue:
+      return value_.uint_;
+   case realValue:
+      return value_.real_;
+   case booleanValue:
+      return value_.bool_ ? 1.0 : 0.0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+bool
+Value::asBool() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return false;
+   case intValue:
+   case uintValue:
+      return value_.int_ != 0;
+   case realValue:
+      return value_.real_ != 0.0;
+   case booleanValue:
+      return value_.bool_;
+   case stringValue:
+      return value_.string_  &&  value_.string_[0] != 0;
+   case arrayValue:
+   case objectValue:
+      return value_.map_->size() != 0;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false; // unreachable;
+}
+
+
+bool
+Value::isConvertibleTo( ValueType other ) const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return true;
+   case intValue:
+      return ( other == nullValue  &&  value_.int_ == 0 )
+             || other == intValue
+             || ( other == uintValue  && value_.int_ >= 0 )
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case uintValue:
+      return ( other == nullValue  &&  value_.uint_ == 0 )
+             || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
+             || other == uintValue
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case realValue:
+      return ( other == nullValue  &&  value_.real_ == 0.0 )
+             || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
+             || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case booleanValue:
+      return ( other == nullValue  &&  value_.bool_ == false )
+             || other == intValue
+             || other == uintValue
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case stringValue:
+      return other == stringValue
+             || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
+   case arrayValue:
+      return other == arrayValue
+             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
+   case objectValue:
+      return other == objectValue
+             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false; // unreachable;
+}
+
+
+/// Number of values in array or object
+Value::UInt
+Value::size() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+   case stringValue:
+      return 0;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:  // size of the array is highest index + 1
+      if ( !value_.map_->empty() )
+      {
+         ObjectValues::const_iterator itLast = value_.map_->end();
+         --itLast;
+         return (*itLast).first.index()+1;
+      }
+      return 0;
+   case objectValue:
+      return Int( value_.map_->size() );
+#else
+   case arrayValue:
+      return Int( value_.array_->size() );
+   case objectValue:
+      return Int( value_.map_->size() );
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+bool
+Value::empty() const
+{
+   if ( isNull() || isArray() || isObject() )
+      return size() == 0u;
+   else
+      return false;
+}
+
+
+bool
+Value::operator!() const
+{
+   return isNull();
+}
+
+
+void
+Value::clear()
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
+
+   switch ( type_ )
+   {
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_->clear();
+      break;
+#else
+   case arrayValue:
+      value_.array_->clear();
+      break;
+   case objectValue:
+      value_.map_->clear();
+      break;
+#endif
+   default:
+      break;
+   }
+}
+
+void
+Value::resize( UInt newSize )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   UInt oldSize = size();
+   if ( newSize == 0 )
+      clear();
+   else if ( newSize > oldSize )
+      (*this)[ newSize - 1 ];
+   else
+   {
+      for ( UInt index = newSize; index < oldSize; ++index )
+         value_.map_->erase( index );
+      assert( size() == newSize );
+   }
+#else
+   value_.array_->resize( newSize );
+#endif
+}
+
+
+Value &
+Value::operator[]( UInt index )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString key( index );
+   ObjectValues::iterator it = value_.map_->lower_bound( key );
+   if ( it != value_.map_->end()  &&  (*it).first == key )
+      return (*it).second;
+
+   ObjectValues::value_type defaultValue( key, null );
+   it = value_.map_->insert( it, defaultValue );
+   return (*it).second;
+#else
+   return value_.array_->resolveReference( index );
+#endif
+}
+
+
+const Value &
+Value::operator[]( UInt index ) const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString key( index );
+   ObjectValues::const_iterator it = value_.map_->find( key );
+   if ( it == value_.map_->end() )
+      return null;
+   return (*it).second;
+#else
+   Value *value = value_.array_->find( index );
+   return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const char *key )
+{
+   return resolveReference( key, false );
+}
+
+
+Value &
+Value::resolveReference( const char *key,
+                         bool isStatic )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      *this = Value( objectValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, isStatic ? CZString::noDuplication
+                                     : CZString::duplicateOnCopy );
+   ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
+   if ( it != value_.map_->end()  &&  (*it).first == actualKey )
+      return (*it).second;
+
+   ObjectValues::value_type defaultValue( actualKey, null );
+   it = value_.map_->insert( it, defaultValue );
+   Value &value = (*it).second;
+   return value;
+#else
+   return value_.map_->resolveReference( key, isStatic );
+#endif
+}
+
+
+Value
+Value::get( UInt index,
+            const Value &defaultValue ) const
+{
+   const Value *value = &((*this)[index]);
+   return value == &null ? defaultValue : *value;
+}
+
+
+bool
+Value::isValidIndex( UInt index ) const
+{
+   return index < size();
+}
+
+
+
+const Value &
+Value::operator[]( const char *key ) const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, CZString::noDuplication );
+   ObjectValues::const_iterator it = value_.map_->find( actualKey );
+   if ( it == value_.map_->end() )
+      return null;
+   return (*it).second;
+#else
+   const Value *value = value_.map_->find( key );
+   return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const std::string &key )
+{
+   return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const std::string &key ) const
+{
+   return (*this)[ key.c_str() ];
+}
+
+Value &
+Value::operator[]( const StaticString &key )
+{
+   return resolveReference( key, true );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value &
+Value::operator[]( const CppTL::ConstString &key )
+{
+   return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const CppTL::ConstString &key ) const
+{
+   return (*this)[ key.c_str() ];
+}
+# endif
+
+
+Value &
+Value::append( const Value &value )
+{
+   return (*this)[size()] = value;
+}
+
+
+Value
+Value::get( const char *key,
+            const Value &defaultValue ) const
+{
+   const Value *value = &((*this)[key]);
+   return value == &null ? defaultValue : *value;
+}
+
+
+Value
+Value::get( const std::string &key,
+            const Value &defaultValue ) const
+{
+   return get( key.c_str(), defaultValue );
+}
+
+Value
+Value::removeMember( const char* key )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, CZString::noDuplication );
+   ObjectValues::iterator it = value_.map_->find( actualKey );
+   if ( it == value_.map_->end() )
+      return null;
+   Value old(it->second);
+   value_.map_->erase(it);
+   return old;
+#else
+   Value *value = value_.map_->find( key );
+   if (value){
+      Value old(*value);
+      value_.map_.remove( key );
+      return old;
+   } else {
+      return null;
+   }
+#endif
+}
+
+Value
+Value::removeMember( const std::string &key )
+{
+   return removeMember( key.c_str() );
+}
+
+# ifdef JSON_USE_CPPTL
+Value
+Value::get( const CppTL::ConstString &key,
+            const Value &defaultValue ) const
+{
+   return get( key.c_str(), defaultValue );
+}
+# endif
+
+bool
+Value::isMember( const char *key ) const
+{
+   const Value *value = &((*this)[key]);
+   return value != &null;
+}
+
+
+bool
+Value::isMember( const std::string &key ) const
+{
+   return isMember( key.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+bool
+Value::isMember( const CppTL::ConstString &key ) const
+{
+   return isMember( key.c_str() );
+}
+#endif
+
+Value::Members
+Value::getMemberNames() const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+       return Value::Members();
+   Members members;
+   members.reserve( value_.map_->size() );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ObjectValues::const_iterator it = value_.map_->begin();
+   ObjectValues::const_iterator itEnd = value_.map_->end();
+   for ( ; it != itEnd; ++it )
+      members.push_back( std::string( (*it).first.c_str() ) );
+#else
+   ValueInternalMap::IteratorState it;
+   ValueInternalMap::IteratorState itEnd;
+   value_.map_->makeBeginIterator( it );
+   value_.map_->makeEndIterator( itEnd );
+   for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
+      members.push_back( std::string( ValueInternalMap::key( it ) ) );
+#endif
+   return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+//EnumMemberNames
+//Value::enumMemberNames() const
+//{
+//   if ( type_ == objectValue )
+//   {
+//      return CppTL::Enum::any(  CppTL::Enum::transform(
+//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+//         MemberNamesTransform() ) );
+//   }
+//   return EnumMemberNames();
+//}
+//
+//
+//EnumValues
+//Value::enumValues() const
+//{
+//   if ( type_ == objectValue  ||  type_ == arrayValue )
+//      return CppTL::Enum::anyValues( *(value_.map_),
+//                                     CppTL::Type<const Value &>() );
+//   return EnumValues();
+//}
+//
+//# endif
+
+
+bool
+Value::isNull() const
+{
+   return type_ == nullValue;
+}
+
+
+bool
+Value::isBool() const
+{
+   return type_ == booleanValue;
+}
+
+
+bool
+Value::isInt() const
+{
+   return type_ == intValue;
+}
+
+
+bool
+Value::isUInt() const
+{
+   return type_ == uintValue;
+}
+
+
+bool
+Value::isIntegral() const
+{
+   return type_ == intValue
+          ||  type_ == uintValue
+          ||  type_ == booleanValue;
+}
+
+
+bool
+Value::isDouble() const
+{
+   return type_ == realValue;
+}
+
+
+bool
+Value::isNumeric() const
+{
+   return isIntegral() || isDouble();
+}
+
+
+bool
+Value::isString() const
+{
+   return type_ == stringValue;
+}
+
+
+bool
+Value::isArray() const
+{
+   return type_ == nullValue  ||  type_ == arrayValue;
+}
+
+
+bool
+Value::isObject() const
+{
+   return type_ == nullValue  ||  type_ == objectValue;
+}
+
+
+void
+Value::setComment( const char *comment,
+                   CommentPlacement placement )
+{
+   if ( !comments_ )
+      comments_ = new CommentInfo[numberOfCommentPlacement];
+   comments_[placement].setComment( comment );
+}
+
+
+void
+Value::setComment( const std::string &comment,
+                   CommentPlacement placement )
+{
+   setComment( comment.c_str(), placement );
+}
+
+
+bool
+Value::hasComment( CommentPlacement placement ) const
+{
+   return comments_ != 0  &&  comments_[placement].comment_ != 0;
+}
+
+std::string
+Value::getComment( CommentPlacement placement ) const
+{
+   if ( hasComment(placement) )
+      return comments_[placement].comment_;
+   return "";
+}
+
+
+std::string
+Value::toStyledString() const
+{
+   StyledWriter writer;
+   return writer.write( *this );
+}
+
+
+Value::const_iterator
+Value::begin() const
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeBeginIterator( it );
+         return const_iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeBeginIterator( it );
+         return const_iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return const_iterator( value_.map_->begin() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return const_iterator();
+}
+
+Value::const_iterator
+Value::end() const
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeEndIterator( it );
+         return const_iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeEndIterator( it );
+         return const_iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return const_iterator( value_.map_->end() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return const_iterator();
+}
+
+
+Value::iterator
+Value::begin()
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeBeginIterator( it );
+         return iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeBeginIterator( it );
+         return iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return iterator( value_.map_->begin() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return iterator();
+}
+
+Value::iterator
+Value::end()
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeEndIterator( it );
+         return iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeEndIterator( it );
+         return iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return iterator( value_.map_->end() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return iterator();
+}
+
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument()
+   : kind_( kindNone )
+{
+}
+
+
+PathArgument::PathArgument( Value::UInt index )
+   : index_( index )
+   , kind_( kindIndex )
+{
+}
+
+
+PathArgument::PathArgument( const char *key )
+   : key_( key )
+   , kind_( kindKey )
+{
+}
+
+
+PathArgument::PathArgument( const std::string &key )
+   : key_( key.c_str() )
+   , kind_( kindKey )
+{
+}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path( const std::string &path,
+            const PathArgument &a1,
+            const PathArgument &a2,
+            const PathArgument &a3,
+            const PathArgument &a4,
+            const PathArgument &a5 )
+{
+   InArgs in;
+   in.push_back( &a1 );
+   in.push_back( &a2 );
+   in.push_back( &a3 );
+   in.push_back( &a4 );
+   in.push_back( &a5 );
+   makePath( path, in );
+}
+
+
+void
+Path::makePath( const std::string &path,
+                const InArgs &in )
+{
+   const char *current = path.c_str();
+   const char *end = current + path.length();
+   InArgs::const_iterator itInArg = in.begin();
+   while ( current != end )
+   {
+      if ( *current == '[' )
+      {
+         ++current;
+         if ( *current == '%' )
+            addPathInArg( path, in, itInArg, PathArgument::kindIndex );
+         else
+         {
+            Value::UInt index = 0;
+            for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
+               index = index * 10 + Value::UInt(*current - '0');
+            args_.push_back( index );
+         }
+         if ( current == end  ||  *current++ != ']' )
+            invalidPath( path, int(current - path.c_str()) );
+      }
+      else if ( *current == '%' )
+      {
+         addPathInArg( path, in, itInArg, PathArgument::kindKey );
+         ++current;
+      }
+      else if ( *current == '.' )
+      {
+         ++current;
+      }
+      else
+      {
+         const char *beginName = current;
+         while ( current != end  &&  !strchr( "[.", *current ) )
+            ++current;
+         args_.push_back( std::string( beginName, current ) );
+      }
+   }
+}
+
+
+void
+Path::addPathInArg( const std::string &path,
+                    const InArgs &in,
+                    InArgs::const_iterator &itInArg,
+                    PathArgument::Kind kind )
+{
+   if ( itInArg == in.end() )
+   {
+      // Error: missing argument %d
+   }
+   else if ( (*itInArg)->kind_ != kind )
+   {
+      // Error: bad argument type
+   }
+   else
+   {
+      args_.push_back( **itInArg );
+   }
+}
+
+
+void
+Path::invalidPath( const std::string &path,
+                   int location )
+{
+   // Error: invalid path.
+}
+
+
+const Value &
+Path::resolve( const Value &root ) const
+{
+   const Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
+         {
+            // Error: unable to resolve path (array value expected at position...
+         }
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+         {
+            // Error: unable to resolve path (object value expected at position...)
+         }
+         node = &((*node)[arg.key_]);
+         if ( node == &Value::null )
+         {
+            // Error: unable to resolve path (object has no member named '' at position...)
+         }
+      }
+   }
+   return *node;
+}
+
+
+Value
+Path::resolve( const Value &root,
+               const Value &defaultValue ) const
+{
+   const Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
+            return defaultValue;
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+            return defaultValue;
+         node = &((*node)[arg.key_]);
+         if ( node == &Value::null )
+            return defaultValue;
+      }
+   }
+   return *node;
+}
+
+
+Value &
+Path::make( Value &root ) const
+{
+   Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray() )
+         {
+            // Error: node is not an array at position ...
+         }
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+         {
+            // Error: node is not an object at position...
+         }
+         node = &((*node)[arg.key_]);
+      }
+   }
+   return *node;
+}
+
+
+} // namespace Json
diff --git a/final/lib/JSON/json_valueiterator.inl b/final/lib/JSON/json_valueiterator.inl
new file mode 100644
index 0000000..736e260
--- /dev/null
+++ b/final/lib/JSON/json_valueiterator.inl
@@ -0,0 +1,292 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   : current_()
+   , isNull_( true )
+{
+}
+#else
+   : isArray_( true )
+   , isNull_( true )
+{
+   iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
+   : current_( current )
+   , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+   : isArray_( true )
+{
+   iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+   : isArray_( false )
+{
+   iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   return current_->second;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::dereference( iterator_.array_ );
+   return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ++current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::increment( iterator_.array_ );
+   ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   --current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::decrement( iterator_.array_ );
+   ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type 
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+   return current_ - other.current_;
+# else
+   // Iterator for null value are initialized using the default
+   // constructor, which initialize current_ to the default
+   // std::map::iterator. As begin() and end() are two instance 
+   // of the default std::map::iterator, they can not be compared.
+   // To allow this, we handle this comparison specifically.
+   if ( isNull_  &&  other.isNull_ )
+   {
+      return 0;
+   }
+
+
+   // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+   // which is the one used by default).
+   // Using a portable hand-made version for non random iterator instead:
+   //   return difference_type( std::distance( current_, other.current_ ) );
+   difference_type myDistance = 0;
+   for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+   {
+      ++myDistance;
+   }
+   return myDistance;
+# endif
+#else
+   if ( isArray_ )
+      return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool 
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   if ( isNull_ )
+   {
+      return other.isNull_;
+   }
+   return current_ == other.current_;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   current_ = other.current_;
+#else
+   if ( isArray_ )
+      iterator_.array_ = other.iterator_.array_;
+   iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value 
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( czstring.c_str() )
+   {
+      if ( czstring.isStaticString() )
+         return Value( StaticString( czstring.c_str() ) );
+      return Value( czstring.c_str() );
+   }
+   return Value( czstring.index() );
+#else
+   if ( isArray_ )
+      return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+   bool isStatic;
+   const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+   if ( isStatic )
+      return Value( StaticString( memberName ) );
+   return Value( memberName );
+#endif
+}
+
+
+UInt 
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( !czstring.c_str() )
+      return czstring.index();
+   return Value::UInt( -1 );
+#else
+   if ( isArray_ )
+      return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+   return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const char *name = (*current_).first.c_str();
+   return name ? name : "";
+#else
+   if ( !isArray_ )
+      return ValueInternalMap::key( iterator_.map_ );
+   return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+   copy( other );
+   return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+   copy( other );
+   return *this;
+}
diff --git a/final/lib/JSON/json_writer.cpp b/final/lib/JSON/json_writer.cpp
new file mode 100644
index 0000000..bf475c3
--- /dev/null
+++ b/final/lib/JSON/json_writer.cpp
@@ -0,0 +1,829 @@
+#include <json/writer.h>
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool isControlCharacter(char ch)
+{
+   return ch > 0 && ch <= 0x1F;
+}
+
+static bool containsControlCharacter( const char* str )
+{
+   while ( *str ) 
+   {
+      if ( isControlCharacter( *(str++) ) )
+         return true;
+   }
+   return false;
+}
+static void uintToString( unsigned int value, 
+                          char *&current )
+{
+   *--current = 0;
+   do
+   {
+      *--current = (value % 10) + '0';
+      value /= 10;
+   }
+   while ( value != 0 );
+}
+
+std::string valueToString( Int value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   bool isNegative = value < 0;
+   if ( isNegative )
+      value = -value;
+   uintToString( UInt(value), current );
+   if ( isNegative )
+      *--current = '-';
+   assert( current >= buffer );
+   return current;
+}
+
+
+std::string valueToString( UInt value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   uintToString( value, current );
+   assert( current >= buffer );
+   return current;
+}
+
+std::string valueToString( double value )
+{
+   char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. 
+   sprintf_s(buffer, sizeof(buffer), "%#.16g", value); 
+#else	
+   sprintf(buffer, "%#.16g", value); 
+#endif
+   char* ch = buffer + strlen(buffer) - 1;
+   if (*ch != '0') return buffer; // nothing to truncate, so save time
+   while(ch > buffer && *ch == '0'){
+     --ch;
+   }
+   char* last_nonzero = ch;
+   while(ch >= buffer){
+     switch(*ch){
+     case '0':
+     case '1':
+     case '2':
+     case '3':
+     case '4':
+     case '5':
+     case '6':
+     case '7':
+     case '8':
+     case '9':
+       --ch;
+       continue;
+     case '.':
+       // Truncate zeroes to save bytes in output, but keep one.
+       *(last_nonzero+2) = '\0';
+       return buffer;
+     default:
+       return buffer;
+     }
+   }
+   return buffer;
+}
+
+
+std::string valueToString( bool value )
+{
+   return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+   // Not sure how to handle unicode...
+   if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && !containsControlCharacter( value ))
+      return std::string("\"") + value + "\"";
+   // We have to walk value and escape any special characters.
+   // Appending to std::string is not efficient, but this should be rare.
+   // (Note: forward slashes are *not* rare, but I am not escaping them.)
+   unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+nullptr
+   std::string result;
+   result.reserve(maxsize); // to avoid lots of mallocs
+   result += "\"";
+   for (const char* c=value; *c != 0; ++c)
+   {
+      switch(*c)
+      {
+         case '\"':
+            result += "\\\"";
+            break;
+         case '\\':
+            result += "\\\\";
+            break;
+         case '\b':
+            result += "\\b";
+            break;
+         case '\f':
+            result += "\\f";
+            break;
+         case '\n':
+            result += "\\n";
+            break;
+         case '\r':
+            result += "\\r";
+            break;
+         case '\t':
+            result += "\\t";
+            break;
+         //case '/':
+            // Even though \/ is considered a legal escape in JSON, a bare
+            // slash is also legal, so I see no reason to escape it.
+            // (I hope I am not misunderstanding something.
+            // blep notes: actually escaping \/ may be useful in javascript to avoid </ 
+            // sequence.
+            // Should add a flag to allow this compatibility mode and prevent this 
+            // sequence from occurring.
+         default:
+            if ( isControlCharacter( *c ) )
+            {
+               std::ostringstream oss;
+               oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+               result += oss.str();
+            }
+            else
+            {
+               result += *c;
+            }
+            break;
+      }
+   }
+   result += "\"";
+   return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+   : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void 
+FastWriter::enableYAMLCompatibility()
+{
+   yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string 
+FastWriter::write( const Value &root )
+{
+   document_ = "";
+   writeValue( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+FastWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      document_ += "null";
+      break;
+   case intValue:
+      document_ += valueToString( value.asInt() );
+      break;
+   case uintValue:
+      document_ += valueToString( value.asUInt() );
+      break;
+   case realValue:
+      document_ += valueToString( value.asDouble() );
+      break;
+   case stringValue:
+      document_ += valueToQuotedString( value.asCString() );
+      break;
+   case booleanValue:
+      document_ += valueToString( value.asBool() );
+      break;
+   case arrayValue:
+      {
+         document_ += "[";
+         int size = value.size();
+         for ( int index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ",";
+            writeValue( value[index] );
+         }
+         document_ += "]";
+      }
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         document_ += "{";
+         for ( Value::Members::iterator it = members.begin(); 
+               it != members.end(); 
+               ++it )
+         {
+            const std::string &name = *it;
+            if ( it != members.begin() )
+               document_ += ",";
+            document_ += valueToQuotedString( name.c_str() );
+            document_ += yamlCompatiblityEnabled_ ? ": " 
+                                                  : ":";
+            writeValue( value[name] );
+         }
+         document_ += "}";
+      }
+      break;
+   }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+   : rightMargin_( 74 )
+   , indentSize_( 3 )
+{
+}
+
+
+std::string 
+StyledWriter::write( const Value &root )
+{
+   document_ = "";
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+StyledWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               document_ += " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               document_ += ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+               writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            document_ += ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         document_ += "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ", ";
+            document_ += childValues_[index];
+         }
+         document_ += " ]";
+      }
+   }
+}
+
+
+bool 
+StyledWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      document_ += value;
+}
+
+
+void 
+StyledWriter::writeIndent()
+{
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         document_ += '\n';
+   }
+   document_ += indentString_;
+}
+
+
+void 
+StyledWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   document_ += value;
+}
+
+
+void 
+StyledWriter::indent()
+{
+   indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void 
+StyledWriter::unindent()
+{
+   assert( int(indentString_.size()) >= indentSize_ );
+   indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void 
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   document_ += normalizeEOL( root.getComment( commentBefore ) );
+   document_ += "\n";
+}
+
+
+void 
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      document_ += "\n";
+      document_ += normalizeEOL( root.getComment( commentAfter ) );
+      document_ += "\n";
+   }
+}
+
+
+bool 
+StyledWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+   : document_(nullptr)
+   , rightMargin_( 74 )
+   , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+   document_ = &out;
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   *document_ << "\n";
+   document_ = nullptr; // Forget the stream, for safety.
+}
+
+
+void 
+StyledStreamWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               *document_ << " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               *document_ << ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+	       writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            *document_ << ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         *document_ << "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               *document_ << ", ";
+            *document_ << childValues_[index];
+         }
+         *document_ << " ]";
+      }
+   }
+}
+
+
+bool 
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledStreamWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::writeIndent()
+{
+  /*
+    Some comments in this method would have been nice. ;-)
+
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         *document_ << '\n';
+   }
+  */
+   *document_ << '\n' << indentString_;
+}
+
+
+void 
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::indent()
+{
+   indentString_ += indentation_;
+}
+
+
+void 
+StyledStreamWriter::unindent()
+{
+   assert( indentString_.size() >= indentation_.size() );
+   indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void 
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   *document_ << normalizeEOL( root.getComment( commentBefore ) );
+   *document_ << "\n";
+}
+
+
+void 
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      *document_ << "\n";
+      *document_ << normalizeEOL( root.getComment( commentAfter ) );
+      *document_ << "\n";
+   }
+}
+
+
+bool 
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+   Json::StyledStreamWriter writer;
+   writer.write(sout, root);
+   return sout;
+}
+
+
+} // namespace Json
diff --git a/final/lib/JSON/sconscript b/final/lib/JSON/sconscript
new file mode 100644
index 0000000..6e7c6c8
--- /dev/null
+++ b/final/lib/JSON/sconscript
@@ -0,0 +1,8 @@
+Import( 'env buildLibrary' )
+
+buildLibrary( env, Split( """
+    json_reader.cpp 
+    json_value.cpp 
+    json_writer.cpp
+     """ ),
+    'json' )
diff --git a/final/lib/Makefile b/final/lib/Makefile
new file mode 100644
index 0000000..eb9ed85
--- /dev/null
+++ b/final/lib/Makefile
@@ -0,0 +1,68 @@
+##===- polly/lib/Makefile -----------------------*- Makefile -*-===##
+
+#
+# Indicate where we are relative to the top of the source tree.
+#
+LEVEL :=..
+
+LIBRARYNAME=LLVMPolly
+LOADABLE_MODULE = 1
+
+# TODO: Export symbols for RTTI or EH?
+
+CPP.Flags += $(POLLY_INC)
+LD.Flags += $(POLLY_LD) $(POLLY_LIB)
+
+include $(LEVEL)/Makefile.config
+
+# Enable optional source files
+ifeq ($(GPU_CODEGEN), yes)
+GPGPU_CODEGEN_FILES= CodeGen/PTXGenerator.cpp
+endif
+
+ifeq ($(PLUTO_FOUND), yes)
+POLLY_PLUTO_FILES= Transform/Pluto.cpp
+endif
+
+ISL_CODEGEN_FILES= CodeGen/IslAst.cpp \
+                   CodeGen/IslExprBuilder.cpp \
+                   CodeGen/IslCodeGeneration.cpp
+
+POLLY_JSON_FILES= JSON/json_reader.cpp \
+		  JSON/json_value.cpp \
+		  JSON/json_writer.cpp
+
+SOURCES= Polly.cpp \
+	 Support/GICHelper.cpp \
+	 Support/SCEVValidator.cpp \
+	 Support/RegisterPasses.cpp \
+	 Support/ScopHelper.cpp \
+	 Analysis/Dependences.cpp \
+	 Analysis/ScopDetection.cpp \
+	 Analysis/ScopDetectionDiagnostic.cpp \
+	 Analysis/ScopInfo.cpp \
+	 Analysis/ScopGraphPrinter.cpp \
+	 Analysis/ScopPass.cpp \
+	 Analysis/TempScopInfo.cpp \
+	 CodeGen/BlockGenerators.cpp \
+	 CodeGen/LoopGenerators.cpp \
+	 CodeGen/IRBuilder.cpp \
+	 CodeGen/Utils.cpp \
+	 CodeGen/RuntimeDebugBuilder.cpp \
+	 Exchange/JSONExporter.cpp \
+	 Transform/Canonicalization.cpp \
+	 Transform/CodePreparation.cpp \
+	 Transform/DeadCodeElimination.cpp \
+	 Transform/IndependentBlocks.cpp \
+	 Transform/ScheduleOptimizer.cpp \
+	 ${GPGPU_FILES} \
+	 ${ISL_CODEGEN_FILES} \
+	 ${POLLY_JSON_FILES} \
+	 ${POLLY_PLUTO_FILES}
+
+#
+# Include Makefile.common so we know what to do.
+#
+include $(LEVEL)/Makefile.common
+
+LIBS += $(POLLY_LD) $(POLLY_LIB)
diff --git a/final/lib/Polly.cpp b/final/lib/Polly.cpp
new file mode 100644
index 0000000..c879fd9
--- /dev/null
+++ b/final/lib/Polly.cpp
@@ -0,0 +1,30 @@
+//===---------- Polly.cpp - Initialize the Polly Module -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/RegisterPasses.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+
+namespace {
+
+/// @brief Initialize Polly passes when library is loaded.
+///
+/// We use the constructor of a statically declared object to initialize the
+/// different Polly passes right after the Polly library is loaded. This ensures
+/// that the Polly passes are available e.g. in the 'opt' tool.
+class StaticInitializer {
+public:
+  StaticInitializer() {
+    llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
+    polly::initializePollyPasses(Registry);
+  }
+};
+static StaticInitializer InitializeEverything;
+} // end of anonymous namespace.
diff --git a/final/lib/Support/GICHelper.cpp b/final/lib/Support/GICHelper.cpp
new file mode 100644
index 0000000..0b7abc2
--- /dev/null
+++ b/final/lib/Support/GICHelper.cpp
@@ -0,0 +1,150 @@
+//===- GmpConv.cpp - Recreate LLVM IR from the Scop.  ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Functions for converting between gmp objects and apint.
+//
+//===----------------------------------------------------------------------===//
+#include "polly/Support/GICHelper.h"
+#include "llvm/IR/Value.h"
+#include "isl/aff.h"
+#include "isl/map.h"
+#include "isl/schedule.h"
+#include "isl/set.h"
+#include "isl/union_map.h"
+#include "isl/union_set.h"
+#include "isl/val.h"
+
+using namespace llvm;
+
+__isl_give isl_val *polly::isl_valFromAPInt(isl_ctx *Ctx, const APInt Int,
+                                            bool IsSigned) {
+  APInt Abs;
+  isl_val *v;
+
+  if (IsSigned)
+    Abs = Int.abs();
+  else
+    Abs = Int;
+
+  const uint64_t *Data = Abs.getRawData();
+  unsigned Words = Abs.getNumWords();
+
+  v = isl_val_int_from_chunks(Ctx, Words, sizeof(uint64_t), Data);
+
+  if (IsSigned && Int.isNegative())
+    v = isl_val_neg(v);
+
+  return v;
+}
+
+APInt polly::APIntFromVal(__isl_take isl_val *Val) {
+  uint64_t *Data;
+  int NumChunks;
+
+  NumChunks = isl_val_n_abs_num_chunks(Val, sizeof(uint64_t));
+
+  Data = (uint64_t *)malloc(NumChunks * sizeof(uint64_t));
+  isl_val_get_abs_num_chunks(Val, sizeof(uint64_t), Data);
+  APInt A(8 * sizeof(uint64_t) * NumChunks, NumChunks, Data);
+
+  if (isl_val_is_neg(Val)) {
+    A = A.zext(A.getBitWidth() + 1);
+    A = -A;
+  }
+
+  if (A.getMinSignedBits() < A.getBitWidth())
+    A = A.trunc(A.getMinSignedBits());
+
+  free(Data);
+  isl_val_free(Val);
+  return A;
+}
+
+template <typename ISLTy, typename ISL_CTX_GETTER, typename ISL_PRINTER>
+static inline std::string stringFromIslObjInternal(__isl_keep ISLTy *isl_obj,
+                                                   ISL_CTX_GETTER ctx_getter_fn,
+                                                   ISL_PRINTER printer_fn) {
+  isl_ctx *ctx = ctx_getter_fn(isl_obj);
+  isl_printer *p = isl_printer_to_str(ctx);
+  printer_fn(p, isl_obj);
+  char *char_str = isl_printer_get_str(p);
+  std::string string(char_str);
+  free(char_str);
+  isl_printer_free(p);
+  return string;
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_map *map) {
+  return stringFromIslObjInternal(map, isl_map_get_ctx, isl_printer_print_map);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_set *set) {
+  return stringFromIslObjInternal(set, isl_set_get_ctx, isl_printer_print_set);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_union_map *umap) {
+  return stringFromIslObjInternal(umap, isl_union_map_get_ctx,
+                                  isl_printer_print_union_map);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_union_set *uset) {
+  return stringFromIslObjInternal(uset, isl_union_set_get_ctx,
+                                  isl_printer_print_union_set);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_schedule *schedule) {
+  return stringFromIslObjInternal(schedule, isl_schedule_get_ctx,
+                                  isl_printer_print_schedule);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_multi_aff *maff) {
+  return stringFromIslObjInternal(maff, isl_multi_aff_get_ctx,
+                                  isl_printer_print_multi_aff);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_pw_multi_aff *pma) {
+  return stringFromIslObjInternal(pma, isl_pw_multi_aff_get_ctx,
+                                  isl_printer_print_pw_multi_aff);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_aff *aff) {
+  return stringFromIslObjInternal(aff, isl_aff_get_ctx, isl_printer_print_aff);
+}
+
+std::string polly::stringFromIslObj(__isl_keep isl_pw_aff *pwaff) {
+  return stringFromIslObjInternal(pwaff, isl_pw_aff_get_ctx,
+                                  isl_printer_print_pw_aff);
+}
+
+static void replace(std::string &str, const std::string &find,
+                    const std::string &replace) {
+  size_t pos = 0;
+  while ((pos = str.find(find, pos)) != std::string::npos) {
+    str.replace(pos, find.length(), replace);
+    pos += replace.length();
+  }
+}
+
+static void makeIslCompatible(std::string &str) {
+  replace(str, ".", "_");
+  replace(str, "\"", "_");
+}
+
+std::string polly::getIslCompatibleName(std::string Prefix, const Value *Val,
+                                        std::string Suffix) {
+  std::string ValStr;
+  raw_string_ostream OS(ValStr);
+  Val->printAsOperand(OS, false);
+  ValStr = OS.str();
+  // Remove the leading %
+  ValStr.erase(0, 1);
+  ValStr = Prefix + ValStr + Suffix;
+  makeIslCompatible(ValStr);
+  return ValStr;
+}
diff --git a/final/lib/Support/RegisterPasses.cpp b/final/lib/Support/RegisterPasses.cpp
new file mode 100644
index 0000000..47b6b61
--- /dev/null
+++ b/final/lib/Support/RegisterPasses.cpp
@@ -0,0 +1,285 @@
+//===------ RegisterPasses.cpp - Add the Polly Passes to default passes  --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file composes the individual LLVM-IR passes provided by Polly to a
+// functional polyhedral optimizer. The polyhedral optimizer is automatically
+// made available to LLVM based compilers by loading the Polly shared library
+// into such a compiler.
+//
+// The Polly optimizer is made available by executing a static constructor that
+// registers the individual Polly passes in the LLVM pass manager builder. The
+// passes are registered such that the default behaviour of the compiler is not
+// changed, but that the flag '-polly' provided at optimization level '-O3'
+// enables additional polyhedral optimizations.
+//===----------------------------------------------------------------------===//
+
+#include "polly/RegisterPasses.h"
+#include "polly/Canonicalization.h"
+#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/ScopDetection.h"
+#include "polly/ScopInfo.h"
+#include "polly/TempScopInfo.h"
+#include "llvm/Analysis/CFGPrinter.h"
+#include "llvm/PassManager.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Vectorize.h"
+
+using namespace llvm;
+using namespace polly;
+
+cl::OptionCategory PollyCategory("Polly Options",
+                                 "Configure the polly loop optimizer");
+
+static cl::opt<bool>
+    PollyEnabled("polly", cl::desc("Enable the polly optimizer (only at -O3)"),
+                 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+enum OptimizerChoice {
+  OPTIMIZER_NONE,
+#ifdef PLUTO_FOUND
+  OPTIMIZER_PLUTO,
+#endif
+  OPTIMIZER_ISL
+};
+
+static cl::opt<OptimizerChoice> Optimizer(
+    "polly-optimizer", cl::desc("Select the scheduling optimizer"),
+    cl::values(clEnumValN(OPTIMIZER_NONE, "none", "No optimizer"),
+#ifdef PLUTO_FOUND
+               clEnumValN(OPTIMIZER_PLUTO, "pluto",
+                          "The Pluto scheduling optimizer"),
+#endif
+               clEnumValN(OPTIMIZER_ISL, "isl", "The isl scheduling optimizer"),
+               clEnumValEnd),
+    cl::Hidden, cl::init(OPTIMIZER_ISL), cl::ZeroOrMore,
+    cl::cat(PollyCategory));
+
+CodeGenChoice polly::PollyCodeGenChoice;
+static cl::opt<CodeGenChoice, true> XCodeGenerator(
+    "polly-code-generator", cl::desc("Select the code generator"),
+    cl::values(clEnumValN(CODEGEN_ISL, "isl", "isl code generator"),
+               clEnumValN(CODEGEN_NONE, "none", "no code generation"),
+               clEnumValEnd),
+    cl::Hidden, cl::location(PollyCodeGenChoice), cl::init(CODEGEN_ISL),
+    cl::ZeroOrMore, cl::cat(PollyCategory));
+
+VectorizerChoice polly::PollyVectorizerChoice;
+static cl::opt<polly::VectorizerChoice, true> Vectorizer(
+    "polly-vectorizer", cl::desc("Select the vectorization strategy"),
+    cl::values(clEnumValN(polly::VECTORIZER_NONE, "none", "No Vectorization"),
+               clEnumValN(polly::VECTORIZER_POLLY, "polly",
+                          "Polly internal vectorizer"),
+               clEnumValN(polly::VECTORIZER_UNROLL_ONLY, "unroll-only",
+                          "Only grouped unroll the vectorize candidate loops"),
+               clEnumValN(polly::VECTORIZER_BB, "bb",
+                          "The Basic Block vectorizer driven by Polly"),
+               clEnumValEnd),
+    cl::location(PollyVectorizerChoice), cl::init(polly::VECTORIZER_NONE),
+    cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> ImportJScop(
+    "polly-import",
+    cl::desc("Export the polyhedral description of the detected Scops"),
+    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> ExportJScop(
+    "polly-export",
+    cl::desc("Export the polyhedral description of the detected Scops"),
+    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> DeadCodeElim("polly-run-dce",
+                                  cl::desc("Run the dead code elimination"),
+                                  cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                  cl::cat(PollyCategory));
+
+static cl::opt<bool> PollyViewer(
+    "polly-show",
+    cl::desc("Highlight the code regions that will be optimized in a "
+             "(CFG BBs and LLVM-IR instructions)"),
+    cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> PollyOnlyViewer(
+    "polly-show-only",
+    cl::desc("Highlight the code regions that will be optimized in "
+             "a (CFG only BBs)"),
+    cl::init(false), cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"),
+                 cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"),
+                 cl::init(false), cl::cat(PollyCategory));
+
+static cl::opt<bool> PollyOnlyPrinter(
+    "polly-dot-only",
+    cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden,
+    cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"),
+    cl::init(false), cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    CFGPrinter("polly-view-cfg",
+               cl::desc("Show the Polly CFG right after code generation"),
+               cl::Hidden, cl::init(false), cl::cat(PollyCategory));
+
+bool polly::PollyAnnotateAliasScopes;
+static cl::opt<bool, true> XPollyAnnotateAliasScopes(
+    "polly-annotate-alias-scopes",
+    cl::desc("Annotate memory instructions with alias scopes"),
+    cl::location(PollyAnnotateAliasScopes), cl::init(true), cl::ZeroOrMore,
+    cl::cat(PollyCategory));
+
+namespace polly {
+void initializePollyPasses(PassRegistry &Registry) {
+  initializeIslCodeGenerationPass(Registry);
+  initializeCodePreparationPass(Registry);
+  initializeDeadCodeElimPass(Registry);
+  initializeDependencesPass(Registry);
+  initializeIndependentBlocksPass(Registry);
+  initializeJSONExporterPass(Registry);
+  initializeJSONImporterPass(Registry);
+  initializeIslAstInfoPass(Registry);
+  initializeIslScheduleOptimizerPass(Registry);
+  initializePollyCanonicalizePass(Registry);
+  initializeScopDetectionPass(Registry);
+  initializeScopInfoPass(Registry);
+  initializeTempScopInfoPass(Registry);
+}
+
+/// @brief Register Polly passes such that they form a polyhedral optimizer.
+///
+/// The individual Polly passes are registered in the pass manager such that
+/// they form a full polyhedral optimizer. The flow of the optimizer starts with
+/// a set of preparing transformations that canonicalize the LLVM-IR such that
+/// the LLVM-IR is easier for us to understand and to optimizes. On the
+/// canonicalized LLVM-IR we first run the ScopDetection pass, which detects
+/// static control flow regions. Those regions are then translated by the
+/// ScopInfo pass into a polyhedral representation. As a next step, a scheduling
+/// optimizer is run on the polyhedral representation and finally the optimized
+/// polyhedral representation is code generated back to LLVM-IR.
+///
+/// Besides this core functionality, we optionally schedule passes that provide
+/// a graphical view of the scops (Polly[Only]Viewer, Polly[Only]Printer), that
+/// allow the export/import of the polyhedral representation
+/// (JSCON[Exporter|Importer]) or that show the cfg after code generation.
+///
+/// For certain parts of the Polly optimizer, several alternatives are provided:
+///
+/// As scheduling optimizer we support PLUTO
+/// (http://pluto-compiler.sourceforge.net) as well as the isl scheduling
+/// optimizer (http://freecode.com/projects/isl). The isl optimizer is the
+/// default optimizer.
+/// It is also possible to run Polly with no optimizer. This mode is mainly
+/// provided to analyze the run and compile time changes caused by the
+/// scheduling optimizer.
+///
+/// Polly supports the isl internal code generator.
+void registerPollyPasses(llvm::PassManagerBase &PM) {
+  registerCanonicalicationPasses(PM);
+
+  PM.add(polly::createScopInfoPass());
+
+  if (PollyViewer)
+    PM.add(polly::createDOTViewerPass());
+  if (PollyOnlyViewer)
+    PM.add(polly::createDOTOnlyViewerPass());
+  if (PollyPrinter)
+    PM.add(polly::createDOTPrinterPass());
+  if (PollyOnlyPrinter)
+    PM.add(polly::createDOTOnlyPrinterPass());
+
+  if (ImportJScop)
+    PM.add(polly::createJSONImporterPass());
+
+  if (DeadCodeElim)
+    PM.add(polly::createDeadCodeElimPass());
+
+  switch (Optimizer) {
+  case OPTIMIZER_NONE:
+    break; /* Do nothing */
+
+#ifdef PLUTO_FOUND
+  case OPTIMIZER_PLUTO:
+    PM.add(polly::createPlutoOptimizerPass());
+    break;
+#endif
+
+  case OPTIMIZER_ISL:
+    PM.add(polly::createIslScheduleOptimizerPass());
+    break;
+  }
+
+  if (ExportJScop)
+    PM.add(polly::createJSONExporterPass());
+
+  switch (PollyCodeGenChoice) {
+  case CODEGEN_ISL:
+    PM.add(polly::createIslCodeGenerationPass());
+    break;
+  case CODEGEN_NONE:
+    break;
+  }
+
+  if (CFGPrinter)
+    PM.add(llvm::createCFGPrinterPass());
+}
+
+static bool shouldEnablePolly() {
+  if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)
+    PollyTrackFailures = true;
+
+  if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||
+      ExportJScop || ImportJScop)
+    PollyEnabled = true;
+
+  return PollyEnabled;
+}
+
+static void
+registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
+                                   llvm::PassManagerBase &PM) {
+  if (!polly::shouldEnablePolly())
+    return;
+
+  polly::registerPollyPasses(PM);
+}
+
+/// @brief Register Polly to be available as an optimizer
+///
+/// We currently register Polly such that it runs as early as possible. This has
+/// several implications:
+///
+///   1) We need to schedule more canonicalization passes
+///
+///   As nothing is run before Polly, it is necessary to run a set of preparing
+///   transformations before Polly to canonicalize the LLVM-IR and to allow
+///   Polly to detect and understand the code.
+///
+///   2) LICM and LoopIdiom pass have not yet been run
+///
+///   Loop invariant code motion as well as the loop idiom recognition pass make
+///   it more difficult for Polly to transform code. LICM may introduce
+///   additional data dependences that are hard to eliminate and the loop idiom
+///   recognition pass may introduce calls to memset that we currently do not
+///   understand. By running Polly early enough (meaning before these passes) we
+///   avoid difficulties that may be introduced by these passes.
+///
+///   3) We get the full -O3 optimization sequence after Polly
+///
+///   The LLVM-IR that is generated by Polly has been optimized on a high level,
+///   but it may be rather inefficient on the lower/scalar level. By scheduling
+///   Polly before all other passes, we have the full sequence of -O3
+///   optimizations behind us, such that inefficiencies on the low level can
+///   be optimized away.
+static llvm::RegisterStandardPasses
+    RegisterPollyOptimizer(llvm::PassManagerBuilder::EP_EarlyAsPossible,
+                           registerPollyEarlyAsPossiblePasses);
+}
diff --git a/final/lib/Support/SCEVValidator.cpp b/final/lib/Support/SCEVValidator.cpp
new file mode 100644
index 0000000..40f1d91
--- /dev/null
+++ b/final/lib/Support/SCEVValidator.cpp
@@ -0,0 +1,546 @@
+
+#include "polly/Support/SCEVValidator.h"
+#include "polly/ScopInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/Support/Debug.h"
+
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "polly-scev-validator"
+
+namespace SCEVType {
+/// @brief The type of a SCEV
+///
+/// To check for the validity of a SCEV we assign to each SCEV a type. The
+/// possible types are INT, PARAM, IV and INVALID. The order of the types is
+/// important. The subexpressions of SCEV with a type X can only have a type
+/// that is smaller or equal than X.
+enum TYPE {
+  // An integer value.
+  INT,
+
+  // An expression that is constant during the execution of the Scop,
+  // but that may depend on parameters unknown at compile time.
+  PARAM,
+
+  // An expression that may change during the execution of the SCoP.
+  IV,
+
+  // An invalid expression.
+  INVALID
+};
+}
+
+/// @brief The result the validator returns for a SCEV expression.
+class ValidatorResult {
+  /// @brief The type of the expression
+  SCEVType::TYPE Type;
+
+  /// @brief The set of Parameters in the expression.
+  std::vector<const SCEV *> Parameters;
+
+public:
+  /// @brief The copy constructor
+  ValidatorResult(const ValidatorResult &Source) {
+    Type = Source.Type;
+    Parameters = Source.Parameters;
+  }
+
+  /// @brief Construct a result with a certain type and no parameters.
+  ValidatorResult(SCEVType::TYPE Type) : Type(Type) {
+    assert(Type != SCEVType::PARAM && "Did you forget to pass the parameter");
+  }
+
+  /// @brief Construct a result with a certain type and a single parameter.
+  ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
+    Parameters.push_back(Expr);
+  }
+
+  /// @brief Get the type of the ValidatorResult.
+  SCEVType::TYPE getType() { return Type; }
+
+  /// @brief Is the analyzed SCEV constant during the execution of the SCoP.
+  bool isConstant() { return Type == SCEVType::INT || Type == SCEVType::PARAM; }
+
+  /// @brief Is the analyzed SCEV valid.
+  bool isValid() { return Type != SCEVType::INVALID; }
+
+  /// @brief Is the analyzed SCEV of Type IV.
+  bool isIV() { return Type == SCEVType::IV; }
+
+  /// @brief Is the analyzed SCEV of Type INT.
+  bool isINT() { return Type == SCEVType::INT; }
+
+  /// @brief Is the analyzed SCEV of Type PARAM.
+  bool isPARAM() { return Type == SCEVType::PARAM; }
+
+  /// @brief Get the parameters of this validator result.
+  std::vector<const SCEV *> getParameters() { return Parameters; }
+
+  /// @brief Add the parameters of Source to this result.
+  void addParamsFrom(class ValidatorResult &Source) {
+    Parameters.insert(Parameters.end(), Source.Parameters.begin(),
+                      Source.Parameters.end());
+  }
+
+  /// @brief Merge a result.
+  ///
+  /// This means to merge the parameters and to set the Type to the most
+  /// specific Type that matches both.
+  void merge(class ValidatorResult &ToMerge) {
+    Type = std::max(Type, ToMerge.Type);
+    addParamsFrom(ToMerge);
+  }
+
+  void print(raw_ostream &OS) {
+    switch (Type) {
+    case SCEVType::INT:
+      OS << "SCEVType::INT";
+      break;
+    case SCEVType::PARAM:
+      OS << "SCEVType::PARAM";
+      break;
+    case SCEVType::IV:
+      OS << "SCEVType::IV";
+      break;
+    case SCEVType::INVALID:
+      OS << "SCEVType::INVALID";
+      break;
+    }
+  }
+};
+
+raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
+  VR.print(OS);
+  return OS;
+}
+
+/// Check if a SCEV is valid in a SCoP.
+struct SCEVValidator
+    : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
+private:
+  const Region *R;
+  ScalarEvolution &SE;
+  const Value *BaseAddress;
+
+public:
+  SCEVValidator(const Region *R, ScalarEvolution &SE, const Value *BaseAddress)
+      : R(R), SE(SE), BaseAddress(BaseAddress) {}
+
+  class ValidatorResult visitConstant(const SCEVConstant *Constant) {
+    return ValidatorResult(SCEVType::INT);
+  }
+
+  class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
+    ValidatorResult Op = visit(Expr->getOperand());
+
+    switch (Op.getType()) {
+    case SCEVType::INT:
+    case SCEVType::PARAM:
+      // We currently do not represent a truncate expression as an affine
+      // expression. If it is constant during Scop execution, we treat it as a
+      // parameter.
+      return ValidatorResult(SCEVType::PARAM, Expr);
+    case SCEVType::IV:
+      DEBUG(dbgs() << "INVALID: Truncation of SCEVType::IV expression");
+      return ValidatorResult(SCEVType::INVALID);
+    case SCEVType::INVALID:
+      return Op;
+    }
+
+    llvm_unreachable("Unknown SCEVType");
+  }
+
+  class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+    ValidatorResult Op = visit(Expr->getOperand());
+
+    switch (Op.getType()) {
+    case SCEVType::INT:
+    case SCEVType::PARAM:
+      // We currently do not represent a truncate expression as an affine
+      // expression. If it is constant during Scop execution, we treat it as a
+      // parameter.
+      return ValidatorResult(SCEVType::PARAM, Expr);
+    case SCEVType::IV:
+      DEBUG(dbgs() << "INVALID: ZeroExtend of SCEVType::IV expression");
+      return ValidatorResult(SCEVType::INVALID);
+    case SCEVType::INVALID:
+      return Op;
+    }
+
+    llvm_unreachable("Unknown SCEVType");
+  }
+
+  class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
+    // We currently allow only signed SCEV expressions. In the case of a
+    // signed value, a sign extend is a noop.
+    //
+    // TODO: Reconsider this when we add support for unsigned values.
+    return visit(Expr->getOperand());
+  }
+
+  class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
+    ValidatorResult Return(SCEVType::INT);
+
+    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
+      ValidatorResult Op = visit(Expr->getOperand(i));
+      Return.merge(Op);
+
+      // Early exit.
+      if (!Return.isValid())
+        break;
+    }
+
+    // TODO: Check for NSW and NUW.
+    return Return;
+  }
+
+  class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
+    ValidatorResult Return(SCEVType::INT);
+
+    bool HasMultipleParams = false;
+
+    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
+      ValidatorResult Op = visit(Expr->getOperand(i));
+
+      if (Op.isINT())
+        continue;
+
+      if (Op.isPARAM() && Return.isPARAM()) {
+        HasMultipleParams = true;
+        continue;
+      }
+
+      if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) {
+        DEBUG(dbgs() << "INVALID: More than one non-int operand in MulExpr\n"
+                     << "\tExpr: " << *Expr << "\n"
+                     << "\tPrevious expression type: " << Return << "\n"
+                     << "\tNext operand (" << Op
+                     << "): " << *Expr->getOperand(i) << "\n");
+
+        return ValidatorResult(SCEVType::INVALID);
+      }
+
+      Return.merge(Op);
+    }
+
+    if (HasMultipleParams)
+      return ValidatorResult(SCEVType::PARAM, Expr);
+
+    // TODO: Check for NSW and NUW.
+    return Return;
+  }
+
+  class ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
+    ValidatorResult LHS = visit(Expr->getLHS());
+    ValidatorResult RHS = visit(Expr->getRHS());
+
+    // We currently do not represent an unsigned division as an affine
+    // expression. If the division is constant during Scop execution we treat it
+    // as a parameter, otherwise we bail out.
+    if (LHS.isConstant() && RHS.isConstant())
+      return ValidatorResult(SCEVType::PARAM, Expr);
+
+    DEBUG(dbgs() << "INVALID: unsigned division of non-constant expressions");
+    return ValidatorResult(SCEVType::INVALID);
+  }
+
+  class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+    if (!Expr->isAffine()) {
+      DEBUG(dbgs() << "INVALID: AddRec is not affine");
+      return ValidatorResult(SCEVType::INVALID);
+    }
+
+    ValidatorResult Start = visit(Expr->getStart());
+    ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
+
+    if (!Start.isValid())
+      return Start;
+
+    if (!Recurrence.isValid())
+      return Recurrence;
+
+    if (R->contains(Expr->getLoop())) {
+      if (Recurrence.isINT()) {
+        ValidatorResult Result(SCEVType::IV);
+        Result.addParamsFrom(Start);
+        return Result;
+      }
+
+      DEBUG(dbgs() << "INVALID: AddRec within scop has non-int"
+                      "recurrence part");
+      return ValidatorResult(SCEVType::INVALID);
+    }
+
+    assert(Start.isConstant() && Recurrence.isConstant() &&
+           "Expected 'Start' and 'Recurrence' to be constant");
+
+    // Directly generate ValidatorResult for Expr if 'start' is zero.
+    if (Expr->getStart()->isZero())
+      return ValidatorResult(SCEVType::PARAM, Expr);
+
+    // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
+    // if 'start' is not zero.
+    const SCEV *ZeroStartExpr = SE.getAddRecExpr(
+        SE.getConstant(Expr->getStart()->getType(), 0),
+        Expr->getStepRecurrence(SE), Expr->getLoop(), SCEV::FlagAnyWrap);
+
+    ValidatorResult ZeroStartResult =
+        ValidatorResult(SCEVType::PARAM, ZeroStartExpr);
+    ZeroStartResult.addParamsFrom(Start);
+
+    return ZeroStartResult;
+  }
+
+  class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
+    ValidatorResult Return(SCEVType::INT);
+
+    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
+      ValidatorResult Op = visit(Expr->getOperand(i));
+
+      if (!Op.isValid())
+        return Op;
+
+      Return.merge(Op);
+    }
+
+    return Return;
+  }
+
+  class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
+    // We do not support unsigned operations. If 'Expr' is constant during Scop
+    // execution we treat this as a parameter, otherwise we bail out.
+    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
+      ValidatorResult Op = visit(Expr->getOperand(i));
+
+      if (!Op.isConstant()) {
+        DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand");
+        return ValidatorResult(SCEVType::INVALID);
+      }
+    }
+
+    return ValidatorResult(SCEVType::PARAM, Expr);
+  }
+
+  ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
+    Value *V = Expr->getValue();
+
+    // We currently only support integer types. It may be useful to support
+    // pointer types, e.g. to support code like:
+    //
+    //   if (A)
+    //     A[i] = 1;
+    //
+    // See test/CodeGen/20120316-InvalidCast.ll
+    if (!Expr->getType()->isIntegerTy()) {
+      DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer type");
+      return ValidatorResult(SCEVType::INVALID);
+    }
+
+    if (isa<UndefValue>(V)) {
+      DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value");
+      return ValidatorResult(SCEVType::INVALID);
+    }
+
+    if (Instruction *I = dyn_cast<Instruction>(Expr->getValue()))
+      if (R->contains(I)) {
+        DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction "
+                        "within the region\n");
+        return ValidatorResult(SCEVType::INVALID);
+      }
+
+    if (BaseAddress == V) {
+      DEBUG(dbgs() << "INVALID: UnknownExpr references BaseAddress\n");
+      return ValidatorResult(SCEVType::INVALID);
+    }
+
+    return ValidatorResult(SCEVType::PARAM, Expr);
+  }
+};
+
+/// @brief Check whether a SCEV refers to an SSA name defined inside a region.
+///
+struct SCEVInRegionDependences
+    : public SCEVVisitor<SCEVInRegionDependences, bool> {
+public:
+  /// Returns true when the SCEV has SSA names defined in region R.
+  static bool hasDependences(const SCEV *S, const Region *R) {
+    SCEVInRegionDependences Ignore(R);
+    return Ignore.visit(S);
+  }
+
+  SCEVInRegionDependences(const Region *R) : R(R) {}
+
+  bool visit(const SCEV *Expr) {
+    return SCEVVisitor<SCEVInRegionDependences, bool>::visit(Expr);
+  }
+
+  bool visitConstant(const SCEVConstant *Constant) { return false; }
+
+  bool visitTruncateExpr(const SCEVTruncateExpr *Expr) {
+    return visit(Expr->getOperand());
+  }
+
+  bool visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+    return visit(Expr->getOperand());
+  }
+
+  bool visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
+    return visit(Expr->getOperand());
+  }
+
+  bool visitAddExpr(const SCEVAddExpr *Expr) {
+    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
+      if (visit(Expr->getOperand(i)))
+        return true;
+
+    return false;
+  }
+
+  bool visitMulExpr(const SCEVMulExpr *Expr) {
+    for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
+      if (visit(Expr->getOperand(i)))
+        return true;
+
+    return false;
+  }
+
+  bool visitUDivExpr(const SCEVUDivExpr *Expr) {
+    if (visit(Expr->getLHS()))
+      return true;
+
+    if (visit(Expr->getRHS()))
+      return true;
+
+    return false;
+  }
+
+  bool visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+    if (visit(Expr->getStart()))
+      return true;
+
+    for (size_t i = 0; i < Expr->getNumOperands(); ++i)
+      if (visit(Expr->getOperand(i)))
+        return true;
+
+    return false;
+  }
+
+  bool visitSMaxExpr(const SCEVSMaxExpr *Expr) {
+    for (size_t i = 0; i < Expr->getNumOperands(); ++i)
+      if (visit(Expr->getOperand(i)))
+        return true;
+
+    return false;
+  }
+
+  bool visitUMaxExpr(const SCEVUMaxExpr *Expr) {
+    for (size_t i = 0; i < Expr->getNumOperands(); ++i)
+      if (visit(Expr->getOperand(i)))
+        return true;
+
+    return false;
+  }
+
+  bool visitUnknown(const SCEVUnknown *Expr) {
+    Instruction *Inst = dyn_cast<Instruction>(Expr->getValue());
+
+    // Return true when Inst is defined inside the region R.
+    if (Inst && R->contains(Inst))
+      return true;
+
+    return false;
+  }
+
+private:
+  const Region *R;
+};
+
+namespace polly {
+/// Find all loops referenced in SCEVAddRecExprs.
+class SCEVFindLoops {
+  SetVector<const Loop *> &Loops;
+
+public:
+  SCEVFindLoops(SetVector<const Loop *> &Loops) : Loops(Loops) {}
+
+  bool follow(const SCEV *S) {
+    if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S))
+      Loops.insert(AddRec->getLoop());
+    return true;
+  }
+  bool isDone() { return false; }
+};
+
+void findLoops(const SCEV *Expr, SetVector<const Loop *> &Loops) {
+  SCEVFindLoops FindLoops(Loops);
+  SCEVTraversal<SCEVFindLoops> ST(FindLoops);
+  ST.visitAll(Expr);
+}
+
+/// Find all values referenced in SCEVUnknowns.
+class SCEVFindValues {
+  SetVector<Value *> &Values;
+
+public:
+  SCEVFindValues(SetVector<Value *> &Values) : Values(Values) {}
+
+  bool follow(const SCEV *S) {
+    if (const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(S))
+      Values.insert(Unknown->getValue());
+    return true;
+  }
+  bool isDone() { return false; }
+};
+
+void findValues(const SCEV *Expr, SetVector<Value *> &Values) {
+  SCEVFindValues FindValues(Values);
+  SCEVTraversal<SCEVFindValues> ST(FindValues);
+  ST.visitAll(Expr);
+}
+
+bool hasScalarDepsInsideRegion(const SCEV *Expr, const Region *R) {
+  return SCEVInRegionDependences::hasDependences(Expr, R);
+}
+
+bool isAffineExpr(const Region *R, const SCEV *Expr, ScalarEvolution &SE,
+                  const Value *BaseAddress) {
+  if (isa<SCEVCouldNotCompute>(Expr))
+    return false;
+
+  SCEVValidator Validator(R, SE, BaseAddress);
+  DEBUG({
+    dbgs() << "\n";
+    dbgs() << "Expr: " << *Expr << "\n";
+    dbgs() << "Region: " << R->getNameStr() << "\n";
+    dbgs() << " -> ";
+  });
+
+  ValidatorResult Result = Validator.visit(Expr);
+
+  DEBUG({
+    if (Result.isValid())
+      dbgs() << "VALID\n";
+    dbgs() << "\n";
+  });
+
+  return Result.isValid();
+}
+
+std::vector<const SCEV *> getParamsInAffineExpr(const Region *R,
+                                                const SCEV *Expr,
+                                                ScalarEvolution &SE,
+                                                const Value *BaseAddress) {
+  if (isa<SCEVCouldNotCompute>(Expr))
+    return std::vector<const SCEV *>();
+
+  SCEVValidator Validator(R, SE, BaseAddress);
+  ValidatorResult Result = Validator.visit(Expr);
+
+  return Result.getParameters();
+}
+}
diff --git a/final/lib/Support/ScopHelper.cpp b/final/lib/Support/ScopHelper.cpp
new file mode 100644
index 0000000..1b7b9a2
--- /dev/null
+++ b/final/lib/Support/ScopHelper.cpp
@@ -0,0 +1,178 @@
+//===- ScopHelper.cpp - Some Helper Functions for Scop.  ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Small functions that help with Scop and LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/Support/ScopHelper.h"
+#include "polly/ScopInfo.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "polly-scop-helper"
+
+// Helper function for Scop
+// TODO: Add assertion to not allow parameter to be null
+//===----------------------------------------------------------------------===//
+// Temporary Hack for extended region tree.
+// Cast the region to loop if there is a loop have the same header and exit.
+Loop *polly::castToLoop(const Region &R, LoopInfo &LI) {
+  BasicBlock *entry = R.getEntry();
+
+  if (!LI.isLoopHeader(entry))
+    return 0;
+
+  Loop *L = LI.getLoopFor(entry);
+
+  BasicBlock *exit = L->getExitBlock();
+
+  // Is the loop with multiple exits?
+  if (!exit)
+    return 0;
+
+  if (exit != R.getExit()) {
+    // SubRegion/ParentRegion with the same entry.
+    assert((R.getNode(R.getEntry())->isSubRegion() ||
+            R.getParent()->getEntry() == entry) &&
+           "Expect the loop is the smaller or bigger region");
+    return 0;
+  }
+
+  return L;
+}
+
+Value *polly::getPointerOperand(Instruction &Inst) {
+  if (LoadInst *load = dyn_cast<LoadInst>(&Inst))
+    return load->getPointerOperand();
+  else if (StoreInst *store = dyn_cast<StoreInst>(&Inst))
+    return store->getPointerOperand();
+  else if (GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(&Inst))
+    return gep->getPointerOperand();
+
+  return 0;
+}
+
+Type *polly::getAccessInstType(Instruction *AccInst) {
+  if (StoreInst *Store = dyn_cast<StoreInst>(AccInst))
+    return Store->getValueOperand()->getType();
+  return AccInst->getType();
+}
+
+bool polly::hasInvokeEdge(const PHINode *PN) {
+  for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i)
+    if (InvokeInst *II = dyn_cast<InvokeInst>(PN->getIncomingValue(i)))
+      if (II->getParent() == PN->getIncomingBlock(i))
+        return true;
+
+  return false;
+}
+
+BasicBlock *polly::createSingleExitEdge(Region *R, Pass *P) {
+  BasicBlock *BB = R->getExit();
+
+  SmallVector<BasicBlock *, 4> Preds;
+  for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI)
+    if (R->contains(*PI))
+      Preds.push_back(*PI);
+
+  return SplitBlockPredecessors(BB, Preds, ".region", P);
+}
+
+static void replaceScopAndRegionEntry(polly::Scop *S, BasicBlock *OldEntry,
+                                      BasicBlock *NewEntry) {
+  if (polly::ScopStmt *Stmt = S->getStmtForBasicBlock(OldEntry))
+    Stmt->setBasicBlock(NewEntry);
+
+  S->getRegion().replaceEntryRecursive(NewEntry);
+}
+
+BasicBlock *polly::simplifyRegion(Scop *S, Pass *P) {
+  Region *R = &S->getRegion();
+
+  // The entering block for the region.
+  BasicBlock *EnteringBB = R->getEnteringBlock();
+  BasicBlock *OldEntry = R->getEntry();
+  BasicBlock *NewEntry = nullptr;
+
+  // Create single entry edge if the region has multiple entry edges.
+  if (!EnteringBB) {
+    NewEntry = SplitBlock(OldEntry, OldEntry->begin(), P);
+    EnteringBB = OldEntry;
+  }
+
+  // Create an unconditional entry edge.
+  if (EnteringBB->getTerminator()->getNumSuccessors() != 1) {
+    BasicBlock *EntryBB = NewEntry ? NewEntry : OldEntry;
+    BasicBlock *SplitEdgeBB = SplitEdge(EnteringBB, EntryBB, P);
+
+    // Once the edge between EnteringBB and EntryBB is split, two cases arise.
+    // The first is simple. The new block is inserted between EnteringBB and
+    // EntryBB. In this case no further action is needed. However it might
+    // happen (if the splitted edge is not critical) that the new block is
+    // inserted __after__ EntryBB causing the following situation:
+    //
+    // EnteringBB
+    //    _|_
+    //    | |
+    //    |  \-> some_other_BB_not_in_R
+    //    V
+    // EntryBB
+    //    |
+    //    V
+    // SplitEdgeBB
+    //
+    // In this case we need to swap the role of EntryBB and SplitEdgeBB.
+
+    // Check which case SplitEdge produced:
+    if (SplitEdgeBB->getTerminator()->getSuccessor(0) == EntryBB) {
+      // First (simple) case.
+      EnteringBB = SplitEdgeBB;
+    } else {
+      // Second (complicated) case.
+      NewEntry = SplitEdgeBB;
+      EnteringBB = EntryBB;
+    }
+
+    EnteringBB->setName("polly.entering.block");
+  }
+
+  if (NewEntry)
+    replaceScopAndRegionEntry(S, OldEntry, NewEntry);
+
+  // Create single exit edge if the region has multiple exit edges.
+  if (!R->getExitingBlock()) {
+    BasicBlock *NewExit = createSingleExitEdge(R, P);
+
+    for (auto &&SubRegion : *R)
+      SubRegion->replaceExitRecursive(NewExit);
+  }
+
+  return EnteringBB;
+}
+
+void polly::splitEntryBlockForAlloca(BasicBlock *EntryBlock, Pass *P) {
+  // Find first non-alloca instruction. Every basic block has a non-alloc
+  // instruction, as every well formed basic block has a terminator.
+  BasicBlock::iterator I = EntryBlock->begin();
+  while (isa<AllocaInst>(I))
+    ++I;
+
+  // SplitBlock updates DT, DF and LI.
+  BasicBlock *NewEntry = SplitBlock(EntryBlock, I, P);
+  if (RegionInfoPass *RIP = P->getAnalysisIfAvailable<RegionInfoPass>())
+    RIP->getRegionInfo().splitBlock(NewEntry, EntryBlock);
+}
diff --git a/final/lib/Transform/Canonicalization.cpp b/final/lib/Transform/Canonicalization.cpp
new file mode 100644
index 0000000..40903c6
--- /dev/null
+++ b/final/lib/Transform/Canonicalization.cpp
@@ -0,0 +1,80 @@
+//===---- Canonicalization.cpp - Run canonicalization passes ======-------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Run the set of default canonicalization passes.
+//
+// This pass is mainly used for debugging.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/LinkAllPasses.h"
+#include "polly/Canonicalization.h"
+#include "llvm/Transforms/Scalar.h"
+
+using namespace llvm;
+using namespace polly;
+
+void polly::registerCanonicalicationPasses(llvm::PassManagerBase &PM) {
+  PM.add(llvm::createPromoteMemoryToRegisterPass());
+  PM.add(llvm::createInstructionCombiningPass());
+  PM.add(llvm::createCFGSimplificationPass());
+  PM.add(llvm::createTailCallEliminationPass());
+  PM.add(llvm::createCFGSimplificationPass());
+  PM.add(llvm::createReassociatePass());
+  PM.add(llvm::createLoopRotatePass());
+  PM.add(llvm::createInstructionCombiningPass());
+  PM.add(polly::createCodePreparationPass());
+}
+
+namespace {
+class PollyCanonicalize : public ModulePass {
+  PollyCanonicalize(const PollyCanonicalize &) LLVM_DELETED_FUNCTION;
+  const PollyCanonicalize &
+  operator=(const PollyCanonicalize &) LLVM_DELETED_FUNCTION;
+
+public:
+  static char ID;
+
+  explicit PollyCanonicalize() : ModulePass(ID) {}
+  ~PollyCanonicalize();
+
+  /// @name FunctionPass interface.
+  //@{
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual void releaseMemory();
+  virtual bool runOnModule(Module &M);
+  virtual void print(raw_ostream &OS, const Module *) const;
+  //@}
+};
+}
+
+PollyCanonicalize::~PollyCanonicalize() {}
+
+void PollyCanonicalize::getAnalysisUsage(AnalysisUsage &AU) const {}
+
+void PollyCanonicalize::releaseMemory() {}
+
+bool PollyCanonicalize::runOnModule(Module &M) {
+  PassManager PM;
+  registerCanonicalicationPasses(PM);
+  PM.run(M);
+
+  return true;
+}
+
+void PollyCanonicalize::print(raw_ostream &OS, const Module *) const {}
+
+char PollyCanonicalize::ID = 0;
+
+Pass *polly::createPollyCanonicalizePass() { return new PollyCanonicalize(); }
+
+INITIALIZE_PASS_BEGIN(PollyCanonicalize, "polly-canonicalize",
+                      "Polly - Run canonicalization passes", false, false)
+INITIALIZE_PASS_END(PollyCanonicalize, "polly-canonicalize",
+                    "Polly - Run canonicalization passes", false, false)
diff --git a/final/lib/Transform/CodePreparation.cpp b/final/lib/Transform/CodePreparation.cpp
new file mode 100644
index 0000000..67e111b
--- /dev/null
+++ b/final/lib/Transform/CodePreparation.cpp
@@ -0,0 +1,227 @@
+//===---- CodePreparation.cpp - Code preparation for Scop Detection -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The Polly code preparation pass is executed before SCoP detection. Its only
+// use is to translate all PHI nodes that can not be expressed by the code
+// generator into explicit memory dependences.
+//
+// Polly's code generation can code generate all PHI nodes that do not
+// reference parameters within the scop. As the code preparation pass is run
+// before scop detection, we can not check this condition, because without
+// a detected scop, we do not know SCEVUnknowns that appear in the SCEV of
+// a PHI node may later be within or outside of the SCoP. Hence, we follow a
+// heuristic and translate all PHI nodes that are either directly SCEVUnknown
+// or SCEVCouldNotCompute. This will hopefully get most of the PHI nodes that
+// are introduced due to conditional control flow, but not the ones that are
+// referencing loop counters.
+//
+// XXX: In the future, we should remove the need for this pass entirely and
+// instead add support for scalar dependences to ScopInfo and code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/LinkAllPasses.h"
+#include "polly/CodeGen/BlockGenerators.h"
+#include "polly/Support/ScopHelper.h"
+#include "llvm/Analysis/DominanceFrontier.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+using namespace llvm;
+using namespace polly;
+
+namespace {
+
+// Helper function which (for a given PHI node):
+//
+// 1) Remembers all incoming values and the associated basic blocks
+// 2) Demotes the phi node to the stack
+// 3) Remembers the correlation between the PHI node and the new alloca
+//
+// When we combine the information from 1) and 3) we know the values stored
+// in this alloca at the end of the predecessor basic blocks of the PHI.
+static void DemotePHI(
+    PHINode *PN, DenseMap<PHINode *, AllocaInst *> &PNallocMap,
+    DenseMap<std::pair<Value *, BasicBlock *>, PHINode *> &ValueLocToPhiMap) {
+
+  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+    auto *InVal = PN->getIncomingValue(i);
+    auto *InBB = PN->getIncomingBlock(i);
+    ValueLocToPhiMap[std::make_pair(InVal, InBB)] = PN;
+  }
+
+  PNallocMap[PN] = DemotePHIToStack(PN);
+}
+
+/// @brief Prepare the IR for the scop detection.
+///
+class CodePreparation : public FunctionPass {
+  CodePreparation(const CodePreparation &) LLVM_DELETED_FUNCTION;
+  const CodePreparation &
+  operator=(const CodePreparation &) LLVM_DELETED_FUNCTION;
+
+  LoopInfo *LI;
+  ScalarEvolution *SE;
+
+  void clear();
+
+  bool eliminatePHINodes(Function &F);
+
+public:
+  static char ID;
+
+  explicit CodePreparation() : FunctionPass(ID) {}
+  ~CodePreparation();
+
+  /// @name FunctionPass interface.
+  //@{
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual void releaseMemory();
+  virtual bool runOnFunction(Function &F);
+  virtual void print(raw_ostream &OS, const Module *) const;
+  //@}
+};
+}
+
+void CodePreparation::clear() {}
+
+CodePreparation::~CodePreparation() { clear(); }
+
+bool CodePreparation::eliminatePHINodes(Function &F) {
+  // The PHINodes that will be demoted.
+  std::vector<PHINode *> PNtoDemote;
+  // The PHINodes that will be deleted (stack slot sharing).
+  std::vector<PHINode *> PNtoDelete;
+  // The PHINodes that will be preserved.
+  std::vector<PHINode *> PNtoPreserve;
+  // Map to remember values stored in PHINodes at the end of basic blocks.
+  DenseMap<std::pair<Value *, BasicBlock *>, PHINode *> ValueLocToPhiMap;
+  // Map from PHINodes to their alloca (after demotion) counterpart.
+  DenseMap<PHINode *, AllocaInst *> PNallocMap;
+
+  // Scan the PHINodes in this function and categorize them to be either:
+  // o Preserved, if they are (canonical) induction variables or can be
+  //              synthesized during code generation ('SCEVable')
+  // o Deleted, if they are trivial PHI nodes (one incoming value) and the
+  //            incoming value is a PHI node we will demote
+  // o Demoted, if they do not fit any of the previous categories
+  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI)
+    for (BasicBlock::iterator II = BI->begin(), IE = BI->getFirstNonPHI();
+         II != IE; ++II) {
+      PHINode *PN = cast<PHINode>(II);
+      if (SE->isSCEVable(PN->getType())) {
+        const SCEV *S = SE->getSCEV(PN);
+        if (!isa<SCEVUnknown>(S) && !isa<SCEVCouldNotCompute>(S)) {
+          PNtoPreserve.push_back(PN);
+          continue;
+        }
+      }
+
+      // As DemotePHIToStack does not support invoke edges, we preserve
+      // PHINodes that have invoke edges.
+      if (hasInvokeEdge(PN)) {
+        PNtoPreserve.push_back(PN);
+      } else {
+        if (PN->getNumIncomingValues() == 1)
+          PNtoDelete.push_back(PN);
+        else
+          PNtoDemote.push_back(PN);
+      }
+    }
+
+  if (PNtoDemote.empty() && PNtoDelete.empty())
+    return false;
+
+  while (!PNtoDemote.empty()) {
+    PHINode *PN = PNtoDemote.back();
+    PNtoDemote.pop_back();
+    DemotePHI(PN, PNallocMap, ValueLocToPhiMap);
+  }
+
+  // For each trivial PHI we encountered (and we want to delete) we try to find
+  // the value it will hold in a alloca we already created by PHI demotion. If
+  // we succeed (the incoming value is stored in an alloca at the predecessor
+  // block), we can replace the trivial PHI by the value stored in the alloca.
+  // If not, we will demote this trivial PHI as any other one.
+  for (auto PNIt = PNtoDelete.rbegin(), PNEnd = PNtoDelete.rend();
+       PNIt != PNEnd; ++PNIt) {
+    PHINode *TrivPN = *PNIt;
+    assert(TrivPN->getNumIncomingValues() == 1 && "Assumed trivial PHI");
+
+    auto *InVal = TrivPN->getIncomingValue(0);
+    auto *InBB = TrivPN->getIncomingBlock(0);
+    const auto &ValLocIt = ValueLocToPhiMap.find(std::make_pair(InVal, InBB));
+    if (ValLocIt != ValueLocToPhiMap.end()) {
+      PHINode *InPHI = ValLocIt->second;
+      assert(PNallocMap.count(InPHI) &&
+             "Inconsitent state, PN was not demoted!");
+      auto *InPHIAlloca = PNallocMap[InPHI];
+      PNallocMap[TrivPN] = InPHIAlloca;
+      LoadInst *LI = new LoadInst(InPHIAlloca, "",
+                                  TrivPN->getParent()->getFirstInsertionPt());
+      TrivPN->replaceAllUsesWith(LI);
+      TrivPN->eraseFromParent();
+      continue;
+    }
+
+    DemotePHI(TrivPN, PNallocMap, ValueLocToPhiMap);
+  }
+
+  // Move preserved PHINodes to the beginning of the BasicBlock.
+  while (!PNtoPreserve.empty()) {
+    PHINode *PN = PNtoPreserve.back();
+    PNtoPreserve.pop_back();
+
+    BasicBlock *BB = PN->getParent();
+    if (PN == BB->begin())
+      continue;
+
+    PN->moveBefore(BB->begin());
+  }
+
+  return true;
+}
+
+void CodePreparation::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<LoopInfo>();
+  AU.addRequired<ScalarEvolution>();
+
+  AU.addPreserved<LoopInfo>();
+  AU.addPreserved<RegionInfoPass>();
+  AU.addPreserved<DominatorTreeWrapperPass>();
+  AU.addPreserved<DominanceFrontier>();
+}
+
+bool CodePreparation::runOnFunction(Function &F) {
+  LI = &getAnalysis<LoopInfo>();
+  SE = &getAnalysis<ScalarEvolution>();
+
+  splitEntryBlockForAlloca(&F.getEntryBlock(), this);
+
+  eliminatePHINodes(F);
+
+  return false;
+}
+
+void CodePreparation::releaseMemory() { clear(); }
+
+void CodePreparation::print(raw_ostream &OS, const Module *) const {}
+
+char CodePreparation::ID = 0;
+char &polly::CodePreparationID = CodePreparation::ID;
+
+Pass *polly::createCodePreparationPass() { return new CodePreparation(); }
+
+INITIALIZE_PASS_BEGIN(CodePreparation, "polly-prepare",
+                      "Polly - Prepare code for polly", false, false)
+INITIALIZE_PASS_DEPENDENCY(LoopInfo)
+INITIALIZE_PASS_END(CodePreparation, "polly-prepare",
+                    "Polly - Prepare code for polly", false, false)
diff --git a/final/lib/Transform/DeadCodeElimination.cpp b/final/lib/Transform/DeadCodeElimination.cpp
new file mode 100644
index 0000000..497999f
--- /dev/null
+++ b/final/lib/Transform/DeadCodeElimination.cpp
@@ -0,0 +1,181 @@
+//===- DeadCodeElimination.cpp - Eliminate dead iteration  ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The polyhedral dead code elimination pass analyses a SCoP to eliminate
+// statement instances that can be proven dead.
+// As a consequence, the code generated for this SCoP may execute a statement
+// less often. This means, a statement may be executed only in certain loop
+// iterations or it may not even be part of the generated code at all.
+//
+// This code:
+//
+//    for (i = 0; i < N; i++)
+//        arr[i] = 0;
+//    for (i = 0; i < N; i++)
+//        arr[i] = 10;
+//    for (i = 0; i < N; i++)
+//        arr[i] = i;
+//
+// is e.g. simplified to:
+//
+//    for (i = 0; i < N; i++)
+//        arr[i] = i;
+//
+// The idea and the algorithm used was first implemented by Sven Verdoolaege in
+// the 'ppcg' tool.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/ScopInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "isl/flow.h"
+#include "isl/set.h"
+#include "isl/map.h"
+#include "isl/union_map.h"
+
+using namespace llvm;
+using namespace polly;
+
+namespace {
+
+cl::opt<int> DCEPreciseSteps(
+    "polly-dce-precise-steps",
+    cl::desc("The number of precise steps between two approximating "
+             "iterations. (A value of -1 schedules another approximation stage "
+             "before the actual dead code elimination."),
+    cl::ZeroOrMore, cl::init(-1));
+
+class DeadCodeElim : public ScopPass {
+public:
+  static char ID;
+  explicit DeadCodeElim() : ScopPass(ID) {}
+
+  virtual bool runOnScop(Scop &S);
+
+  void printScop(llvm::raw_ostream &OS) const;
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+
+private:
+  /// @brief Return the set of live iterations.
+  ///
+  /// The set of live iterations are all iterations that write to memory and for
+  /// which we can not prove that there will be a later write that _must_
+  /// overwrite the same memory location and is consequently the only one that
+  /// is visible after the execution of the SCoP.
+  ///
+  isl_union_set *getLiveOut(Scop &S);
+  bool eliminateDeadCode(Scop &S, int PreciseSteps);
+};
+}
+
+char DeadCodeElim::ID = 0;
+
+// To compute the live outs, we compute for the data-locations that are
+// must-written to the last statement that touches these locations. On top of
+// this we add all statements that perform may-write accesses.
+//
+// We could be more precise by removing may-write accesses for which we know
+// that they are overwritten by a must-write after. However, at the moment the
+// only may-writes we introduce access the full (unbounded) array, such that
+// bounded write accesses can not overwrite all of the data-locations. As
+// this means may-writes are in the current situation always live, there is
+// no point in trying to remove them from the live-out set.
+isl_union_set *DeadCodeElim::getLiveOut(Scop &S) {
+  isl_union_map *Schedule = S.getSchedule();
+  isl_union_map *WriteIterations = isl_union_map_reverse(S.getMustWrites());
+  isl_union_map *WriteTimes =
+      isl_union_map_apply_range(WriteIterations, isl_union_map_copy(Schedule));
+
+  isl_union_map *LastWriteTimes = isl_union_map_lexmax(WriteTimes);
+  isl_union_map *LastWriteIterations = isl_union_map_apply_range(
+      LastWriteTimes, isl_union_map_reverse(Schedule));
+
+  isl_union_set *Live = isl_union_map_range(LastWriteIterations);
+  Live = isl_union_set_union(Live, isl_union_map_domain(S.getMayWrites()));
+  return isl_union_set_coalesce(Live);
+}
+
+/// Performs polyhedral dead iteration elimination by:
+/// o Assuming that the last write to each location is live.
+/// o Following each RAW dependency from a live iteration backwards and adding
+///   that iteration to the live set.
+///
+/// To ensure the set of live iterations does not get too complex we always
+/// combine a certain number of precise steps with one approximating step that
+/// simplifies the life set with an affine hull.
+bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) {
+  Dependences *D = &getAnalysis<Dependences>();
+
+  if (!D->hasValidDependences())
+    return false;
+
+  isl_union_set *Live = getLiveOut(S);
+  isl_union_map *Dep =
+      D->getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);
+  Dep = isl_union_map_reverse(Dep);
+
+  if (PreciseSteps == -1)
+    Live = isl_union_set_affine_hull(Live);
+
+  isl_union_set *OriginalDomain = S.getDomains();
+  int Steps = 0;
+  while (true) {
+    isl_union_set *Extra;
+    Steps++;
+
+    Extra =
+        isl_union_set_apply(isl_union_set_copy(Live), isl_union_map_copy(Dep));
+
+    if (isl_union_set_is_subset(Extra, Live)) {
+      isl_union_set_free(Extra);
+      break;
+    }
+
+    Live = isl_union_set_union(Live, Extra);
+
+    if (Steps > PreciseSteps) {
+      Steps = 0;
+      Live = isl_union_set_affine_hull(Live);
+    }
+
+    Live = isl_union_set_intersect(Live, isl_union_set_copy(OriginalDomain));
+  }
+  isl_union_map_free(Dep);
+  isl_union_set_free(OriginalDomain);
+
+  bool Changed = S.restrictDomains(isl_union_set_coalesce(Live));
+
+  // FIXME: We can probably avoid the recomputation of all dependences by
+  // updating them explicitly.
+  if (Changed)
+    D->recomputeDependences();
+  return Changed;
+}
+
+bool DeadCodeElim::runOnScop(Scop &S) {
+  return eliminateDeadCode(S, DCEPreciseSteps);
+}
+
+void DeadCodeElim::printScop(raw_ostream &OS) const {}
+
+void DeadCodeElim::getAnalysisUsage(AnalysisUsage &AU) const {
+  ScopPass::getAnalysisUsage(AU);
+  AU.addRequired<Dependences>();
+}
+
+Pass *polly::createDeadCodeElimPass() { return new DeadCodeElim(); }
+
+INITIALIZE_PASS_BEGIN(DeadCodeElim, "polly-dce",
+                      "Polly - Remove dead iterations", false, false)
+INITIALIZE_PASS_DEPENDENCY(Dependences)
+INITIALIZE_PASS_DEPENDENCY(ScopInfo)
+INITIALIZE_PASS_END(DeadCodeElim, "polly-dce", "Polly - Remove dead iterations",
+                    false, false)
diff --git a/final/lib/Transform/IndependentBlocks.cpp b/final/lib/Transform/IndependentBlocks.cpp
new file mode 100644
index 0000000..f74c4b8
--- /dev/null
+++ b/final/lib/Transform/IndependentBlocks.cpp
@@ -0,0 +1,563 @@
+//===------ IndependentBlocks.cpp - Create Independent Blocks in Regions --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Create independent blocks in the regions detected by ScopDetection.
+//
+//===----------------------------------------------------------------------===//
+//
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/CodeGen/BlockGenerators.h"
+#include "polly/ScopDetection.h"
+#include "polly/Support/ScopHelper.h"
+#include "llvm/Analysis/DominanceFrontier.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+
+#include <vector>
+
+using namespace polly;
+using namespace llvm;
+
+#define DEBUG_TYPE "polly-independent"
+
+static cl::opt<bool> DisableIntraScopScalarToArray(
+    "disable-polly-intra-scop-scalar-to-array",
+    cl::desc("Do not rewrite scalar to array to generate independent blocks"),
+    cl::Hidden, cl::init(false), cl::cat(PollyCategory));
+
+namespace {
+struct IndependentBlocks : public FunctionPass {
+  RegionInfo *RI;
+  ScalarEvolution *SE;
+  ScopDetection *SD;
+  LoopInfo *LI;
+
+  BasicBlock *AllocaBlock;
+
+  static char ID;
+
+  IndependentBlocks() : FunctionPass(ID) {}
+
+  // Create new code for every instruction operator that can be expressed by a
+  // SCEV.  Like this there are just two types of instructions left:
+  //
+  // 1. Instructions that only reference loop ivs or parameters outside the
+  // region.
+  //
+  // 2. Instructions that are not used for any memory modification. (These
+  //    will be ignored later on.)
+  //
+  // Blocks containing only these kind of instructions are called independent
+  // blocks as they can be scheduled arbitrarily.
+  bool createIndependentBlocks(BasicBlock *BB, const Region *R);
+  bool createIndependentBlocks(const Region *R);
+
+  // Elimination on the Scop to eliminate the scalar dependences come with
+  // trivially dead instructions.
+  bool eliminateDeadCode(const Region *R);
+
+  //===--------------------------------------------------------------------===//
+  /// Non trivial scalar dependences checking functions.
+  /// Non trivial scalar dependences occur when the def and use are located in
+  /// different BBs and we can not move them into the same one. This will
+  /// prevent use from schedule BBs arbitrarily.
+  ///
+  /// @brief This function checks if a scalar value that is part of the
+  ///        Scop is used outside of the Scop.
+  ///
+  /// @param Use  The use of the instruction.
+  /// @param R    The maximum region in the Scop.
+  ///
+  /// @return Return true if the Use of an instruction and the instruction
+  ///         itself form a non trivial scalar dependence.
+  static bool isEscapeUse(const Value *Use, const Region *R);
+
+  /// @brief This function just checks if a Value is either defined in the same
+  ///        basic block or outside the region, such that there are no scalar
+  ///        dependences between basic blocks that are both part of the same
+  ///        region.
+  ///
+  /// @param Operand  The operand of the instruction.
+  /// @param CurBB    The BasicBlock that contains the instruction.
+  /// @param R        The maximum region in the Scop.
+  ///
+  /// @return Return true if the Operand of an instruction and the instruction
+  ///         itself form a non trivial scalar (true) dependence.
+  bool isEscapeOperand(const Value *Operand, const BasicBlock *CurBB,
+                       const Region *R) const;
+
+  //===--------------------------------------------------------------------===//
+  /// Operand tree moving functions.
+  /// Trivial scalar dependences can eliminate by move the def to the same BB
+  /// that containing use.
+  ///
+  /// @brief Check if the instruction can be moved to another place safely.
+  ///
+  /// @param Inst The instruction.
+  ///
+  /// @return Return true if the instruction can be moved safely, false
+  ///         otherwise.
+  static bool isSafeToMove(Instruction *Inst);
+
+  typedef std::map<Instruction *, Instruction *> ReplacedMapType;
+
+  /// @brief Move all safe to move instructions in the Operand Tree (DAG) to
+  ///        eliminate trivial scalar dependences.
+  ///
+  /// @param Inst         The root of the operand Tree.
+  /// @param R            The maximum region in the Scop.
+  /// @param ReplacedMap  The map that mapping original instruction to the moved
+  ///                     instruction.
+  /// @param InsertPos    The insert position of the moved instructions.
+  void moveOperandTree(Instruction *Inst, const Region *R,
+                       ReplacedMapType &ReplacedMap, Instruction *InsertPos);
+
+  bool isIndependentBlock(const Region *R, BasicBlock *BB) const;
+  bool areAllBlocksIndependent(const Region *R) const;
+
+  // Split the exit block to hold load instructions.
+  bool splitExitBlock(Region *R);
+  bool onlyUsedInRegion(Instruction *Inst, const Region *R);
+  bool translateScalarToArray(BasicBlock *BB, const Region *R);
+  bool translateScalarToArray(Instruction *Inst, const Region *R);
+  bool translateScalarToArray(const Region *R);
+
+  bool runOnFunction(Function &F);
+  void verifyAnalysis() const;
+  void verifyScop(const Region *R) const;
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+};
+}
+
+bool IndependentBlocks::isSafeToMove(Instruction *Inst) {
+  if (Inst->mayReadFromMemory() || Inst->mayWriteToMemory())
+    return false;
+
+  return isSafeToSpeculativelyExecute(Inst);
+}
+
+void IndependentBlocks::moveOperandTree(Instruction *Inst, const Region *R,
+                                        ReplacedMapType &ReplacedMap,
+                                        Instruction *InsertPos) {
+  BasicBlock *CurBB = Inst->getParent();
+
+  // Depth first traverse the operand tree (or operand dag, because we will
+  // stop at PHINodes, so there are no cycle).
+  typedef Instruction::op_iterator ChildIt;
+  std::vector<std::pair<Instruction *, ChildIt>> WorkStack;
+
+  WorkStack.push_back(std::make_pair(Inst, Inst->op_begin()));
+  DenseSet<Instruction *> VisitedSet;
+
+  while (!WorkStack.empty()) {
+    Instruction *CurInst = WorkStack.back().first;
+    ChildIt It = WorkStack.back().second;
+    DEBUG(dbgs() << "Checking Operand of Node:\n" << *CurInst << "\n------>\n");
+    if (It == CurInst->op_end()) {
+      // Insert the new instructions in topological order.
+      if (!CurInst->getParent()) {
+        CurInst->insertBefore(InsertPos);
+        SE->forgetValue(CurInst);
+      }
+
+      WorkStack.pop_back();
+    } else {
+      // for each node N,
+      Instruction *Operand = dyn_cast<Instruction>(*It);
+      ++WorkStack.back().second;
+
+      // Can not move no instruction value.
+      if (Operand == 0)
+        continue;
+
+      DEBUG(dbgs() << "For Operand:\n" << *Operand << "\n--->");
+
+      // If the Scop Region does not contain N, skip it and all its operands and
+      // continue: because we reach a "parameter".
+      // FIXME: we must keep the predicate instruction inside the Scop,
+      // otherwise it will be translated to a load instruction, and we can not
+      // handle load as affine predicate at this moment.
+      if (!R->contains(Operand) && !isa<TerminatorInst>(CurInst)) {
+        DEBUG(dbgs() << "Out of region.\n");
+        continue;
+      }
+
+      if (canSynthesize(Operand, LI, SE, R)) {
+        DEBUG(dbgs() << "is IV.\n");
+        continue;
+      }
+
+      // We can not move the operand, a non trivial scalar dependence found!
+      if (!isSafeToMove(Operand)) {
+        DEBUG(dbgs() << "Can not move!\n");
+        continue;
+      }
+
+      // Do not need to move instruction if it is contained in the same BB with
+      // the root instruction.
+      if (Operand->getParent() == CurBB) {
+        DEBUG(dbgs() << "No need to move.\n");
+        // Try to move its operand, but do not visit an instuction twice.
+        if (VisitedSet.insert(Operand).second)
+          WorkStack.push_back(std::make_pair(Operand, Operand->op_begin()));
+        continue;
+      }
+
+      // Now we need to move Operand to CurBB.
+      // Check if we already moved it.
+      ReplacedMapType::iterator At = ReplacedMap.find(Operand);
+      if (At != ReplacedMap.end()) {
+        DEBUG(dbgs() << "Moved.\n");
+        Instruction *MovedOp = At->second;
+        It->set(MovedOp);
+        SE->forgetValue(MovedOp);
+      } else {
+        // Note that NewOp is not inserted in any BB now, we will insert it when
+        // it popped form the work stack, so it will be inserted in topological
+        // order.
+        Instruction *NewOp = Operand->clone();
+        NewOp->setName(Operand->getName() + ".moved.to." + CurBB->getName());
+        DEBUG(dbgs() << "Move to " << *NewOp << "\n");
+        It->set(NewOp);
+        ReplacedMap.insert(std::make_pair(Operand, NewOp));
+        SE->forgetValue(Operand);
+
+        // Process its operands, but do not visit an instuction twice.
+        if (VisitedSet.insert(NewOp).second)
+          WorkStack.push_back(std::make_pair(NewOp, NewOp->op_begin()));
+      }
+    }
+  }
+
+  SE->forgetValue(Inst);
+}
+
+bool IndependentBlocks::createIndependentBlocks(BasicBlock *BB,
+                                                const Region *R) {
+  std::vector<Instruction *> WorkList;
+  for (Instruction &Inst : *BB)
+    if (!isSafeToMove(&Inst) && !canSynthesize(&Inst, LI, SE, R))
+      WorkList.push_back(&Inst);
+
+  ReplacedMapType ReplacedMap;
+  Instruction *InsertPos = BB->getFirstNonPHIOrDbg();
+
+  for (Instruction *Inst : WorkList)
+    moveOperandTree(Inst, R, ReplacedMap, InsertPos);
+
+  // The BB was changed if we replaced any operand.
+  return !ReplacedMap.empty();
+}
+
+bool IndependentBlocks::createIndependentBlocks(const Region *R) {
+  bool Changed = false;
+
+  for (BasicBlock *BB : R->blocks())
+    Changed |= createIndependentBlocks(BB, R);
+
+  return Changed;
+}
+
+bool IndependentBlocks::eliminateDeadCode(const Region *R) {
+  std::vector<Instruction *> WorkList;
+
+  // Find all trivially dead instructions.
+  for (BasicBlock *BB : R->blocks())
+    for (Instruction &Inst : *BB)
+      if (isInstructionTriviallyDead(&Inst))
+        WorkList.push_back(&Inst);
+
+  if (WorkList.empty())
+    return false;
+
+  // Delete them so the cross BB scalar dependences come with them will
+  // also be eliminated.
+  while (!WorkList.empty()) {
+    RecursivelyDeleteTriviallyDeadInstructions(WorkList.back());
+    WorkList.pop_back();
+  }
+
+  return true;
+}
+
+bool IndependentBlocks::isEscapeUse(const Value *Use, const Region *R) {
+  // Non-instruction user will never escape.
+  if (!isa<Instruction>(Use))
+    return false;
+
+  return !R->contains(cast<Instruction>(Use));
+}
+
+bool IndependentBlocks::isEscapeOperand(const Value *Operand,
+                                        const BasicBlock *CurBB,
+                                        const Region *R) const {
+  const Instruction *OpInst = dyn_cast<Instruction>(Operand);
+
+  // Non-instruction operand will never escape.
+  if (OpInst == 0)
+    return false;
+
+  // Induction variables are valid operands.
+  if (canSynthesize(OpInst, LI, SE, R))
+    return false;
+
+  // A value from a different BB is used in the same region.
+  return R->contains(OpInst) && (OpInst->getParent() != CurBB);
+}
+
+bool IndependentBlocks::splitExitBlock(Region *R) {
+  // Split the exit BB to place the load instruction of escaped users.
+  BasicBlock *ExitBB = R->getExit();
+  Region *ExitRegion = RI->getRegionFor(ExitBB);
+
+  if (ExitBB != ExitRegion->getEntry())
+    return false;
+
+  BasicBlock *NewExit = createSingleExitEdge(R, this);
+
+  std::vector<Region *> toUpdate;
+  toUpdate.push_back(R);
+
+  while (!toUpdate.empty()) {
+    Region *R = toUpdate.back();
+    toUpdate.pop_back();
+
+    for (auto &&SubRegion : *R)
+      if (SubRegion->getExit() == ExitBB)
+        toUpdate.push_back(SubRegion.get());
+
+    R->replaceExit(NewExit);
+  }
+
+  RI->setRegionFor(NewExit, R->getParent());
+  return true;
+}
+
+bool IndependentBlocks::translateScalarToArray(const Region *R) {
+  bool Changed = false;
+
+  for (BasicBlock *BB : R->blocks())
+    Changed |= translateScalarToArray(BB, R);
+
+  return Changed;
+}
+
+// Returns true when Inst is only used inside region R.
+bool IndependentBlocks::onlyUsedInRegion(Instruction *Inst, const Region *R) {
+  for (User *U : Inst->users())
+    if (Instruction *UI = dyn_cast<Instruction>(U))
+      if (isEscapeUse(UI, R))
+        return false;
+
+  return true;
+}
+
+bool IndependentBlocks::translateScalarToArray(Instruction *Inst,
+                                               const Region *R) {
+  if (canSynthesize(Inst, LI, SE, R) && onlyUsedInRegion(Inst, R))
+    return false;
+
+  SmallVector<Instruction *, 4> LoadInside, LoadOutside;
+  for (User *U : Inst->users())
+    // Inst is referenced outside or referenced as an escaped operand.
+    if (Instruction *UI = dyn_cast<Instruction>(U)) {
+      if (isEscapeUse(UI, R))
+        LoadOutside.push_back(UI);
+
+      if (DisableIntraScopScalarToArray)
+        continue;
+
+      if (canSynthesize(UI, LI, SE, R))
+        continue;
+
+      BasicBlock *UParent = UI->getParent();
+      if (R->contains(UParent) && isEscapeOperand(Inst, UParent, R))
+        LoadInside.push_back(UI);
+    }
+
+  if (LoadOutside.empty() && LoadInside.empty())
+    return false;
+
+  // Create the alloca.
+  AllocaInst *Slot = new AllocaInst(
+      Inst->getType(), 0, Inst->getName() + ".s2a", AllocaBlock->begin());
+  assert(!isa<InvokeInst>(Inst) && "Unexpect Invoke in Scop!");
+
+  // Store right after Inst, and make sure the position is after all phi nodes.
+  BasicBlock::iterator StorePos;
+  if (isa<PHINode>(Inst)) {
+    StorePos = Inst->getParent()->getFirstNonPHI();
+  } else {
+    StorePos = Inst;
+    StorePos++;
+  }
+  (void)new StoreInst(Inst, Slot, StorePos);
+
+  if (!LoadOutside.empty()) {
+    LoadInst *ExitLoad = new LoadInst(Slot, Inst->getName() + ".loadoutside",
+                                      false, R->getExit()->getFirstNonPHI());
+
+    while (!LoadOutside.empty()) {
+      Instruction *U = LoadOutside.pop_back_val();
+      SE->forgetValue(U);
+      U->replaceUsesOfWith(Inst, ExitLoad);
+    }
+  }
+
+  while (!LoadInside.empty()) {
+    Instruction *U = LoadInside.pop_back_val();
+    assert(!isa<PHINode>(U) && "Can not handle PHI node inside!");
+    SE->forgetValue(U);
+    LoadInst *L = new LoadInst(Slot, Inst->getName() + ".loadarray", false, U);
+    U->replaceUsesOfWith(Inst, L);
+  }
+
+  SE->forgetValue(Inst);
+  return true;
+}
+
+bool IndependentBlocks::translateScalarToArray(BasicBlock *BB,
+                                               const Region *R) {
+  bool changed = false;
+
+  SmallVector<Instruction *, 32> Insts;
+  for (BasicBlock::iterator II = BB->begin(), IE = --BB->end(); II != IE; ++II)
+    Insts.push_back(II);
+
+  while (!Insts.empty()) {
+    Instruction *Inst = Insts.pop_back_val();
+    changed |= translateScalarToArray(Inst, R);
+  }
+
+  return changed;
+}
+
+bool IndependentBlocks::isIndependentBlock(const Region *R,
+                                           BasicBlock *BB) const {
+  for (Instruction &Inst : *BB) {
+    if (canSynthesize(&Inst, LI, SE, R))
+      continue;
+
+    // A value inside the Scop is referenced outside.
+    for (User *U : Inst.users()) {
+      if (isEscapeUse(U, R)) {
+        DEBUG(dbgs() << "Instruction not independent:\n");
+        DEBUG(dbgs() << "Instruction used outside the Scop!\n");
+        DEBUG(Inst.print(dbgs()));
+        DEBUG(dbgs() << "\n");
+        return false;
+      }
+    }
+
+    if (DisableIntraScopScalarToArray)
+      continue;
+
+    for (Value *Op : Inst.operands()) {
+      if (isEscapeOperand(Op, BB, R)) {
+        DEBUG(dbgs() << "Instruction in function '";
+              BB->getParent()->printAsOperand(dbgs(), false);
+              dbgs() << "' not independent:\n");
+        DEBUG(dbgs() << "Uses invalid operator\n");
+        DEBUG(Inst.print(dbgs()));
+        DEBUG(dbgs() << "\n");
+        DEBUG(dbgs() << "Invalid operator is: ";
+              Op->printAsOperand(dbgs(), false); dbgs() << "\n");
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool IndependentBlocks::areAllBlocksIndependent(const Region *R) const {
+  for (BasicBlock *BB : R->blocks())
+    if (!isIndependentBlock(R, BB))
+      return false;
+
+  return true;
+}
+
+void IndependentBlocks::getAnalysisUsage(AnalysisUsage &AU) const {
+  // FIXME: If we set preserves cfg, the cfg only passes do not need to
+  // be "addPreserved"?
+  AU.addPreserved<DominatorTreeWrapperPass>();
+  AU.addPreserved<DominanceFrontier>();
+  AU.addPreserved<PostDominatorTree>();
+  AU.addRequired<RegionInfoPass>();
+  AU.addPreserved<RegionInfoPass>();
+  AU.addRequired<LoopInfo>();
+  AU.addPreserved<LoopInfo>();
+  AU.addRequired<ScalarEvolution>();
+  AU.addPreserved<ScalarEvolution>();
+  AU.addRequired<ScopDetection>();
+  AU.addPreserved<ScopDetection>();
+}
+
+bool IndependentBlocks::runOnFunction(llvm::Function &F) {
+  bool Changed = false;
+
+  RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
+  LI = &getAnalysis<LoopInfo>();
+  SD = &getAnalysis<ScopDetection>();
+  SE = &getAnalysis<ScalarEvolution>();
+
+  AllocaBlock = &F.getEntryBlock();
+
+  DEBUG(dbgs() << "Run IndepBlock on " << F.getName() << '\n');
+
+  for (const Region *R : *SD) {
+    Changed |= createIndependentBlocks(R);
+    Changed |= eliminateDeadCode(R);
+    // This may change the RegionTree.
+    Changed |= splitExitBlock(const_cast<Region *>(R));
+  }
+
+  DEBUG(dbgs() << "Before Scalar to Array------->\n");
+  DEBUG(F.dump());
+
+  for (const Region *R : *SD)
+    Changed |= translateScalarToArray(R);
+
+  DEBUG(dbgs() << "After Independent Blocks------------->\n");
+  DEBUG(F.dump());
+
+  verifyAnalysis();
+
+  return Changed;
+}
+
+void IndependentBlocks::verifyAnalysis() const {
+  for (const Region *R : *SD)
+    verifyScop(R);
+}
+
+void IndependentBlocks::verifyScop(const Region *R) const {
+  assert(areAllBlocksIndependent(R) && "Cannot generate independent blocks");
+}
+
+char IndependentBlocks::ID = 0;
+char &polly::IndependentBlocksID = IndependentBlocks::ID;
+
+Pass *polly::createIndependentBlocksPass() { return new IndependentBlocks(); }
+
+INITIALIZE_PASS_BEGIN(IndependentBlocks, "polly-independent",
+                      "Polly - Create independent blocks", false, false);
+INITIALIZE_PASS_DEPENDENCY(LoopInfo);
+INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_DEPENDENCY(ScopDetection);
+INITIALIZE_PASS_END(IndependentBlocks, "polly-independent",
+                    "Polly - Create independent blocks", false, false)
diff --git a/final/lib/Transform/Pluto.cpp b/final/lib/Transform/Pluto.cpp
new file mode 100644
index 0000000..e0ab060
--- /dev/null
+++ b/final/lib/Transform/Pluto.cpp
@@ -0,0 +1,270 @@
+//===- Pluto.cpp - Calculate an optimized schedule ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Use libpluto to optimize the schedule.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/Config/config.h"
+
+#ifdef PLUTO_FOUND
+#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+#include "llvm/Support/Debug.h"
+
+#include "pluto/libpluto.h"
+#include "isl/map.h"
+
+using namespace llvm;
+using namespace polly;
+
+#define DEBUG_TYPE "polly-opt-pluto"
+
+static cl::opt<bool> EnableTiling("polly-pluto-tile", cl::desc("Enable tiling"),
+                                  cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                  cl::cat(PollyCategory));
+
+static cl::opt<bool> EnableIntraTiling("polly-pluto-intratileopt",
+                                       cl::desc("Enable intratiling"),
+                                       cl::Hidden, cl::init(true),
+                                       cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoDebug("polly-pluto-debug",
+                                cl::desc("Enable pluto debug"), cl::Hidden,
+                                cl::init(false), cl::ZeroOrMore,
+                                cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoMoreDebug("polly-pluto-moredebug",
+                                    cl::desc("Enable more pluto debugging"),
+                                    cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                    cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoParallel("polly-pluto-parallel",
+                                   cl::desc("Enable pluto parallel transforms"),
+                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                   cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    PlutoInnerParallel("polly-pluto-innerpara",
+                       cl::desc("Enable inner parallelism instead of piped."),
+                       cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                       cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    PlutoIdentity("polly-pluto-identity",
+                  cl::desc("Enable pluto identity transformation"), cl::Hidden,
+                  cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoUnroll("polly-pluto-unroll",
+                                 cl::desc("Enable pluto unrolling"), cl::Hidden,
+                                 cl::init(false), cl::ZeroOrMore,
+                                 cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoRar("polly-pluto-rar",
+                              cl::desc("Enable pluto rar deps"), cl::Hidden,
+                              cl::init(false), cl::ZeroOrMore,
+                              cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoParaPipe("polly-pluto-multipipe",
+                                   cl::desc("Enable multipipe parallelism"),
+                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                   cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoL2Tile("polly-pluto-l2tile",
+                                 cl::desc("Enable L2 tiling"), cl::Hidden,
+                                 cl::init(false), cl::ZeroOrMore,
+                                 cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoPollyUnroll("polly-pluto-pollyunroll",
+                                      cl::desc("Enable pluto polly unrolling"),
+                                      cl::Hidden, cl::init(false),
+                                      cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool>
+    PlutoIslDep("polly-pluto-isldep",
+                cl::desc("Enable pluto isl dependency scanning"), cl::Hidden,
+                cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoIslDepCompact(
+    "polly-pluto-isldepcom", cl::desc("Enable pluto isl dependency compaction"),
+    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoIslSolve("polly-pluto-islsolve",
+                                   cl::desc("Enable pluto isl solver"),
+                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
+                                   cl::cat(PollyCategory));
+
+static cl::opt<bool> PlutoLastWriter("polly-pluto-lastwriter",
+                                     cl::desc("Enable pluto lastwriter"),
+                                     cl::Hidden, cl::init(false),
+                                     cl::ZeroOrMore, cl::cat(PollyCategory));
+
+namespace {
+/// Convert an int into a string.
+static std::string convertInt(int number) {
+  if (number == 0)
+    return "0";
+  std::string temp = "";
+  std::string returnvalue = "";
+  while (number > 0) {
+    temp += number % 10 + 48;
+    number /= 10;
+  }
+  for (unsigned i = 0; i < temp.length(); i++)
+    returnvalue += temp[temp.length() - i - 1];
+  return returnvalue;
+}
+
+class PlutoOptimizer : public ScopPass {
+public:
+  static char ID;
+  explicit PlutoOptimizer() : ScopPass(ID) {}
+
+  virtual bool runOnScop(Scop &S);
+  void printScop(llvm::raw_ostream &OS) const;
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+  static void extendScattering(Scop &S, unsigned NewDimensions);
+};
+}
+
+char PlutoOptimizer::ID = 0;
+
+static int getSingleMap(__isl_take isl_map *map, void *user) {
+  isl_map **singleMap = (isl_map **)user;
+  *singleMap = map;
+
+  return 0;
+}
+
+void PlutoOptimizer::extendScattering(Scop &S, unsigned NewDimensions) {
+  for (ScopStmt *Stmt : S) {
+    unsigned OldDimensions = Stmt->getNumScattering();
+    isl_space *Space;
+    isl_map *Map, *New;
+
+    Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions);
+    Map = isl_map_universe(Space);
+
+    for (unsigned i = 0; i < OldDimensions; i++)
+      Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
+
+    for (unsigned i = OldDimensions; i < NewDimensions; i++)
+      Map = isl_map_fix_si(Map, isl_dim_out, i, 0);
+
+    Map = isl_map_align_params(Map, S.getParamSpace());
+    New = isl_map_apply_range(Stmt->getScattering(), Map);
+    Stmt->setScattering(New);
+  }
+}
+
+bool PlutoOptimizer::runOnScop(Scop &S) {
+  isl_union_set *Domain;
+  isl_union_map *Deps, *ToPlutoNames, *Schedule;
+  PlutoOptions *Options;
+
+  Dependences *D = &getAnalysis<Dependences>();
+
+  int DependencesKinds =
+      Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
+
+  Deps = D->getDependences(DependencesKinds);
+  Domain = S.getDomains();
+  ToPlutoNames = isl_union_map_empty(S.getParamSpace());
+
+  int counter = 0;
+  for (ScopStmt *Stmt : S) {
+    std::string Name = "S_" + convertInt(counter);
+    isl_map *Identity = isl_map_identity(isl_space_map_from_domain_and_range(
+        Stmt->getDomainSpace(), Stmt->getDomainSpace()));
+    Identity = isl_map_set_tuple_name(Identity, isl_dim_out, Name.c_str());
+    ToPlutoNames = isl_union_map_add_map(ToPlutoNames, Identity);
+    counter++;
+  }
+
+  Deps = isl_union_map_apply_domain(Deps, isl_union_map_copy(ToPlutoNames));
+  Deps = isl_union_map_apply_range(Deps, isl_union_map_copy(ToPlutoNames));
+  Domain = isl_union_set_apply(Domain, isl_union_map_copy(ToPlutoNames));
+
+  Options = pluto_options_alloc();
+  Options->debug = PlutoDebug;
+  Options->fuse = 2;
+  Options->identity = PlutoIdentity;
+  Options->innerpar = PlutoInnerParallel;
+  Options->intratileopt = EnableIntraTiling;
+  Options->isldep = PlutoIslDep;
+  Options->isldepcompact = PlutoIslDepCompact;
+  Options->islsolve = PlutoIslSolve;
+  Options->l2tile = PlutoL2Tile;
+  Options->lastwriter = PlutoLastWriter;
+  Options->moredebug = PlutoMoreDebug;
+  Options->multipipe = PlutoParaPipe;
+  Options->parallel = PlutoParallel;
+  Options->polyunroll = PlutoPollyUnroll;
+  Options->rar = PlutoRar;
+  Options->tile = EnableTiling;
+  Options->unroll = PlutoUnroll;
+
+  DEBUG(dbgs() << "Domain: " << stringFromIslObj(Domain) << "\n";
+        dbgs() << "Dependences: " << stringFromIslObj(Deps) << "\n";);
+  Schedule = pluto_schedule(Domain, Deps, Options);
+  pluto_options_free(Options);
+
+  isl_union_set_free(Domain);
+  isl_union_map_free(Deps);
+
+  if (!Schedule)
+    return false;
+
+  Schedule =
+      isl_union_map_apply_domain(Schedule, isl_union_map_reverse(ToPlutoNames));
+
+  for (ScopStmt *Stmt : S) {
+    isl_set *Domain = Stmt->getDomain();
+    isl_union_map *StmtBand;
+    StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(Schedule),
+                                              isl_union_set_from_set(Domain));
+    isl_map *StmtSchedule;
+    isl_union_map_foreach_map(StmtBand, getSingleMap, &StmtSchedule);
+    Stmt->setScattering(StmtSchedule);
+    isl_union_map_free(StmtBand);
+  }
+
+  isl_union_map_free(Schedule);
+
+  unsigned MaxScatDims = 0;
+
+  for (ScopStmt *Stmt : S)
+    MaxScatDims = std::max(Stmt->getNumScattering(), MaxScatDims);
+
+  extendScattering(S, MaxScatDims);
+  return false;
+}
+
+void PlutoOptimizer::printScop(raw_ostream &OS) const {}
+
+void PlutoOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
+  ScopPass::getAnalysisUsage(AU);
+  AU.addRequired<Dependences>();
+}
+
+Pass *polly::createPlutoOptimizerPass() { return new PlutoOptimizer(); }
+
+INITIALIZE_PASS_BEGIN(PlutoOptimizer, "polly-opt-pluto",
+                      "Polly - Optimize schedule of SCoP (Pluto)", false,
+                      false);
+INITIALIZE_PASS_DEPENDENCY(Dependences);
+INITIALIZE_PASS_DEPENDENCY(ScopInfo);
+INITIALIZE_PASS_END(PlutoOptimizer, "polly-opt-pluto",
+                    "Polly - Optimize schedule of SCoP (Pluto)", false, false)
+
+#endif // PLUTO_FOUND
diff --git a/final/lib/Transform/ScheduleOptimizer.cpp b/final/lib/Transform/ScheduleOptimizer.cpp
new file mode 100644
index 0000000..c8d9fe0
--- /dev/null
+++ b/final/lib/Transform/ScheduleOptimizer.cpp
@@ -0,0 +1,623 @@
+//===- Schedule.cpp - Calculate an optimized schedule ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass the isl to calculate a schedule that is optimized for parallelism
+// and tileablility. The algorithm used in isl is an optimized version of the
+// algorithm described in following paper:
+//
+// U. Bondhugula, A. Hartono, J. Ramanujam, and P. Sadayappan.
+// A Practical Automatic Polyhedral Parallelizer and Locality Optimizer.
+// In Proceedings of the 2008 ACM SIGPLAN Conference On Programming Language
+// Design and Implementation, PLDI ’08, pages 101–113. ACM, 2008.
+//===----------------------------------------------------------------------===//
+
+#include "polly/ScheduleOptimizer.h"
+#include "isl/aff.h"
+#include "isl/band.h"
+#include "isl/constraint.h"
+#include "isl/map.h"
+#include "isl/options.h"
+#include "isl/schedule.h"
+#include "isl/space.h"
+#include "polly/CodeGen/CodeGeneration.h"
+#include "polly/Dependences.h"
+#include "polly/LinkAllPasses.h"
+#include "polly/Options.h"
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+using namespace polly;
+
+#define DEBUG_TYPE "polly-opt-isl"
+
+namespace polly {
+bool DisablePollyTiling;
+}
+static cl::opt<bool, true>
+    DisableTiling("polly-no-tiling",
+                  cl::desc("Disable tiling in the scheduler"),
+                  cl::location(polly::DisablePollyTiling), cl::init(false),
+                  cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<std::string>
+    OptimizeDeps("polly-opt-optimize-only",
+                 cl::desc("Only a certain kind of dependences (all/raw)"),
+                 cl::Hidden, cl::init("all"), cl::ZeroOrMore,
+                 cl::cat(PollyCategory));
+
+static cl::opt<std::string>
+    SimplifyDeps("polly-opt-simplify-deps",
+                 cl::desc("Dependences should be simplified (yes/no)"),
+                 cl::Hidden, cl::init("yes"), cl::ZeroOrMore,
+                 cl::cat(PollyCategory));
+
+static cl::opt<int> MaxConstantTerm(
+    "polly-opt-max-constant-term",
+    cl::desc("The maximal constant term allowed (-1 is unlimited)"), cl::Hidden,
+    cl::init(20), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<int> MaxCoefficient(
+    "polly-opt-max-coefficient",
+    cl::desc("The maximal coefficient allowed (-1 is unlimited)"), cl::Hidden,
+    cl::init(20), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<std::string> FusionStrategy(
+    "polly-opt-fusion", cl::desc("The fusion strategy to choose (min/max)"),
+    cl::Hidden, cl::init("min"), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<std::string>
+    MaximizeBandDepth("polly-opt-maximize-bands",
+                      cl::desc("Maximize the band depth (yes/no)"), cl::Hidden,
+                      cl::init("yes"), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::opt<int> DefaultTileSize(
+    "polly-default-tile-size",
+    cl::desc("The default tile size (if not enough were provided by"
+             " --polly-tile-sizes)"),
+    cl::Hidden, cl::init(32), cl::ZeroOrMore, cl::cat(PollyCategory));
+
+static cl::list<int> TileSizes("polly-tile-sizes",
+                               cl::desc("A tile size"
+                                        " for each loop dimension, filled with"
+                                        " --polly-default-tile-size"),
+                               cl::Hidden, cl::ZeroOrMore, cl::CommaSeparated,
+                               cl::cat(PollyCategory));
+namespace {
+
+class IslScheduleOptimizer : public ScopPass {
+public:
+  static char ID;
+  explicit IslScheduleOptimizer() : ScopPass(ID) { LastSchedule = nullptr; }
+
+  ~IslScheduleOptimizer() { isl_schedule_free(LastSchedule); }
+
+  virtual bool runOnScop(Scop &S);
+  void printScop(llvm::raw_ostream &OS) const;
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+
+private:
+  isl_schedule *LastSchedule;
+
+  static void extendScattering(Scop &S, unsigned NewDimensions);
+
+  /// @brief Create a map that describes a n-dimensonal tiling.
+  ///
+  /// getTileMap creates a map from a n-dimensional scattering space into an
+  /// 2*n-dimensional scattering space. The map describes a rectangular
+  /// tiling.
+  ///
+  /// Example:
+  ///   scheduleDimensions = 2, parameterDimensions = 1, TileSizes = <32, 64>
+  ///
+  ///   tileMap := [p0] -> {[s0, s1] -> [t0, t1, s0, s1]:
+  ///                        t0 % 32 = 0 and t0 <= s0 < t0 + 32 and
+  ///                        t1 % 64 = 0 and t1 <= s1 < t1 + 64}
+  ///
+  ///  Before tiling:
+  ///
+  ///  for (i = 0; i < N; i++)
+  ///    for (j = 0; j < M; j++)
+  ///	S(i,j)
+  ///
+  ///  After tiling:
+  ///
+  ///  for (t_i = 0; t_i < N; i+=32)
+  ///    for (t_j = 0; t_j < M; j+=64)
+  ///	for (i = t_i; i < min(t_i + 32, N); i++)  | Unknown that N % 32 = 0
+  ///	  for (j = t_j; j < t_j + 64; j++)        |   Known that M % 64 = 0
+  ///	    S(i,j)
+  ///
+  static isl_basic_map *getTileMap(isl_ctx *ctx, int scheduleDimensions,
+                                   isl_space *SpaceModel);
+
+  /// @brief Get the schedule for this band.
+  ///
+  /// Polly applies transformations like tiling on top of the isl calculated
+  /// value.  This can influence the number of scheduling dimension. The
+  /// number of schedule dimensions is returned in the parameter 'Dimension'.
+  static isl_union_map *getScheduleForBand(isl_band *Band, int *Dimensions);
+
+  /// @brief Create a map that pre-vectorizes one scheduling dimension.
+  ///
+  /// getPrevectorMap creates a map that maps each input dimension to the same
+  /// output dimension, except for the dimension DimToVectorize.
+  /// DimToVectorize is strip mined by 'VectorWidth' and the newly created
+  /// point loop of DimToVectorize is moved to the innermost level.
+  ///
+  /// Example (DimToVectorize=0, ScheduleDimensions=2, VectorWidth=4):
+  ///
+  /// | Before transformation
+  /// |
+  /// | A[i,j] -> [i,j]
+  /// |
+  /// | for (i = 0; i < 128; i++)
+  /// |    for (j = 0; j < 128; j++)
+  /// |      A(i,j);
+  ///
+  ///   Prevector map:
+  ///   [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
+  ///
+  /// | After transformation:
+  /// |
+  /// | A[i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
+  /// |
+  /// | for (it = 0; it < 128; it+=4)
+  /// |    for (j = 0; j < 128; j++)
+  /// |      for (ip = max(0,it); ip < min(128, it + 3); ip++)
+  /// |        A(ip,j);
+  ///
+  /// The goal of this transformation is to create a trivially vectorizable
+  /// loop.  This means a parallel loop at the innermost level that has a
+  /// constant number of iterations corresponding to the target vector width.
+  ///
+  /// This transformation creates a loop at the innermost level. The loop has
+  /// a constant number of iterations, if the number of loop iterations at
+  /// DimToVectorize can be divided by VectorWidth. The default VectorWidth is
+  /// currently constant and not yet target specific. This function does not
+  /// reason about parallelism.
+  static isl_map *getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
+                                  int ScheduleDimensions, int VectorWidth = 4);
+
+  /// @brief Get the scheduling map for a list of bands.
+  ///
+  /// Walk recursively the forest of bands to combine the schedules of the
+  /// individual bands to the overall schedule. In case tiling is requested,
+  /// the individual bands are tiled.
+  static isl_union_map *getScheduleForBandList(isl_band_list *BandList);
+
+  static isl_union_map *getScheduleMap(isl_schedule *Schedule);
+
+  using llvm::Pass::doFinalization;
+
+  virtual bool doFinalization() {
+    isl_schedule_free(LastSchedule);
+    LastSchedule = nullptr;
+    return true;
+  }
+};
+}
+
+char IslScheduleOptimizer::ID = 0;
+
+void IslScheduleOptimizer::extendScattering(Scop &S, unsigned NewDimensions) {
+  for (ScopStmt *Stmt : S) {
+    unsigned OldDimensions = Stmt->getNumScattering();
+    isl_space *Space;
+    isl_map *Map, *New;
+
+    Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions);
+    Map = isl_map_universe(Space);
+
+    for (unsigned i = 0; i < OldDimensions; i++)
+      Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
+
+    for (unsigned i = OldDimensions; i < NewDimensions; i++)
+      Map = isl_map_fix_si(Map, isl_dim_out, i, 0);
+
+    Map = isl_map_align_params(Map, S.getParamSpace());
+    New = isl_map_apply_range(Stmt->getScattering(), Map);
+    Stmt->setScattering(New);
+  }
+}
+
+isl_basic_map *IslScheduleOptimizer::getTileMap(isl_ctx *ctx,
+                                                int scheduleDimensions,
+                                                isl_space *SpaceModel) {
+  // We construct
+  //
+  // tileMap := [p0] -> {[s0, s1] -> [t0, t1, p0, p1, a0, a1]:
+  //	                  s0 = a0 * 32 and s0 = p0 and t0 <= p0 < t0 + 64 and
+  //	                  s1 = a1 * 64 and s1 = p1 and t1 <= p1 < t1 + 64}
+  //
+  // and project out the auxilary dimensions a0 and a1.
+  isl_space *Space =
+      isl_space_alloc(ctx, 0, scheduleDimensions, scheduleDimensions * 3);
+  isl_basic_map *tileMap = isl_basic_map_universe(isl_space_copy(Space));
+
+  isl_local_space *LocalSpace = isl_local_space_from_space(Space);
+
+  for (int x = 0; x < scheduleDimensions; x++) {
+    int sX = x;
+    int tX = x;
+    int pX = scheduleDimensions + x;
+    int aX = 2 * scheduleDimensions + x;
+    int tileSize = (int)TileSizes.size() > x ? TileSizes[x] : DefaultTileSize;
+    assert(tileSize > 0 && "Invalid tile size");
+
+    isl_constraint *c;
+
+    // sX = aX * tileSize;
+    c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
+    isl_constraint_set_coefficient_si(c, isl_dim_out, sX, 1);
+    isl_constraint_set_coefficient_si(c, isl_dim_out, aX, -tileSize);
+    tileMap = isl_basic_map_add_constraint(tileMap, c);
+
+    // pX = sX;
+    c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
+    isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
+    isl_constraint_set_coefficient_si(c, isl_dim_in, sX, -1);
+    tileMap = isl_basic_map_add_constraint(tileMap, c);
+
+    // tX <= pX
+    c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
+    isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
+    isl_constraint_set_coefficient_si(c, isl_dim_out, tX, -1);
+    tileMap = isl_basic_map_add_constraint(tileMap, c);
+
+    // pX <= tX + (tileSize - 1)
+    c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
+    isl_constraint_set_coefficient_si(c, isl_dim_out, tX, 1);
+    isl_constraint_set_coefficient_si(c, isl_dim_out, pX, -1);
+    isl_constraint_set_constant_si(c, tileSize - 1);
+    tileMap = isl_basic_map_add_constraint(tileMap, c);
+  }
+
+  // Project out auxilary dimensions.
+  //
+  // The auxilary dimensions are transformed into existentially quantified ones.
+  // This reduces the number of visible scattering dimensions and allows Cloog
+  // to produces better code.
+  tileMap = isl_basic_map_project_out(
+      tileMap, isl_dim_out, 2 * scheduleDimensions, scheduleDimensions);
+  isl_local_space_free(LocalSpace);
+  return tileMap;
+}
+
+isl_union_map *IslScheduleOptimizer::getScheduleForBand(isl_band *Band,
+                                                        int *Dimensions) {
+  isl_union_map *PartialSchedule;
+  isl_ctx *ctx;
+  isl_space *Space;
+  isl_basic_map *TileMap;
+  isl_union_map *TileUMap;
+
+  PartialSchedule = isl_band_get_partial_schedule(Band);
+  *Dimensions = isl_band_n_member(Band);
+
+  if (DisableTiling)
+    return PartialSchedule;
+
+  // It does not make any sense to tile a band with just one dimension.
+  if (*Dimensions == 1)
+    return PartialSchedule;
+
+  ctx = isl_union_map_get_ctx(PartialSchedule);
+  Space = isl_union_map_get_space(PartialSchedule);
+
+  TileMap = getTileMap(ctx, *Dimensions, Space);
+  TileUMap = isl_union_map_from_map(isl_map_from_basic_map(TileMap));
+  TileUMap = isl_union_map_align_params(TileUMap, Space);
+  *Dimensions = 2 * *Dimensions;
+
+  return isl_union_map_apply_range(PartialSchedule, TileUMap);
+}
+
+isl_map *IslScheduleOptimizer::getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
+                                               int ScheduleDimensions,
+                                               int VectorWidth) {
+  isl_space *Space;
+  isl_local_space *LocalSpace, *LocalSpaceRange;
+  isl_set *Modulo;
+  isl_map *TilingMap;
+  isl_constraint *c;
+  isl_aff *Aff;
+  int PointDimension; /* ip */
+  int TileDimension;  /* it */
+  isl_val *VectorWidthMP;
+
+  assert(0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);
+
+  Space = isl_space_alloc(ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
+  TilingMap = isl_map_universe(isl_space_copy(Space));
+  LocalSpace = isl_local_space_from_space(Space);
+  PointDimension = ScheduleDimensions;
+  TileDimension = DimToVectorize;
+
+  // Create an identity map for everything except DimToVectorize and map
+  // DimToVectorize to the point loop at the innermost dimension.
+  for (int i = 0; i < ScheduleDimensions; i++) {
+    c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
+    c = isl_constraint_set_coefficient_si(c, isl_dim_in, i, -1);
+
+    if (i == DimToVectorize)
+      c = isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
+    else
+      c = isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
+
+    TilingMap = isl_map_add_constraint(TilingMap, c);
+  }
+
+  // it % 'VectorWidth' = 0
+  LocalSpaceRange = isl_local_space_range(isl_local_space_copy(LocalSpace));
+  Aff = isl_aff_zero_on_domain(LocalSpaceRange);
+  Aff = isl_aff_set_constant_si(Aff, VectorWidth);
+  Aff = isl_aff_set_coefficient_si(Aff, isl_dim_in, TileDimension, 1);
+  VectorWidthMP = isl_val_int_from_si(ctx, VectorWidth);
+  Aff = isl_aff_mod_val(Aff, VectorWidthMP);
+  Modulo = isl_pw_aff_zero_set(isl_pw_aff_from_aff(Aff));
+  TilingMap = isl_map_intersect_range(TilingMap, Modulo);
+
+  // it <= ip
+  c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
+  isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, -1);
+  isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
+  TilingMap = isl_map_add_constraint(TilingMap, c);
+
+  // ip <= it + ('VectorWidth' - 1)
+  c = isl_inequality_alloc(LocalSpace);
+  isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, 1);
+  isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, -1);
+  isl_constraint_set_constant_si(c, VectorWidth - 1);
+  TilingMap = isl_map_add_constraint(TilingMap, c);
+
+  return TilingMap;
+}
+
+isl_union_map *
+IslScheduleOptimizer::getScheduleForBandList(isl_band_list *BandList) {
+  int NumBands;
+  isl_union_map *Schedule;
+  isl_ctx *ctx;
+
+  ctx = isl_band_list_get_ctx(BandList);
+  NumBands = isl_band_list_n_band(BandList);
+  Schedule = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
+
+  for (int i = 0; i < NumBands; i++) {
+    isl_band *Band;
+    isl_union_map *PartialSchedule;
+    int ScheduleDimensions;
+    isl_space *Space;
+
+    Band = isl_band_list_get_band(BandList, i);
+    PartialSchedule = getScheduleForBand(Band, &ScheduleDimensions);
+    Space = isl_union_map_get_space(PartialSchedule);
+
+    if (isl_band_has_children(Band)) {
+      isl_band_list *Children;
+      isl_union_map *SuffixSchedule;
+
+      Children = isl_band_get_children(Band);
+      SuffixSchedule = getScheduleForBandList(Children);
+      PartialSchedule =
+          isl_union_map_flat_range_product(PartialSchedule, SuffixSchedule);
+      isl_band_list_free(Children);
+    } else if (PollyVectorizerChoice != VECTORIZER_NONE) {
+      // In case we are at the innermost band, we try to prepare for
+      // vectorization. This means, we look for the innermost parallel loop
+      // and strip mine this loop to the innermost level using a strip-mine
+      // factor corresponding to the number of vector iterations.
+      int NumDims = isl_band_n_member(Band);
+      for (int j = NumDims - 1; j >= 0; j--) {
+        if (isl_band_member_is_coincident(Band, j)) {
+          isl_map *TileMap;
+          isl_union_map *TileUMap;
+
+          TileMap = getPrevectorMap(ctx, ScheduleDimensions - NumDims + j,
+                                    ScheduleDimensions);
+          TileUMap = isl_union_map_from_map(TileMap);
+          TileUMap =
+              isl_union_map_align_params(TileUMap, isl_space_copy(Space));
+          PartialSchedule =
+              isl_union_map_apply_range(PartialSchedule, TileUMap);
+          break;
+        }
+      }
+    }
+
+    Schedule = isl_union_map_union(Schedule, PartialSchedule);
+
+    isl_band_free(Band);
+    isl_space_free(Space);
+  }
+
+  return Schedule;
+}
+
+isl_union_map *IslScheduleOptimizer::getScheduleMap(isl_schedule *Schedule) {
+  isl_band_list *BandList = isl_schedule_get_band_forest(Schedule);
+  isl_union_map *ScheduleMap = getScheduleForBandList(BandList);
+  isl_band_list_free(BandList);
+  return ScheduleMap;
+}
+
+bool IslScheduleOptimizer::runOnScop(Scop &S) {
+  Dependences *D = &getAnalysis<Dependences>();
+
+  if (!D->hasValidDependences())
+    return false;
+
+  isl_schedule_free(LastSchedule);
+  LastSchedule = nullptr;
+
+  // Build input data.
+  int ValidityKinds =
+      Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
+  int ProximityKinds;
+
+  if (OptimizeDeps == "all")
+    ProximityKinds =
+        Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
+  else if (OptimizeDeps == "raw")
+    ProximityKinds = Dependences::TYPE_RAW;
+  else {
+    errs() << "Do not know how to optimize for '" << OptimizeDeps << "'"
+           << " Falling back to optimizing all dependences.\n";
+    ProximityKinds =
+        Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
+  }
+
+  isl_union_set *Domain = S.getDomains();
+
+  if (!Domain)
+    return false;
+
+  isl_union_map *Validity = D->getDependences(ValidityKinds);
+  isl_union_map *Proximity = D->getDependences(ProximityKinds);
+
+  // Simplify the dependences by removing the constraints introduced by the
+  // domains. This can speed up the scheduling time significantly, as large
+  // constant coefficients will be removed from the dependences. The
+  // introduction of some additional dependences reduces the possible
+  // transformations, but in most cases, such transformation do not seem to be
+  // interesting anyway. In some cases this option may stop the scheduler to
+  // find any schedule.
+  if (SimplifyDeps == "yes") {
+    Validity = isl_union_map_gist_domain(Validity, isl_union_set_copy(Domain));
+    Validity = isl_union_map_gist_range(Validity, isl_union_set_copy(Domain));
+    Proximity =
+        isl_union_map_gist_domain(Proximity, isl_union_set_copy(Domain));
+    Proximity = isl_union_map_gist_range(Proximity, isl_union_set_copy(Domain));
+  } else if (SimplifyDeps != "no") {
+    errs() << "warning: Option -polly-opt-simplify-deps should either be 'yes' "
+              "or 'no'. Falling back to default: 'yes'\n";
+  }
+
+  DEBUG(dbgs() << "\n\nCompute schedule from: ");
+  DEBUG(dbgs() << "Domain := " << stringFromIslObj(Domain) << ";\n");
+  DEBUG(dbgs() << "Proximity := " << stringFromIslObj(Proximity) << ";\n");
+  DEBUG(dbgs() << "Validity := " << stringFromIslObj(Validity) << ";\n");
+
+  int IslFusionStrategy;
+
+  if (FusionStrategy == "max") {
+    IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX;
+  } else if (FusionStrategy == "min") {
+    IslFusionStrategy = ISL_SCHEDULE_FUSE_MIN;
+  } else {
+    errs() << "warning: Unknown fusion strategy. Falling back to maximal "
+              "fusion.\n";
+    IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX;
+  }
+
+  int IslMaximizeBands;
+
+  if (MaximizeBandDepth == "yes") {
+    IslMaximizeBands = 1;
+  } else if (MaximizeBandDepth == "no") {
+    IslMaximizeBands = 0;
+  } else {
+    errs() << "warning: Option -polly-opt-maximize-bands should either be 'yes'"
+              " or 'no'. Falling back to default: 'yes'\n";
+    IslMaximizeBands = 1;
+  }
+
+  isl_options_set_schedule_fuse(S.getIslCtx(), IslFusionStrategy);
+  isl_options_set_schedule_maximize_band_depth(S.getIslCtx(), IslMaximizeBands);
+  isl_options_set_schedule_max_constant_term(S.getIslCtx(), MaxConstantTerm);
+  isl_options_set_schedule_max_coefficient(S.getIslCtx(), MaxCoefficient);
+
+  isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE);
+
+  isl_schedule_constraints *ScheduleConstraints;
+  ScheduleConstraints = isl_schedule_constraints_on_domain(Domain);
+  ScheduleConstraints =
+      isl_schedule_constraints_set_proximity(ScheduleConstraints, Proximity);
+  ScheduleConstraints = isl_schedule_constraints_set_validity(
+      ScheduleConstraints, isl_union_map_copy(Validity));
+  ScheduleConstraints =
+      isl_schedule_constraints_set_coincidence(ScheduleConstraints, Validity);
+  isl_schedule *Schedule;
+  Schedule = isl_schedule_constraints_compute_schedule(ScheduleConstraints);
+  isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT);
+
+  // In cases the scheduler is not able to optimize the code, we just do not
+  // touch the schedule.
+  if (!Schedule)
+    return false;
+
+  DEBUG(dbgs() << "Schedule := " << stringFromIslObj(Schedule) << ";\n");
+
+  isl_union_map *ScheduleMap = getScheduleMap(Schedule);
+
+  for (ScopStmt *Stmt : S) {
+    isl_map *StmtSchedule;
+    isl_set *Domain = Stmt->getDomain();
+    isl_union_map *StmtBand;
+    StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(ScheduleMap),
+                                              isl_union_set_from_set(Domain));
+    if (isl_union_map_is_empty(StmtBand)) {
+      StmtSchedule = isl_map_from_domain(isl_set_empty(Stmt->getDomainSpace()));
+      isl_union_map_free(StmtBand);
+    } else {
+      assert(isl_union_map_n_map(StmtBand) == 1);
+      StmtSchedule = isl_map_from_union_map(StmtBand);
+    }
+
+    Stmt->setScattering(StmtSchedule);
+  }
+
+  isl_union_map_free(ScheduleMap);
+  LastSchedule = Schedule;
+
+  unsigned MaxScatDims = 0;
+
+  for (ScopStmt *Stmt : S)
+    MaxScatDims = std::max(Stmt->getNumScattering(), MaxScatDims);
+
+  extendScattering(S, MaxScatDims);
+  return false;
+}
+
+void IslScheduleOptimizer::printScop(raw_ostream &OS) const {
+  isl_printer *p;
+  char *ScheduleStr;
+
+  OS << "Calculated schedule:\n";
+
+  if (!LastSchedule) {
+    OS << "n/a\n";
+    return;
+  }
+
+  p = isl_printer_to_str(isl_schedule_get_ctx(LastSchedule));
+  p = isl_printer_print_schedule(p, LastSchedule);
+  ScheduleStr = isl_printer_get_str(p);
+  isl_printer_free(p);
+
+  OS << ScheduleStr << "\n";
+}
+
+void IslScheduleOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
+  ScopPass::getAnalysisUsage(AU);
+  AU.addRequired<Dependences>();
+}
+
+Pass *polly::createIslScheduleOptimizerPass() {
+  return new IslScheduleOptimizer();
+}
+
+INITIALIZE_PASS_BEGIN(IslScheduleOptimizer, "polly-opt-isl",
+                      "Polly - Optimize schedule of SCoP", false, false);
+INITIALIZE_PASS_DEPENDENCY(Dependences);
+INITIALIZE_PASS_DEPENDENCY(ScopInfo);
+INITIALIZE_PASS_END(IslScheduleOptimizer, "polly-opt-isl",
+                    "Polly - Optimize schedule of SCoP", false, false)
diff --git a/final/test/CMakeLists.txt b/final/test/CMakeLists.txt
new file mode 100644
index 0000000..a31562b
--- /dev/null
+++ b/final/test/CMakeLists.txt
@@ -0,0 +1,88 @@
+set(POLLY_TEST_DIRECTORIES
+  "AffineIterator"
+  "ScopInfo"
+  "ScheduleOptimizer"
+  "CodeGen"
+  "Cloog"
+  "OpenMP"
+  "polybench"
+  "vect")
+
+
+set(POLLY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
+set(POLLY_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/..")
+set(LLVM_SHLIBEXT "${CMAKE_SHARED_MODULE_SUFFIX}")
+
+if (NOT DEFINED LLVM_MAIN_SRC_DIR)
+
+  # We are building polly out of tree, adjust the settings.
+  # FIXME: FileCheck is not available in llvm install directory at the moment.
+  set(LLVM_LIT ${LLVM_INSTALL_ROOT}/bin/llvm-lit)
+  set(POLLY_TEST_DEPS LLVMPolly)
+
+  set(LLVM_BINARY_DIR "${LLVM_INSTALL_ROOT}")
+  set(LLVM_TOOLS_DIR "${LLVM_INSTALL_ROOT}/bin")
+  set(LLVM_LIBS_DIR "${LLVM_INSTALL_ROOT}/lib")
+  set(POLLY_LIB_DIR "${POLLY_BINARY_DIR}/lib")
+
+  include(FindPythonInterp)
+  if(PYTHONINTERP_FOUND)
+    option(POLLY_TEST_DISABLE_BAR "Run Polly tests with --no-progress-bar" OFF)
+    set(POLLY_TEST_EXTRA_ARGS)
+    if (MSVC OR XCODE OR POLLY_TEST_DISABLE_BAR)
+      set(POLLY_TEST_EXTRA_ARGS "--no-progress-bar")
+    endif()
+
+    option(POLLY_TEST_USE_VG "Run Polly tests under Valgrind" OFF)
+    if(POLLY_TEST_USE_VG)
+      set(POLLY_TEST_EXTRA_ARGS ${POLLY_TEST_EXTRA_ARGS} "--vg")
+    endif ()
+
+    foreach(testdir ${POLLY_TEST_DIRECTORIES})
+      add_custom_target(polly-test-${testdir}
+        COMMAND ${LLVM_LIT}
+                    --param polly_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+                    --param build_config=${CMAKE_CFG_INTDIR}
+                    -sv ${POLLY_TEST_EXTRA_ARGS}
+                    ${CMAKE_CURRENT_BINARY_DIR}/${testdir}
+                    DEPENDS ${POLLY_TEST_DEPS}
+                    COMMENT "Running Polly regression tests in ${testdir}")
+    endforeach()
+
+    add_custom_target(check-polly
+      COMMAND ${LLVM_LIT}
+                  --param polly_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+                  --param build_config=${CMAKE_CFG_INTDIR}
+                  -sv ${POLLY_TEST_EXTRA_ARGS}
+                  ${CMAKE_CURRENT_BINARY_DIR}
+                  DEPENDS ${POLLY_TEST_DEPS}
+                  COMMENT "Running Polly regression tests")
+  endif()
+
+else (NOT DEFINED LLVM_MAIN_SRC_DIR)
+
+  set(LLVM_LIT ${LLVM_TOOLS_BINARY_DIR}/llvm-lit)
+  set(POLLY_TEST_DEPS llvm-config opt LLVMPolly FileCheck not)
+
+  set(LLVM_BINARY_DIR "${LLVM_BINARY_DIR}")
+  set(LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}")
+  set(LLVM_LIBS_DIR "${LLVM_BINARY_DIR}/lib")
+  set(POLLY_LIB_DIR "${LLVM_LIBS_DIR}")
+
+  add_lit_testsuite(check-polly "Running polly regression tests"
+    ${CMAKE_CURRENT_BINARY_DIR}
+    PARAMS polly_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+    DEPENDS ${POLLY_TEST_DEPS}
+    )
+
+  set_target_properties(check-polly PROPERTIES FOLDER "polly tests")
+
+endif (NOT DEFINED LLVM_MAIN_SRC_DIR)
+
+configure_file(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
+
+# Add a legacy target spelling: polly-test
+add_custom_target(polly-test)
+add_dependencies(polly-test check-polly)
diff --git a/final/test/CodePreparation/if_condition.ll b/final/test/CodePreparation/if_condition.ll
new file mode 100644
index 0000000..d29d1df
--- /dev/null
+++ b/final/test/CodePreparation/if_condition.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-prepare -S < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-prepare -S < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br label %for.i
+; CHECK: entry:
+; CHECK: %value.reg2mem = alloca i64
+; CHECK: br label %entry.split
+
+for.i:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %merge ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  %cmp = icmp eq i64 %indvar, 3
+  br i1 %cmp, label %then, label %else
+
+then:
+  %add_two = add i64 %indvar, 2
+  br label %merge
+; CHECK: then:
+; CHECK:   %add_two = add i64 %indvar, 2
+; CHECK:   store i64 %add_two, i64* %value.reg2mem
+; CHECK:   br label %merge
+
+else:
+  %add_three = add i64 %indvar, 4
+  br label %merge
+; CHECK: else:
+; CHECK:   %add_three = add i64 %indvar, 4
+; CHECK:   store i64 %add_three, i64* %value.reg2mem
+; CHECK:   br label %merge
+
+merge:
+  %value = phi i64 [ %add_two, %then ], [ %add_three, %else ]
+  store i64 %value, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
diff --git a/final/test/CodePreparation/multiple_loops_trivial_phis.ll b/final/test/CodePreparation/multiple_loops_trivial_phis.ll
new file mode 100644
index 0000000..f8964ae
--- /dev/null
+++ b/final/test/CodePreparation/multiple_loops_trivial_phis.ll
@@ -0,0 +1,56 @@
+; RUN: opt %loadPolly -S -polly-prepare < %s | FileCheck %s
+; ModuleID = 'multiple_loops_trivial_phis.ll'
+;
+; int f(int * __restrict__ A) {
+;   int i, j, sum = 0;
+;   for (i = 0; i < 100; i++) {
+;     sum *= 2;
+;     for (j = 0; j < 100; j++) {
+;       sum += A[i+j];
+;     }
+;   }
+;   return sum;
+; }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define i32 @f(i32* noalias %A) #0 {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.inc5
+  %sum.04 = phi i32 [ 0, %entry ], [ %add4.lcssa, %for.inc5 ]
+  %indvars.iv23 = phi i64 [ 0, %entry ], [ %2, %for.inc5 ]
+  %mul = shl nsw i32 %sum.04, 1
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %for.inc
+  %sum.12 = phi i32 [ %mul, %for.body ], [ %add4, %for.inc ]
+  %indvars.iv1 = phi i64 [ 0, %for.body ], [ %1, %for.inc ]
+  %0 = add i64 %indvars.iv23, %indvars.iv1
+  %arrayidx = getelementptr i32* %A, i64 %0
+  %tmp5 = load i32* %arrayidx, align 4
+  %add4 = add nsw i32 %tmp5, %sum.12
+  %1 = add nuw nsw i64 %indvars.iv1, 1
+  %exitcond5 = icmp eq i64 %1, 100
+  br i1 %exitcond5, label %for.inc5, label %for.inc
+
+for.inc5:                                         ; preds = %for.inc
+  %add4.lcssa = phi i32 [ %add4, %for.inc ]
+  %2 = add nuw nsw i64 %indvars.iv23, 1
+  %exitcond = icmp eq i64 %2, 100
+  br i1 %exitcond, label %for.end7, label %for.body
+
+for.end7:                                         ; preds = %for.inc5
+  %add4.lcssa.lcssa = phi i32 [ %add4.lcssa, %for.inc5 ]
+  ret i32 %add4.lcssa.lcssa
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+; Verify that only two allocas are created. (instead of 4!)
+; CHECK: alloca
+; CHECK: alloca
+; CHECK-NOT: alloca
diff --git a/final/test/CodePreparation/single_loop_trivial_phi.ll b/final/test/CodePreparation/single_loop_trivial_phi.ll
new file mode 100644
index 0000000..e404da5
--- /dev/null
+++ b/final/test/CodePreparation/single_loop_trivial_phi.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -S -polly-prepare < %s | FileCheck %s
+; ModuleID = 'single_loop_trivial_phi.ll'
+;
+; int f(int *A, int N) {
+;   int i, sum = 0;
+;   for (i = 0; i < N; i++)
+;     sum += A[i];
+;   return sum;
+; }
+; ModuleID = 'stack-slots.ll'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define i32 @f(i32* %A, i32 %N) #0 {
+entry:
+  %cmp1 = icmp sgt i32 %N, 0
+  br i1 %cmp1, label %for.inc.lr.ph, label %for.end
+
+for.inc.lr.ph:                                    ; preds = %entry
+  %0 = zext i32 %N to i64
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.inc.lr.ph, %for.inc
+  %sum.03 = phi i32 [ 0, %for.inc.lr.ph ], [ %add, %for.inc ]
+  %indvars.iv2 = phi i64 [ 0, %for.inc.lr.ph ], [ %indvars.iv.next, %for.inc ]
+  %arrayidx = getelementptr i32* %A, i64 %indvars.iv2
+  %tmp1 = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp1, %sum.03
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv2, 1
+  %exitcond = icmp ne i64 %indvars.iv.next, %0
+  br i1 %exitcond, label %for.inc, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.inc
+  %add.lcssa = phi i32 [ %add, %for.inc ]
+  br label %for.end
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
+  %sum.0.lcssa = phi i32 [ %add.lcssa, %for.cond.for.end_crit_edge ], [ 0, %entry ]
+  ret i32 %sum.0.lcssa
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+; Verify that only two allocas are created.
+; Both are needed for the %sum.0 PHI node and none should be created for the
+; %sum.0.lcssa PHI node
+; CHECK: alloca
+; CHECK: alloca
+; CHECK-NOT: alloca
diff --git a/final/test/DeadCodeElimination/chained_iterations.ll b/final/test/DeadCodeElimination/chained_iterations.ll
new file mode 100644
index 0000000..5df2a59
--- /dev/null
+++ b/final/test/DeadCodeElimination/chained_iterations.ll
@@ -0,0 +1,62 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dependences-analysis-type=value-based -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt -S %loadPolly -basicaa -polly-dependences-analysis-type=value-based -polly-dce -polly-ast -analyze < %s | FileCheck %s -check-prefix=CHECK-DCE
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+;
+; for(i = 0; i < 200; i++ )
+;   A[i] = 2;
+;
+; for (i = 0; i < 200; i++ )
+;   A[i]  = 5;
+;
+; for (i = 0; i < 200; i++ )
+;   A[i] = 5;
+define void @main() nounwind uwtable {
+entry:
+  %A = alloca [200 x i32], align 16
+  br label %for.body.1
+
+for.body.1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %for.body.1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1, align 4
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 200
+  br i1 %exitcond.1, label %for.body.1, label %exit.1
+
+exit.1:
+  br label %for.body.2
+
+for.body.2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %for.body.2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2, align 4
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 200
+  br i1 %exitcond.2, label %for.body.2, label %exit.2
+
+exit.2:
+  br label %for.body.3
+
+for.body.3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %for.body.3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  store i32 7, i32* %arrayidx.3, align 4
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %for.body.3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_1(c1);
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_2(c1);
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_3(c1);
+
+; CHECK-DCE: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK-DCE:   Stmt_for_body_3(c1);
+
diff --git a/final/test/DeadCodeElimination/chained_iterations_2.ll b/final/test/DeadCodeElimination/chained_iterations_2.ll
new file mode 100644
index 0000000..5c84057
--- /dev/null
+++ b/final/test/DeadCodeElimination/chained_iterations_2.ll
@@ -0,0 +1,66 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dependences-analysis-type=value-based -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt -S %loadPolly -basicaa -polly-dependences-analysis-type=value-based -polly-dce -polly-ast -analyze < %s | FileCheck %s -check-prefix=CHECK-DCE
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+;
+; for(i = 0; i < 200; i++ )
+;   A[i] = 2;
+;
+; for (i = 0; i < 200; i++ )
+;   B[i] = A[i];
+;
+; for (i = 0; i < 200; i++ )
+;   B[i] = A[i] = 5;
+define void @main() nounwind uwtable {
+entry:
+  %A = alloca [200 x i32], align 16
+  %B = alloca [200 x i32], align 16
+  br label %for.body.1
+
+for.body.1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %for.body.1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1, align 4
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 200
+  br i1 %exitcond.1, label %for.body.1, label %exit.1
+
+exit.1:
+  br label %for.body.2
+
+for.body.2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %for.body.2 ]
+  %arrayidx.2.a = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  %val = load i32* %arrayidx.2.a, align 4
+  %arrayidx.2.b = getelementptr [200 x i32]* %B, i64 0, i64 %indvar.2
+  store i32 %val, i32* %arrayidx.2.b, align 4
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 200
+  br i1 %exitcond.2, label %for.body.2, label %exit.2
+
+exit.2:
+  br label %for.body.3
+
+for.body.3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %for.body.3 ]
+  %arrayidx.3.a = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  %arrayidx.3.b = getelementptr [200 x i32]* %B, i64 0, i64 %indvar.3
+  store i32 5, i32* %arrayidx.3.a, align 4
+  store i32 5, i32* %arrayidx.3.b, align 4
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %for.body.3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_1(c1);
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_2(c1);
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_3(c1);
+
+; CHECK-DCE: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK-DCE:   Stmt_for_body_3(c1);
diff --git a/final/test/DeadCodeElimination/computeout.ll b/final/test/DeadCodeElimination/computeout.ll
new file mode 100644
index 0000000..a908c4e
--- /dev/null
+++ b/final/test/DeadCodeElimination/computeout.ll
@@ -0,0 +1,64 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dce -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt -S %loadPolly -basicaa -polly-dce -polly-ast -analyze -polly-dependences-computeout=1 < %s | FileCheck %s -check-prefix=TIMEOUT
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+;     for(i = 0; i < 100; i++ )
+; S1:   A[i] = 2;
+;
+;     for (i = 0; i < 10; i++ )
+; S2:   A[i]  = 5;
+;
+;     for (i = 0; i < 200; i++ )
+; S3:   A[i] = 5;
+
+define void @sequential_writes() {
+entry:
+  %A = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  br label %S3
+
+S3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  store i32 7, i32* %arrayidx.3
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %S3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; CHECK-NOT: Stmt_S
+; CHECK: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK: Stmt_S3(c1);
+
+; TIMEOUT: for (int c1 = 0; c1 <= 99; c1 += 1)
+; TIMEOUT: Stmt_S1(c1);
+; TIMEOUT: for (int c1 = 0; c1 <= 9; c1 += 1)
+; TIMEOUT: Stmt_S2(c1);
+; TIMEOUT: for (int c1 = 0; c1 <= 199; c1 += 1)
+; TIMEOUT: Stmt_S3(c1);
+
diff --git a/final/test/DeadCodeElimination/dead_iteration_elimination.ll b/final/test/DeadCodeElimination/dead_iteration_elimination.ll
new file mode 100644
index 0000000..8549a0c
--- /dev/null
+++ b/final/test/DeadCodeElimination/dead_iteration_elimination.ll
@@ -0,0 +1,79 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dependences-analysis-type=value-based -polly-dce -polly-dce-precise-steps=2 -polly-ast -analyze < %s | FileCheck %s -check-prefix=CHECK
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+;
+; for(i = 0; i < 200; i++ )
+;   A[i] = 2;
+;
+; for (i = 0; i < 50; i++ )
+;   A[i]  = 5;
+;
+; for (i = 0; i < 70; i++ )
+;   A[i] = A[i] + 5;
+;
+; for (i = 100; i < 110; i++ )
+;   A[i] = i;
+;
+define void @main() nounwind uwtable {
+entry:
+  %A = alloca [200 x i32], align 16
+  br label %for.body.1
+
+for.body.1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %for.body.1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1, align 4
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 200
+  br i1 %exitcond.1, label %for.body.1, label %exit.1
+
+exit.1:
+  br label %for.body.2
+
+for.body.2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %for.body.2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2, align 4
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 50
+  br i1 %exitcond.2, label %for.body.2, label %exit.2
+
+exit.2:
+  br label %for.body.3
+
+for.body.3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %for.body.3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  %val = load i32* %arrayidx.3, align 4
+  %add = add nsw i32 %val, 5
+  store i32 %add, i32* %arrayidx.3, align 4
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 70
+  br i1 %exitcond.3, label %for.body.3 , label %exit.3
+
+exit.3:
+  br label %for.body.4
+
+for.body.4:
+  %indvar.4 = phi i64 [ 0, %exit.3 ], [ %indvar.next.4, %for.body.4 ]
+  %indvar.plus = add i64 %indvar.4, 100
+  %trunc = trunc i64 %indvar.plus to i32
+  %arrayidx.4 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.plus
+  store i32 %trunc, i32* %arrayidx.4, align 4
+  %indvar.next.4 = add i64 %indvar.4, 1
+  %exitcond.4 = icmp ne i64 %indvar.next.4, 10
+  br i1 %exitcond.4, label %for.body.4, label %exit.4
+
+exit.4:
+  ret void
+}
+
+; CHECK: for (int c1 = 50; c1 <= 99; c1 += 1)
+; CHECK:   Stmt_for_body_1(c1);
+; CHECK: for (int c1 = 110; c1 <= 199; c1 += 1)
+; CHECK:   Stmt_for_body_1(c1);
+; CHECK: for (int c1 = 0; c1 <= 49; c1 += 1)
+; CHECK:   Stmt_for_body_2(c1);
+; CHECK: for (int c1 = 0; c1 <= 69; c1 += 1)
+; CHECK:   Stmt_for_body_3(c1);
+; CHECK: for (int c1 = 0; c1 <= 9; c1 += 1)
diff --git a/final/test/DeadCodeElimination/non-affine-affine-mix.ll b/final/test/DeadCodeElimination/non-affine-affine-mix.ll
new file mode 100644
index 0000000..24b04a1
--- /dev/null
+++ b/final/test/DeadCodeElimination/non-affine-affine-mix.ll
@@ -0,0 +1,60 @@
+; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-ast -analyze < %s | FileCheck %s
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+; S1:    A[i % 2] = i;
+;      for (int i = 0; i < 1024; i++)
+; S2:    A[i2] = i;
+;    }
+
+; We unfortunately do need to execute all iterations of S1, as we do not know
+; the size of A and as a result S1 may write for example to A[1024], which
+; is not overwritten by S2.
+
+; CHECK: for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:   Stmt_S1(c1);
+; CHECK: for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:   Stmt_S2(c1);
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %S1, label %next
+
+S1:
+  %rem = srem i32 %i.0, 2
+  %arrayidx = getelementptr inbounds i32* %A, i32 %rem
+  store i32 %i.0, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+next:
+ br label %for.cond.2
+
+for.cond.2:
+  %i.2 = phi i32 [ 0, %next ], [ %inc.2, %for.inc.2 ]
+  %exitcond.2 = icmp ne i32 %i.2, 1024
+  br i1 %exitcond.2, label %S2, label %for.end
+
+S2:
+  %arrayidx.2 = getelementptr inbounds i32* %A, i32 %i.2
+  store i32 %i.2, i32* %arrayidx.2, align 4
+  br label %for.inc.2
+
+for.inc.2:
+  %inc.2 = add nsw i32 %i.2, 1
+  br label %for.cond.2
+
+for.end:
+  ret void
+}
+
diff --git a/final/test/DeadCodeElimination/non-affine.ll b/final/test/DeadCodeElimination/non-affine.ll
new file mode 100644
index 0000000..5f9e953
--- /dev/null
+++ b/final/test/DeadCodeElimination/non-affine.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-ast -analyze < %s | FileCheck %s
+;
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1)
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i % 2] = i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %rem = srem i32 %i.0, 2
+  %arrayidx = getelementptr inbounds i32* %A, i32 %rem
+  store i32 %i.0, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
diff --git a/final/test/DeadCodeElimination/null_schedule.ll b/final/test/DeadCodeElimination/null_schedule.ll
new file mode 100644
index 0000000..106eac2
--- /dev/null
+++ b/final/test/DeadCodeElimination/null_schedule.ll
@@ -0,0 +1,57 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dependences-analysis-type=value-based -polly-dce -polly-ast -analyze < %s | FileCheck %s -check-prefix=CHECK-DCE
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+; A[0] = 1;
+;
+; for(i = 0; i < 100; i++ )
+;   A[i+1] = A[i] * 2;
+;
+; for (i = 0; i < 200; i++ )
+;   A[i] = B[i] * 2;
+
+define void @main() nounwind uwtable {
+
+entry:
+  %A = alloca [200 x i32], align 16
+  %B = alloca [200 x i32], align 16
+
+  %A.zero = getelementptr [200 x i32]* %A, i64 0, i64 0
+  store i32 1, i32* %A.zero, align 4
+
+  br label %for.body.1
+
+for.body.1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %for.body.1 ]
+  %indvar.next.1 = add i64 %indvar.1, 1
+
+  %A.current.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  %val1.1 = load i32* %A.current.1, align 4
+  %val2.1 = mul i32 %val1.1, 2
+  %A.next.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.next.1
+  store i32 %val2.1, i32* %A.next.1, align 4
+
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %for.body.1, label %exit.1
+
+exit.1:
+  br label %for.body.2
+
+for.body.2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %for.body.2 ]
+
+  %B.current.2 = getelementptr [200 x i32]* %B, i64 0, i64 %indvar.2
+  %val1.2 = load i32* %B.current.2, align 4
+  %val2.2 = mul i32 %val1.2, 2
+  %A.current.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 %val2.2, i32* %A.current.2, align 4
+
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 200
+  br i1 %exitcond.2, label %for.body.2, label %exit.3
+
+exit.3:
+  ret void
+}
+
+; CHECK-DCE: for (int c1 = 0; c1 <= 199; c1 += 1)
+; CHECK-DCE:   Stmt_for_body_2(c1);
diff --git a/final/test/Dependences/computeout.ll b/final/test/Dependences/computeout.ll
new file mode 100644
index 0000000..c2339d2
--- /dev/null
+++ b/final/test/Dependences/computeout.ll
@@ -0,0 +1,72 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s -check-prefix=VALUE
+; RUN: opt -S %loadPolly -basicaa -polly-dependences -analyze -polly-dependences-computeout=1 < %s | FileCheck %s -check-prefix=TIMEOUT
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+;     for(i = 0; i < 100; i++ )
+; S1:   A[i] = 2;
+;
+;     for (i = 0; i < 10; i++ )
+; S2:   A[i]  = 5;
+;
+;     for (i = 0; i < 200; i++ )
+; S3:   A[i] = 5;
+
+define void @sequential_writes() {
+entry:
+  %A = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  br label %S3
+
+S3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  store i32 7, i32* %arrayidx.3
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %S3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; VALUE: region: 'S1 => exit.3' in function 'sequential_writes':
+; VALUE:   RAW dependences:
+; VALUE:     {  }
+; VALUE:   WAR dependences:
+; VALUE:     {  }
+; VALUE:   WAW dependences:
+; VALUE:     {
+; VALUE:       Stmt_S1[i0] -> Stmt_S2[i0] : i0 >= 0 and i0 <= 9;
+; VALUE:       Stmt_S2[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 9;
+; VALUE:       Stmt_S1[i0] -> Stmt_S3[i0] : i0 >= 10 and i0 <= 99
+; VALUE:     }
+
+; TIMEOUT: region: 'S1 => exit.3' in function 'sequential_writes':
+; TIMEOUT:   RAW dependences:
+; TIMEOUT:     n/a
+; TIMEOUT:   WAR dependences:
+; TIMEOUT:     n/a
+; TIMEOUT:   WAW dependences:
+; TIMEOUT:     n/a
diff --git a/final/test/Dependences/do_pluto_matmult.ll b/final/test/Dependences/do_pluto_matmult.ll
new file mode 100644
index 0000000..7d9799e
--- /dev/null
+++ b/final/test/Dependences/do_pluto_matmult.ll
@@ -0,0 +1,80 @@
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze -polly-dependences-analysis-type=value-based < %s | FileCheck %s -check-prefix=VALUE
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze -polly-dependences-analysis-type=memory-based -polly-delinearize < %s | FileCheck %s -check-prefix=MEMORY
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+
+@A = common global [36 x [49 x double]] zeroinitializer, align 8 ; <[36 x [49 x double]]*> [#uses=3]
+@B = common global [36 x [49 x double]] zeroinitializer, align 8 ; <[36 x [49 x double]]*> [#uses=3]
+@C = common global [36 x [49 x double]] zeroinitializer, align 8 ; <[36 x [49 x double]]*> [#uses=4]
+
+define void @do_pluto_matmult() nounwind {
+entry:
+  fence seq_cst
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond42, %entry
+  %indvar3 = phi i64 [ %indvar.next4, %do.cond42 ], [ 0, %entry ] ; <i64> [#uses=3]
+  br label %do.body1
+
+do.body1:                                         ; preds = %do.cond36, %do.body
+  %indvar1 = phi i64 [ %indvar.next2, %do.cond36 ], [ 0, %do.body ] ; <i64> [#uses=3]
+  %arrayidx5 = getelementptr [36 x [49 x double]]* @C, i64 0, i64 %indvar3, i64 %indvar1 ; <double*> [#uses=2]
+  br label %do.body2
+
+do.body2:                                         ; preds = %do.cond, %do.body1
+  %indvar = phi i64 [ %indvar.next, %do.cond ], [ 0, %do.body1 ] ; <i64> [#uses=3]
+  %arrayidx13 = getelementptr [36 x [49 x double]]* @A, i64 0, i64 %indvar3, i64 %indvar ; <double*> [#uses=1]
+  %arrayidx22 = getelementptr [36 x [49 x double]]* @B, i64 0, i64 %indvar, i64 %indvar1 ; <double*> [#uses=1]
+  %tmp6 = load double* %arrayidx5                 ; <double> [#uses=1]
+  %mul = fmul double 1.000000e+00, %tmp6          ; <double> [#uses=1]
+  %tmp14 = load double* %arrayidx13               ; <double> [#uses=1]
+  %mul15 = fmul double 1.000000e+00, %tmp14       ; <double> [#uses=1]
+  %tmp23 = load double* %arrayidx22               ; <double> [#uses=1]
+  %mul24 = fmul double %mul15, %tmp23             ; <double> [#uses=1]
+  %add = fadd double %mul, %mul24                 ; <double> [#uses=1]
+  store double %add, double* %arrayidx5
+  br label %do.cond
+
+do.cond:                                          ; preds = %do.body2
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=2]
+  %exitcond = icmp ne i64 %indvar.next, 36        ; <i1> [#uses=1]
+  br i1 %exitcond, label %do.body2, label %do.end
+
+do.end:                                           ; preds = %do.cond
+  br label %do.cond36
+
+do.cond36:                                        ; preds = %do.end
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=2]
+  %exitcond5 = icmp ne i64 %indvar.next2, 36      ; <i1> [#uses=1]
+  br i1 %exitcond5, label %do.body1, label %do.end39
+
+do.end39:                                         ; preds = %do.cond36
+  br label %do.cond42
+
+do.cond42:                                        ; preds = %do.end39
+  %indvar.next4 = add i64 %indvar3, 1             ; <i64> [#uses=2]
+  %exitcond6 = icmp ne i64 %indvar.next4, 36      ; <i1> [#uses=1]
+  br i1 %exitcond6, label %do.body, label %do.end45
+
+do.end45:                                         ; preds = %do.cond42
+  fence seq_cst
+  ret void
+}
+
+; VALUE: RAW dependences:
+; VALUE:  { Stmt_do_body2[i0, i1, i2] -> Stmt_do_body2[i0, i1, 1 + i2] : i0 >= 0 and i0 <= 35 and i1 >= 0 and i1 <= 35 and i2 >= 0 and i2 <= 34 }
+; VALUE: WAR dependences:
+; VALUE:  {  }
+; VALUE: WAW dependences:
+; VALUE:  { Stmt_do_body2[i0, i1, i2] -> Stmt_do_body2[i0, i1, 1 + i2] : i0 >= 0 and i0 <= 35 and i1 >= 0 and i1 <= 35 and i2 >= 0 and i2 <= 34 }
+
+; MEMORY: RAW dependences:
+; MEMORY:  { Stmt_do_body2[i0, i1, i2] -> Stmt_do_body2[i0, i1, o2] : i0 <= 35 and i0 >= 0 and i1 <= 35 and i1 >= 0 and i2 >= 0 and o2 >= 1 + i2 and o2 <= 35 and o2 >= 0 }
+; MEMORY: WAR dependences:
+; MEMORY:  { Stmt_do_body2[i0, i1, i2] -> Stmt_do_body2[i0, i1, o2] : i0 <= 35 and i0 >= 0 and i1 <= 35 and i1 >= 0 and i2 >= 0 and o2 >= 1 + i2 and o2 <= 35 and o2 >= 0 }
+; MEMORY: WAW dependences:
+; MEMORY:  { Stmt_do_body2[i0, i1, i2] -> Stmt_do_body2[i0, i1, o2] : i0 <= 35 and i0 >= 0 and i1 <= 35 and i1 >= 0 and i2 >= 0 and o2 >= 1 + i2 and o2 <= 35 and o2 >= 0 }
diff --git a/final/test/Dependences/reduction_complex_location.ll b/final/test/Dependences/reduction_complex_location.ll
new file mode 100644
index 0000000..8ed46b7
--- /dev/null
+++ b/final/test/Dependences/reduction_complex_location.ll
@@ -0,0 +1,59 @@
+; RUN: opt -basicaa %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_body3[i0, i1] -> Stmt_for_body3[2 + i0, -1 + i1] : i0 <= 97 and i0 >= 0 and i1 <= 99 and i1 >= 1 }
+;
+; void f(int *sum) {
+;   for (int i = 0; i < 100; i++)
+;     for (int j = 0; j < 100; j++)
+;       sum[i+j*2] += j * i;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %exitcond1 = icmp ne i32 %i.0, 100
+  br i1 %exitcond1, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 100
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %mul = mul nsw i32 %j.0, %i.0
+  %mul4 = shl nsw i32 %j.0, 1
+  %add = add nsw i32 %i.0, %mul4
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %add
+  %tmp = load i32* %arrayidx, align 4
+  %add5 = add nsw i32 %tmp, %mul
+  store i32 %add5, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll b/final/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll
new file mode 100644
index 0000000..ef79880
--- /dev/null
+++ b/final/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll
@@ -0,0 +1,62 @@
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s
+;
+; This loopnest contains a reduction which imposes the same dependences as the
+; accesses to the array A. We need to ensure we keep the dependences of A.
+;
+; CHECK: RAW dependences:
+; CHECK:   { Stmt_for_body[i0] -> Stmt_for_body[1 + i0] : i0 >= 0 and i0 <= 1022 }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   { Stmt_for_body[i0] -> Stmt_for_body[1 + i0] : i0 >= 0 and i0 <= 1022 }
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_body[i0] -> Stmt_for_body[1 + i0] : i0 <= 1022 and i0 >= 0 }
+;
+;
+;    void AandSum(int *restrict sum, int *restrict A) {
+;      for (int i = 0; i < 1024; i++) {
+;        A[i] = A[i] + A[i - 1];
+;        A[i - 1] = A[i] + A[i - 2];
+;        *sum += i;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @AandSum(i32* noalias %sum, i32* noalias %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %sub = add nsw i32 %i.0, -1
+  %arrayidx1 = getelementptr inbounds i32* %A, i32 %sub
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx2 = getelementptr inbounds i32* %A, i32 %i.0
+  store i32 %add, i32* %arrayidx2, align 4
+  %sub4 = add nsw i32 %i.0, -2
+  %arrayidx5 = getelementptr inbounds i32* %A, i32 %sub4
+  %tmp2 = load i32* %arrayidx5, align 4
+  %add6 = add nsw i32 %add, %tmp2
+  %sub7 = add nsw i32 %i.0, -1
+  %arrayidx8 = getelementptr inbounds i32* %A, i32 %sub7
+  store i32 %add6, i32* %arrayidx8, align 4
+  %tmp3 = load i32* %sum, align 4
+  %add9 = add nsw i32 %tmp3, %i.0
+  store i32 %add9, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll b/final/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll
new file mode 100644
index 0000000..b114fe6
--- /dev/null
+++ b/final/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll
@@ -0,0 +1,60 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK: RAW dependences:
+; CHECK-DAG: Stmt_for_body3[i0, 1] -> Stmt_for_body3[1 + i0, o1] : i0 <= 1022 and i0 >= 0 and o1 <= 511 and o1 >= 1
+; CHECK-DAG: Stmt_for_body3[i0, 0] -> Stmt_for_body3[i0, o1] : i0 <= 1023 and i0 >= 0 and o1 <= 511 and o1 >= 1
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[1 + i0, -1 + i1] : i0 <= 1022 and i0 >= 0 and i1 <= 511 and i1 >= 2
+; CHECK-DAG: Stmt_for_body3[i0, 2] -> Stmt_for_body3[2 + i0, 0] : i0 <= 1021 and i0 >= 0
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_body3[i0, 1] -> Stmt_for_body3[1 + i0, 0] : i0 <= 1022 and i0 >= 0 }
+;
+; void f(int *sum) {
+;   for (int i = 0; i < 1024; i++)
+;     for (int j = 0; j < 512; j++)
+;       sum[i + j] = sum[i] + 3;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 512
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 3
+  %add4 = add nsw i32 %i.0, %j.0
+  %arrayidx5 = getelementptr inbounds i32* %sum, i32 %add4
+  store i32 %add, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_multiple_loops_array_sum.ll b/final/test/Dependences/reduction_multiple_loops_array_sum.ll
new file mode 100644
index 0000000..20903fb
--- /dev/null
+++ b/final/test/Dependences/reduction_multiple_loops_array_sum.ll
@@ -0,0 +1,77 @@
+; RUN: opt -basicaa %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; Verify that only the inner reduction like accesses cause reduction dependences
+;
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : i0 <= 99 and i0 >= 0 and i1 <= 98 and i1 >= 0 }
+;
+; void f(int * restrict A, int * restrict sum) {
+;   int i, j, k;
+;   for (i = 0; i < 100; i++) {
+;     *sum *= 7;
+;     for (j = 0; j < 100; j++) {
+;       *sum += A[i+j];
+;       for (k = 0; k< 100; k++) {}
+;     }
+;   }
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc11, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc12, %for.inc11 ]
+  %exitcond2 = icmp ne i32 %i.0, 100
+  br i1 %exitcond2, label %for.body, label %for.end13
+
+for.body:                                         ; preds = %for.cond
+  %tmp = load i32* %sum, align 4
+  %mul = mul nsw i32 %tmp, 7
+  store i32 %mul, i32* %sum, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc8, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc9, %for.inc8 ]
+  %exitcond1 = icmp ne i32 %j.0, 100
+  br i1 %exitcond1, label %for.body3, label %for.end10
+
+for.body3:                                        ; preds = %for.cond1
+  %add = add nsw i32 %i.0, %j.0
+  %arrayidx = getelementptr inbounds i32* %A, i32 %add
+  %tmp3 = load i32* %arrayidx, align 4
+  %tmp4 = load i32* %sum, align 4
+  %add4 = add nsw i32 %tmp4, %tmp3
+  store i32 %add4, i32* %sum, align 4
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %k.0, 100
+  br i1 %exitcond, label %for.body7, label %for.end
+
+for.body7:                                        ; preds = %for.cond5
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body7
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond5
+
+for.end:                                          ; preds = %for.cond5
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %for.end
+  %inc9 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end10:                                        ; preds = %for.cond1
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.end10
+  %inc12 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end13:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_multiple_loops_array_sum_2.ll b/final/test/Dependences/reduction_multiple_loops_array_sum_2.ll
new file mode 100644
index 0000000..3398292
--- /dev/null
+++ b/final/test/Dependences/reduction_multiple_loops_array_sum_2.ll
@@ -0,0 +1,79 @@
+; RUN: opt %loadPolly -polly-dependences -analyze -basicaa < %s | FileCheck %s
+;
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : i0 <= 99 and i0 >= 0 and i1 <= 98 and i1 >= 0
+; CHECK-DAG: Stmt_for_body3[i0, 99] -> Stmt_for_body3[1 + i0, 0] : i0 <= 98 and i0 >= 0
+;
+; int f(int * restrict A, int * restrict sum) {
+;   int i, j, k;
+;   for (i = 0; i < 100; i++) {
+;     for (j = 0; j < 100; j++) {
+;       sum += A[i+j];
+;       for (k = 0; k< 100; k++) {}
+;     }
+;   }
+;   return sum;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc11, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc12, %for.inc11 ]
+  %exitcond2 = icmp ne i32 %i.0, 100
+  br i1 %exitcond2, label %for.body, label %for.end13
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc8, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc9, %for.inc8 ]
+  %exitcond1 = icmp ne i32 %j.0, 100
+  br i1 %exitcond1, label %for.body3, label %for.end10
+
+for.body3:                                        ; preds = %for.cond1
+  %add = add nsw i32 %i.0, %j.0
+  %arrayidx = getelementptr inbounds i32* %A, i32 %add
+  %tmp3 = load i32* %arrayidx, align 4
+  %tmp4 = load i32* %sum, align 4
+  %add4 = add nsw i32 %tmp4, %tmp3
+  store i32 %add4, i32* %sum, align 4
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %k.0, 100
+  br i1 %exitcond, label %for.body7, label %for.end
+
+for.body7:                                        ; preds = %for.cond5
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body7
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond5
+
+for.end:                                          ; preds = %for.cond5
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %for.end
+  %inc9 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end10:                                        ; preds = %for.cond1
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.end10
+  %inc12 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end13:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_multiple_loops_array_sum_3.ll b/final/test/Dependences/reduction_multiple_loops_array_sum_3.ll
new file mode 100644
index 0000000..4b699a1
--- /dev/null
+++ b/final/test/Dependences/reduction_multiple_loops_array_sum_3.ll
@@ -0,0 +1,73 @@
+; RUN: opt %loadPolly -polly-dependences -analyze -basicaa < %s | FileCheck %s
+;
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_inc[i0, i1] -> Stmt_for_inc[i0, 1 + i1] : i0 <= 99 and i0 >= 0 and i1 <= 98 and i1 >= 0 }
+;
+; int f(int * __restrict__ A) {
+;   int i, j, sum = 0;
+;   for (k = 0; k < 37; k = g(k)) {
+;     for (i = 0; i < 100; i++) {
+;       sum *= 2;
+;       for (j = 0; j < 100; j++) {
+;         sum += A[i+j];
+;       }
+;     }
+;   }
+;   return sum;
+; }
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare i64 @g(i64)
+
+define i32 @f(i32* noalias %A) {
+entry:
+  %sum.04.reg2mem = alloca i32
+  %sum.12.reg2mem = alloca i32
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  store i32 0, i32* %sum.04.reg2mem
+  br label %for.body_outer_split
+
+for.body_outer_split:                             ; preds = %entry.split, %for.inc5
+  %indvars.ivK = phi i64 [ 0, %entry.split ], [ %incK, %for.bos2 ]
+  br label %for.body_outer
+
+for.body_outer:                                   ; preds = %for.body_outer_split
+  %incK = call i64 @g(i64 %indvars.ivK)
+  %exitcondK = icmp eq i64 %incK, 100
+  br i1 %exitcondK, label %for.end7, label %for.body
+
+for.body:                                         ; preds = %for.inc5, %for.body_outer
+  %indvars.iv23 = phi i64 [ 0, %for.body_outer ], [ %3, %for.inc5 ]
+  %sum.04.reload = load i32* %sum.04.reg2mem
+  %mul = shl nsw i32 %sum.04.reload, 1
+  store i32 %mul, i32* %sum.12.reg2mem
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.inc, %for.body
+  %indvars.iv1 = phi i64 [ 0, %for.body ], [ %1, %for.inc ]
+  %sum.12.reload = load i32* %sum.12.reg2mem
+  %0 = add i64 %indvars.iv23, %indvars.iv1
+  %arrayidx = getelementptr i32* %A, i64 %0
+  %tmp5 = load i32* %arrayidx, align 4
+  %add4 = add nsw i32 %tmp5, %sum.12.reload
+  %1 = add nuw nsw i64 %indvars.iv1, 1
+  %exitcond1 = icmp eq i64 %1, 100
+  store i32 %add4, i32* %sum.12.reg2mem
+  br i1 %exitcond1, label %for.inc5, label %for.inc
+
+for.inc5:                                         ; preds = %for.inc
+  %2 = load i32* %sum.12.reg2mem
+  %3 = add nuw nsw i64 %indvars.iv23, 1
+  %exitcond2 = icmp eq i64 %3, 100
+  store i32 %2, i32* %sum.04.reg2mem
+  br i1 %exitcond2, label %for.bos2, label %for.body
+
+for.bos2:
+  br label %for.body_outer_split
+
+for.end7:                                         ; preds = %for.inc5
+  %4 = load i32* %sum.04.reg2mem
+  ret i32 %4
+}
diff --git a/final/test/Dependences/reduction_multiple_reductions.ll b/final/test/Dependences/reduction_multiple_reductions.ll
new file mode 100644
index 0000000..461f9e4
--- /dev/null
+++ b/final/test/Dependences/reduction_multiple_reductions.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s
+;
+; Verify we do not have dependences between the if and the else clause
+;
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK-DAG: Stmt_if_then[i0] -> Stmt_if_then[1 + i0] : i0 <= 510 and i0 >= 0
+; CHECK-DAG: Stmt_if_else[i0] -> Stmt_if_else[1 + i0] : i0 <= 1022 and i0 >= 512
+;
+; void f(int *restrict sum, int *restrict prod) {
+;   for (int i = 0; i < 1024; i++)
+;     if (i < 512)
+;       *sum += i;
+;     else
+;       *prod *= i;
+; }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %sum, i32* noalias %prod)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %cmp1 = icmp slt i32 %i.0, 512
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.body
+  %tmp = load i32* %sum, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %sum, align 4
+  br label %if.end
+
+if.else:                                          ; preds = %for.body
+  %tmp1 = load i32* %prod, align 4
+  %mul = mul nsw i32 %tmp1, %i.0
+  store i32 %mul, i32* %prod, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_multiple_reductions_2.ll b/final/test/Dependences/reduction_multiple_reductions_2.ll
new file mode 100644
index 0000000..6d1053b
--- /dev/null
+++ b/final/test/Dependences/reduction_multiple_reductions_2.ll
@@ -0,0 +1,110 @@
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK: RAW dependences:
+; CHECK-DAG: Stmt_S2[i0, i1] -> Stmt_S3[i0] : i0 <= 1023 and i0 >= 0 and i1 <= 1023 and i1 >= 0
+; CHECK-DAG: Stmt_S3[i0] -> Stmt_S0[1 + i0] : i0 >= 0 and i0 <= 1022
+; CHECK-DAG: Stmt_S0[i0] -> Stmt_S1[i0, o1] : i0 <= 1023 and i0 >= 0 and o1 <= 1023 and o1 >= 0
+; These are the important RAW dependences, as they need to originate/end in only one iteration:
+; CHECK-DAG: Stmt_S1[i0, 1023] -> Stmt_S2[i0, o1] : i0 <= 1023 and i0 >= 0 and o1 <= 1023 and o1 >= 0
+; CHECK-DAG: Stmt_S1[i0, i1] -> Stmt_S2[i0, 0] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK-DAG: Stmt_S2[i0, i1] -> Stmt_S3[i0] : i0 <= 1023 and i0 >= 0 and i1 <= 1023 and i1 >= 0
+; CHECK-DAG: Stmt_S3[i0] -> Stmt_S0[1 + i0] : i0 >= 0 and i0 <= 1022
+; CHECK-DAG: Stmt_S0[i0] -> Stmt_S1[i0, o1] : i0 <= 1023 and i0 >= 0 and o1 <= 1023 and o1 >= 0
+; These are the important WAW dependences, as they need to originate/end in only one iteration:
+; CHECK-DAG: Stmt_S1[i0, 1023] -> Stmt_S2[i0, o1] : i0 <= 1023 and i0 >= 0 and o1 <= 1023 and o1 >= 0
+; CHECK-DAG: Stmt_S1[i0, i1] -> Stmt_S2[i0, 0] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0
+; CHECK: Reduction dependences:
+; CHECK-DAG:  Stmt_S1[i0, i1] -> Stmt_S1[i0, 1 + i1] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0
+; CHECK-DAG:  Stmt_S2[i0, i1] -> Stmt_S2[i0, 1 + i1] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0
+;
+;    void f(int *restrict red) {
+;      for (int j = 0; j < 1024; j++) {
+; S0:    *red = 42 + *red * 5;
+;        for (int i = 0; i < 1024; i++)
+; S1:      *red *= i;
+;        for (int i = 0; i < 1024; i++)
+; S2:      *red += i;
+; S3:    *red = 42 + *red * 7;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %red)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc15, %entry
+  %j.0 = phi i32 [ 0, %entry ], [ %inc16, %for.inc15 ]
+  %exitcond2 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond2, label %for.body, label %for.end17
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %tmp = load i32* %red, align 4
+  %mul = mul nsw i32 %tmp, 5
+  %add = add nsw i32 %mul, 42
+  store i32 %add, i32* %red, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %S0
+  %i.0 = phi i32 [ 0, %S0 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  br label %S1
+
+S1:                                               ; preds = %for.body3
+  %tmp3 = load i32* %red, align 4
+  %mul4 = mul nsw i32 %tmp3, %i.0
+  store i32 %mul4, i32* %red, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S1
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc10, %for.end
+  %i5.0 = phi i32 [ 0, %for.end ], [ %inc11, %for.inc10 ]
+  %exitcond1 = icmp ne i32 %i5.0, 1024
+  br i1 %exitcond1, label %for.body8, label %for.end12
+
+for.body8:                                        ; preds = %for.cond6
+  br label %S2
+
+S2:                                               ; preds = %for.body8
+  %tmp4 = load i32* %red, align 4
+  %add9 = add nsw i32 %tmp4, %i5.0
+  store i32 %add9, i32* %red, align 4
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %S2
+  %inc11 = add nsw i32 %i5.0, 1
+  br label %for.cond6
+
+for.end12:                                        ; preds = %for.cond6
+  br label %S3
+
+S3:                                               ; preds = %for.end12
+  %tmp5 = load i32* %red, align 4
+  %mul13 = mul nsw i32 %tmp5, 7
+  %add14 = add nsw i32 %mul13, 42
+  store i32 %add14, i32* %red, align 4
+  br label %for.inc15
+
+for.inc15:                                        ; preds = %S3
+  %inc16 = add nsw i32 %j.0, 1
+  br label %for.cond
+
+for.end17:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_only_reduction_like_access.ll b/final/test/Dependences/reduction_only_reduction_like_access.ll
new file mode 100644
index 0000000..c12949a
--- /dev/null
+++ b/final/test/Dependences/reduction_only_reduction_like_access.ll
@@ -0,0 +1,44 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; FIXME: Change the comment once we allow different pointers
+; The statement is "almost" reduction like but should not yield any reduction dependences
+;
+; We are limited to binary reductions at the moment and this is not one.
+; There are never at least two iterations which read __and__ write to the same
+; location, thus we won't find the RAW and WAW dependences of a reduction,
+; thus we should not find Reduction dependences.
+;
+; CHECK:  Reduction dependences:
+; CHECK:    {  }
+;
+; void f(int *sum) {
+;   for (int i = 0; i < 100; i++)
+;     sum[i] = sum[99-i] + i;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %sub = sub nsw i32 99, %i.0
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %sub
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  %arrayidx1 = getelementptr inbounds i32* %sum, i32 %i.0
+  store i32 %add, i32* %arrayidx1, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_partially_escaping_intermediate_in_other_stmt.ll b/final/test/Dependences/reduction_partially_escaping_intermediate_in_other_stmt.ll
new file mode 100644
index 0000000..c48d8f0
--- /dev/null
+++ b/final/test/Dependences/reduction_partially_escaping_intermediate_in_other_stmt.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-dependences -analyze -basicaa < %s | FileCheck %s
+;
+; CHECK: Reduction dependences:
+; CHECK:   [N] -> { Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0 and i1 >= 1024 - N + i0 }
+;
+; void f(int N, int * restrict sums, int * restrict escape) {
+;   for (int i = 0; i < 1024; i++) {
+;     for (int j = 0; j < 1024; j++) {
+;       sums[i] += 5;
+;       if (N - i + j < 1024)
+;         escape[N - i + j] = sums[i];
+;     }
+;   }
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32 %N, i32* noalias %sums, i32* noalias %escape) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sums, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 5
+  store i32 %add, i32* %arrayidx, align 4
+  %sub = sub nsw i32 %N, %i.0
+  %add4 = add nsw i32 %sub, %j.0
+  %cmp5 = icmp slt i32 %add4, 1024
+  br i1 %cmp5, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body3
+  %arrayidx6 = getelementptr inbounds i32* %sums, i32 %i.0
+  %tmp2 = load i32* %arrayidx6, align 4
+  %sub7 = sub nsw i32 %N, %i.0
+  %add8 = add nsw i32 %sub7, %j.0
+  %arrayidx9 = getelementptr inbounds i32* %escape, i32 %add8
+  store i32 %tmp2, i32* %arrayidx9, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body3
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_privatization_deps.ll b/final/test/Dependences/reduction_privatization_deps.ll
new file mode 100644
index 0000000..a4f0895
--- /dev/null
+++ b/final/test/Dependences/reduction_privatization_deps.ll
@@ -0,0 +1,114 @@
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK:      RAW dependences:
+; CHECK-DAG:    Stmt_S0[i0] -> Stmt_S1[o0, i0 - o0] : i0 <= 1023 and o0 >= 0 and o0 <= i0
+; CHECK-DAG:    Stmt_S1[i0, i1] -> Stmt_S2[-1 + i0 + i1] : i0 >= 0 and i1 >= 1 and i0 <= 1022 and i1 <= 1024 - i0 and i1 <= 1023
+; CHECK-DAG:    Stmt_S1[1023, i1] -> Stmt_S2[1022 + i1] : i1 <= 1 and i1 >= 0
+; CHECK-DAG:    Stmt_S1[i0, 0] -> Stmt_S2[-1 + i0] : i0 <= 1022 and i0 >= 1
+; CHECK:      WAR dependences:
+; CHECK-DAG:    Stmt_S2[i0] -> Stmt_S2[1 + i0] : i0 <= 1022 and i0 >= 0
+; CHECK-DAG:    Stmt_S1[i0, i1] -> Stmt_S2[i0 + i1] : i0 >= 0 and i1 <= 1023 - i0 and i1 >= 1
+; CHECK-DAG:    Stmt_S1[i0, 0] -> Stmt_S2[i0] : i0 <= 1023 and i0 >= 1
+; CHECK:      WAW dependences:
+; CHECK-DAG:    Stmt_S0[i0] -> Stmt_S1[o0, i0 - o0] : i0 <= 1023 and o0 >= 0 and o0 <= i0
+; CHECK-DAG:    Stmt_S1[0, 0] -> Stmt_S2[0]
+; CHECK:      Reduction dependences:
+; CHECK-DAG:    Stmt_S1[i0, i1] -> Stmt_S1[1 + i0, -1 + i1] : i0 <= 1022 and i0 >= 0 and i1 <= 1023 and i1 >= 1
+;
+;    void f(int *sum) {
+;      for (int i = 0; i < 1024; i++)
+; S0:    sum[i] = 0;
+;      for (int i = 0; i < 1024; i++)
+;        for (int j = 0; j < 1024; j++)
+; S1:      sum[i + j] += i;
+;      for (int i = 0; i < 1024; i++)
+; S2:    sum[i] = sum[i + 1] * 3;
+;    }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond3 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond3, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %i.0
+  store i32 0, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc13, %for.end
+  %i1.0 = phi i32 [ 0, %for.end ], [ %inc14, %for.inc13 ]
+  %exitcond2 = icmp ne i32 %i1.0, 1024
+  br i1 %exitcond2, label %for.body4, label %for.end15
+
+for.body4:                                        ; preds = %for.cond2
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc10, %for.body4
+  %j.0 = phi i32 [ 0, %for.body4 ], [ %inc11, %for.inc10 ]
+  %exitcond1 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond1, label %for.body7, label %for.end12
+
+for.body7:                                        ; preds = %for.cond5
+  br label %S1
+
+S1:                                               ; preds = %for.body7
+  %add = add nsw i32 %i1.0, %j.0
+  %arrayidx8 = getelementptr inbounds i32* %sum, i32 %add
+  %tmp = load i32* %arrayidx8, align 4
+  %add9 = add nsw i32 %tmp, %i1.0
+  store i32 %add9, i32* %arrayidx8, align 4
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %S1
+  %inc11 = add nsw i32 %j.0, 1
+  br label %for.cond5
+
+for.end12:                                        ; preds = %for.cond5
+  br label %for.inc13
+
+for.inc13:                                        ; preds = %for.end12
+  %inc14 = add nsw i32 %i1.0, 1
+  br label %for.cond2
+
+for.end15:                                        ; preds = %for.cond2
+  br label %for.cond17
+
+for.cond17:                                       ; preds = %for.inc23, %for.end15
+  %i16.0 = phi i32 [ 0, %for.end15 ], [ %inc24, %for.inc23 ]
+  %exitcond = icmp ne i32 %i16.0, 1024
+  br i1 %exitcond, label %for.body19, label %for.end25
+
+for.body19:                                       ; preds = %for.cond17
+  br label %S2
+
+S2:                                               ; preds = %for.body19
+  %add20 = add nsw i32 %i16.0, 1
+  %arrayidx21 = getelementptr inbounds i32* %sum, i32 %add20
+  %tmp4 = load i32* %arrayidx21, align 4
+  %mul = mul nsw i32 %tmp4, 3
+  %arrayidx22 = getelementptr inbounds i32* %sum, i32 %i16.0
+  store i32 %mul, i32* %arrayidx22, align 4
+  br label %for.inc23
+
+for.inc23:                                        ; preds = %S2
+  %inc24 = add nsw i32 %i16.0, 1
+  br label %for.cond17
+
+for.end25:                                        ; preds = %for.cond17
+  ret void
+}
diff --git a/final/test/Dependences/reduction_privatization_deps_2.ll b/final/test/Dependences/reduction_privatization_deps_2.ll
new file mode 100644
index 0000000..979b0ea
--- /dev/null
+++ b/final/test/Dependences/reduction_privatization_deps_2.ll
@@ -0,0 +1,86 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; We have privatization dependences from a textually later statement to a
+; textually earlier one, but the dependences still go forward in time.
+;
+;  CHECK: RAW dependences:
+;  CHECK-DAG:  Stmt_S3[i0] -> Stmt_S2[1 + i0, o1] : i0 <= 97 and i0 >= 0 and o1 <= 99 and o1 >= 0
+;  CHECK-DAG:  Stmt_S1[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 98
+;  CHECK: WAR dependences:
+;  CHECK:   {  }
+;  CHECK: WAW dependences:
+;  CHECK-DAG:  Stmt_S3[i0] -> Stmt_S2[1 + i0, o1] : i0 <= 97 and i0 >= 0 and o1 <= 99 and o1 >= 0
+;  CHECK-DAG:  Stmt_S1[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 98
+;  CHECK: Reduction dependences:
+;  CHECK:   { Stmt_S2[i0, i1] -> Stmt_S2[i0, 1 + i1] : i0 <= 98 and i0 >= 0 and i1 <= 98 and i1 >= 0 }
+;
+;    void f(int *sum) {
+;      int i, j;
+;      for (i = 0; i < 99; i++) {
+; S1:    sum[i + 1] += 42;
+;        for (j = 0; j < 100; j++)
+; S2:      sum[i] += i * j;
+; S3:    sum[i + 1] += 7;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond1 = icmp ne i32 %i.0, 99
+  br i1 %exitcond1, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %S1
+
+S1:                                               ; preds = %for.body
+  %add = add nsw i32 %i.0, 1
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %add
+  %tmp = load i32* %arrayidx, align 4
+  %add1 = add nsw i32 %tmp, 42
+  store i32 %add1, i32* %arrayidx, align 4
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc, %S1
+  %j.0 = phi i32 [ 0, %S1 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 100
+  br i1 %exitcond, label %for.body4, label %for.end
+
+for.body4:                                        ; preds = %for.cond2
+  br label %S2
+
+S2:                                               ; preds = %for.body4
+  %mul = mul nsw i32 %i.0, %j.0
+  %arrayidx5 = getelementptr inbounds i32* %sum, i32 %i.0
+  %tmp2 = load i32* %arrayidx5, align 4
+  %add6 = add nsw i32 %tmp2, %mul
+  store i32 %add6, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S2
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond2
+
+for.end:                                          ; preds = %for.cond2
+  br label %S3
+
+S3:                                               ; preds = %for.end
+  %add7 = add nsw i32 %i.0, 1
+  %arrayidx8 = getelementptr inbounds i32* %sum, i32 %add7
+  %tmp3 = load i32* %arrayidx8, align 4
+  %add9 = add nsw i32 %tmp3, 7
+  store i32 %add9, i32* %arrayidx8, align 4
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %S3
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_privatization_deps_3.ll b/final/test/Dependences/reduction_privatization_deps_3.ll
new file mode 100644
index 0000000..8924492
--- /dev/null
+++ b/final/test/Dependences/reduction_privatization_deps_3.ll
@@ -0,0 +1,89 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+;  CHECK: RAW dependences:
+;  CHECK-DAG:  Stmt_S2[0, 0] -> Stmt_S3[1]
+;  CHECK-DAG:  Stmt_S2[i0, 1 - i0] -> Stmt_S3[i0] : i0 <= 1 and i0 >= 0
+;  CHECK-DAG:  Stmt_S3[i0] -> Stmt_S2[o0, 1 - i0] : i0 <= 1 and i0 >= 0 and o0 >= 1 + i0 and o0 <= 98
+;  CHECK-DAG:  Stmt_S1[i0] -> Stmt_S3[2 + i0] : i0 >= 0 and i0 <= 96
+;  CHECK: WAR dependences:
+;  CHECK:   {  }
+;  CHECK: WAW dependences:
+;  CHECK-DAG:  Stmt_S2[0, 0] -> Stmt_S3[1]
+;  CHECK-DAG:  Stmt_S2[i0, 1 - i0] -> Stmt_S3[i0] : i0 <= 1 and i0 >= 0
+;  CHECK-DAG:  Stmt_S3[i0] -> Stmt_S2[o0, 1 - i0] : i0 <= 1 and i0 >= 0 and o0 >= 1 + i0 and o0 <= 98
+;  CHECK-DAG:  Stmt_S1[i0] -> Stmt_S3[2 + i0] : i0 >= 0 and i0 <= 96
+;  CHECK: Reduction dependences:
+;  CHECK-DAG:  Stmt_S2[i0, i1] -> Stmt_S2[1 + i0, i1] : i0 <= 97 and i0 >= 0 and i1 <= 98 - i0 and i1 >= 0 and i1 >= 2 - i0
+;  CHECK-DAG:  Stmt_S2[0, 0] -> Stmt_S2[1, 0]
+;
+;    void f(int *sum) {
+;      int i, j;
+;      for (i = 0; i < 99; i++) {
+; S1:    sum[i + 1] += 42;
+;        for (j = i; j < 100; j++)
+; S2:      sum[i - j] += i * j;
+; S3:    sum[i - 1] += 7;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond1 = icmp ne i32 %i.0, 99
+  br i1 %exitcond1, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %S1
+
+S1:                                               ; preds = %for.body
+  %add = add nsw i32 %i.0, 1
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %add
+  %tmp = load i32* %arrayidx, align 4
+  %add1 = add nsw i32 %tmp, 42
+  store i32 %add1, i32* %arrayidx, align 4
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc, %S1
+  %j.0 = phi i32 [ %i.0, %S1 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 100
+  br i1 %exitcond, label %for.body4, label %for.end
+
+for.body4:                                        ; preds = %for.cond2
+  br label %S2
+
+S2:                                               ; preds = %for.body4
+  %mul = mul nsw i32 %i.0, %j.0
+  %sub = sub nsw i32 %i.0, %j.0
+  %arrayidx5 = getelementptr inbounds i32* %sum, i32 %sub
+  %tmp2 = load i32* %arrayidx5, align 4
+  %add6 = add nsw i32 %tmp2, %mul
+  store i32 %add6, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S2
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond2
+
+for.end:                                          ; preds = %for.cond2
+  br label %S3
+
+S3:                                               ; preds = %for.end
+  %sub7 = add nsw i32 %i.0, -1
+  %arrayidx8 = getelementptr inbounds i32* %sum, i32 %sub7
+  %tmp3 = load i32* %arrayidx8, align 4
+  %add9 = add nsw i32 %tmp3, 7
+  store i32 %add9, i32* %arrayidx8, align 4
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %S3
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_privatization_deps_4.ll b/final/test/Dependences/reduction_privatization_deps_4.ll
new file mode 100644
index 0000000..190bd94
--- /dev/null
+++ b/final/test/Dependences/reduction_privatization_deps_4.ll
@@ -0,0 +1,84 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK:     RAW dependences:
+; CHECK-DAG:   Stmt_S2[i0, i1] -> Stmt_S1[i1] : i0 >= 0 and i1 >= 1 + i0 and i1 <= 98
+; CHECK-DAG:   Stmt_S1[i0] -> Stmt_S2[i0, i0] : i0 >= 0 and i0 <= 98
+; CHECK-DAG:   Stmt_S2[i0, i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 98
+; CHECK-DAG:   Stmt_S3[i0] -> Stmt_S2[o0, i0] : i0 >= 0 and o0 >= 1 + i0 and o0 <= 98
+; CHECK:     WAR dependences:
+; CHECK-DAG:    {  }
+; CHECK:     WAW dependences:
+; CHECK-DAG:   Stmt_S2[i0, i1] -> Stmt_S1[i1] : i0 >= 0 and i1 >= 1 + i0 and i1 <= 98
+; CHECK-DAG:   Stmt_S1[i0] -> Stmt_S2[i0, i0] : i0 >= 0 and i0 <= 98
+; CHECK-DAG:   Stmt_S2[i0, i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 98
+; CHECK-DAG:   Stmt_S3[i0] -> Stmt_S2[o0, i0] : i0 >= 0 and o0 >= 1 + i0 and o0 <= 98
+; CHECK:     Reduction dependences:
+; CHECK-DAG:    { Stmt_S2[i0, i1] -> Stmt_S2[1 + i0, i1] : (i0 >= 0 and i1 >= 2 + i0 and i1 <= 99) or (i0 <= 97 and i1 >= 0 and i1 <= -1 + i0) }
+;
+;    void f(int *sum) {
+;      for (int i = 0; i < 99; i++) {
+; S1:    sum[i] += 42;
+;        for (int j = 0; j < 100; j++)
+; S2:      sum[j] += i * j;
+; S3:    sum[i] += 7;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc8, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc9, %for.inc8 ]
+  %exitcond1 = icmp ne i32 %i.0, 99
+  br i1 %exitcond1, label %for.body, label %for.end10
+
+for.body:                                         ; preds = %for.cond
+  br label %S1
+
+S1:                                               ; preds = %for.body
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 42
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %S1
+  %j.0 = phi i32 [ 0, %S1 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 100
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  br label %S2
+
+S2:                                               ; preds = %for.body3
+  %mul = mul nsw i32 %i.0, %j.0
+  %arrayidx4 = getelementptr inbounds i32* %sum, i32 %j.0
+  %tmp2 = load i32* %arrayidx4, align 4
+  %add5 = add nsw i32 %tmp2, %mul
+  store i32 %add5, i32* %arrayidx4, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S2
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %S3
+
+S3:                                               ; preds = %for.end
+  %arrayidx6 = getelementptr inbounds i32* %sum, i32 %i.0
+  %tmp3 = load i32* %arrayidx6, align 4
+  %add7 = add nsw i32 %tmp3, 7
+  store i32 %add7, i32* %arrayidx6, align 4
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %S3
+  %inc9 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end10:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_privatization_deps_5.ll b/final/test/Dependences/reduction_privatization_deps_5.ll
new file mode 100644
index 0000000..b6b4dbd
--- /dev/null
+++ b/final/test/Dependences/reduction_privatization_deps_5.ll
@@ -0,0 +1,88 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK:     RAW dependences:
+; CHECK-DAG:   Stmt_S2[i0, 0] -> Stmt_S1[1 + i0, 0] : i0 >= 0 and i0 <= 97
+; CHECK-DAG:   Stmt_S1[i0, 0] -> Stmt_S2[i0, 0] : i0 >= 0 and i0 <= 98
+; CHECK:     WAR dependences:
+; CHECK-DAG:   {  }
+; CHECK:     WAW dependences:
+; CHECK-DAG:   Stmt_S2[i0, 0] -> Stmt_S1[1 + i0, 0] : i0 >= 0 and i0 <= 97
+; CHECK-DAG:   Stmt_S1[i0, 0] -> Stmt_S2[i0, 0] : i0 >= 0 and i0 <= 98
+; CHECK:     Reduction dependences:
+; CHECK-DAG:   { Stmt_S2[i0, i1] -> Stmt_S2[1 + i0, i1] : i0 <= 97 and i0 >= 0 and i1 <= 99 and i1 >= 1 }
+;
+;    void f(int *sum) {
+;      for (int i = 0; i < 99; i++) {
+;        for (int j = 0; j < 1; j++)
+; S1:      sum[j] += 42;
+;        for (int j = 0; j < 100; j++)
+; S2:      sum[j] += i * j;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc12, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc13, %for.inc12 ]
+  %exitcond2 = icmp ne i32 %i.0, 99
+  br i1 %exitcond2, label %for.body, label %for.end14
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  br label %S1
+
+S1:                                               ; preds = %for.body3
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %j.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 42
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S1
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc9, %for.end
+  %j.1 = phi i32 [ 0, %for.end ], [ %inc10, %for.inc9 ]
+  %exitcond1 = icmp ne i32 %j.1, 100
+  br i1 %exitcond1, label %for.body6, label %for.end11
+
+for.body6:                                        ; preds = %for.cond4
+  br label %S2
+
+S2:                                               ; preds = %for.body6
+  %mul = mul nsw i32 %i.0, %j.1
+  %arrayidx7 = getelementptr inbounds i32* %sum, i32 %j.1
+  %tmp3 = load i32* %arrayidx7, align 4
+  %add8 = add nsw i32 %tmp3, %mul
+  store i32 %add8, i32* %arrayidx7, align 4
+  br label %for.inc9
+
+for.inc9:                                         ; preds = %S2
+  %inc10 = add nsw i32 %j.1, 1
+  br label %for.cond4
+
+for.end11:                                        ; preds = %for.cond4
+  br label %for.inc12
+
+for.inc12:                                        ; preds = %for.end11
+  %inc13 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end14:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_simple_iv.ll b/final/test/Dependences/reduction_simple_iv.ll
new file mode 100644
index 0000000..1dd9d51
--- /dev/null
+++ b/final/test/Dependences/reduction_simple_iv.ll
@@ -0,0 +1,40 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK:  RAW dependences:
+; CHECK:    {  }
+; CHECK:  WAR dependences:
+; CHECK:    {  }
+; CHECK:  WAW dependences:
+; CHECK:    {  }
+; CHECK:  Reduction dependences:
+; CHECK:    { Stmt_for_cond[i0] -> Stmt_for_cond[1 + i0] : i0 <= 99 and i0 >= 0 }
+;
+; void f(int* sum) {
+;   for (int i = 0; i <= 100; i++)
+;     sum += i * 3;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %entry.split1
+
+entry.split1:                                     ; preds = %entry
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry.split1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entry.split
+  %i1.0 = phi i32 [ 0, %entry.split ], [ %inc, %for.cond ]
+  %sum.reload = load i32* %sum
+  %mul = mul nsw i32 %i1.0, 3
+  %add = add nsw i32 %sum.reload, %mul
+  %inc = add nsw i32 %i1.0, 1
+  store i32 %add, i32* %sum
+  %cmp = icmp slt i32 %i1.0, 100
+  br i1 %cmp, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_simple_iv_debug_wrapped_dependences.ll b/final/test/Dependences/reduction_simple_iv_debug_wrapped_dependences.ll
new file mode 100644
index 0000000..eb255d6
--- /dev/null
+++ b/final/test/Dependences/reduction_simple_iv_debug_wrapped_dependences.ll
@@ -0,0 +1,81 @@
+; RUN: opt %loadPolly -polly-dependences -analyze -debug-only=polly-dependence 2>&1 < %s | FileCheck %s
+;
+; REQUIRES: asserts
+;
+; CHECK: Read: { [Stmt_for_cond[i0] -> MemRef_sum[0]] -> MemRef_sum[0] : i0 >= 0 and i0 <= 100 }
+; CHECK: Write: { [Stmt_for_cond[i0] -> MemRef_sum[0]] -> MemRef_sum[0] : i0 >= 0 and i0 <= 100 }
+; CHECK: Schedule: { [Stmt_for_cond[i0] -> MemRef_sum[0]] -> scattering[i0] : i0 <= 100 and i0 >= 0; Stmt_for_cond[i0] -> scattering[i0] }
+; CHECK: Wrapped Dependences:
+; CHECK: RAW dependences:
+; CHECK:   { [Stmt_for_cond[i0] -> MemRef_sum[0]] -> [Stmt_for_cond[1 + i0] -> MemRef_sum[0]] : i0 >= 0 and i0 <= 99 }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   { [Stmt_for_cond[i0] -> MemRef_sum[0]] -> [Stmt_for_cond[1 + i0] -> MemRef_sum[0]] : i0 >= 0 and i0 <= 99 }
+; CHECK: Reduction dependences:
+; CHECK:   n/a
+; CHECK: Final Wrapped Dependences:
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK:   { [Stmt_for_cond[i0] -> MemRef_sum[0]] -> [Stmt_for_cond[1 + i0] -> MemRef_sum[0]] : i0 <= 99 and i0 >= 0 }
+; CHECK: Zipped Dependences:
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK:   { [Stmt_for_cond[i0] -> Stmt_for_cond[1 + i0]] -> [MemRef_sum[0] -> MemRef_sum[0]] : i0 <= 99 and i0 >= 0 }
+; CHECK: Unwrapped Dependences:
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_cond[i0] -> Stmt_for_cond[1 + i0] : i0 <= 99 and i0 >= 0 }
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK:   { Stmt_for_cond[i0] -> Stmt_for_cond[1 + i0] : i0 <= 99 and i0 >= 0 }
+;
+; void f(int* sum) {
+;   for (int i = 0; i <= 100; i++)
+;     sum += i * 3;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %entry.split1
+
+entry.split1:                                     ; preds = %entry
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry.split1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entry.split
+  %i1.0 = phi i32 [ 0, %entry.split ], [ %inc, %for.cond ]
+  %sum.reload = load i32* %sum
+  %mul = mul nsw i32 %i1.0, 3
+  %add = add nsw i32 %sum.reload, %mul
+  %inc = add nsw i32 %i1.0, 1
+  store i32 %add, i32* %sum
+  %cmp = icmp slt i32 %i1.0, 100
+  br i1 %cmp, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_simple_privatization_deps_2.ll b/final/test/Dependences/reduction_simple_privatization_deps_2.ll
new file mode 100644
index 0000000..46b32c0
--- /dev/null
+++ b/final/test/Dependences/reduction_simple_privatization_deps_2.ll
@@ -0,0 +1,79 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK:      RAW dependences:
+; CHECK-DAG:    Stmt_S1[i0, i1] -> Stmt_S2[i0] : i0 <= 99 and i0 >= 0 and i1 <= 99 and i1 >= 0
+; CHECK-DAG:    Stmt_S0[i0] -> Stmt_S1[i0, o1] : i0 <= 99 and i0 >= 0 and o1 <= 99 and o1 >= 0
+; CHECK-DAG:    Stmt_S2[i0] -> Stmt_S0[1 + i0] : i0 >= 0 and i0 <= 98
+; CHECK:      WAR dependences:
+; CHECK-DAG:     {  }
+; CHECK:      WAW dependences:
+; CHECK-DAG:    Stmt_S1[i0, i1] -> Stmt_S2[i0] : i0 <= 99 and i0 >= 0 and i1 <= 99 and i1 >= 0
+; CHECK-DAG:    Stmt_S0[i0] -> Stmt_S1[i0, o1] : i0 <= 99 and i0 >= 0 and o1 <= 99 and o1 >= 0
+; CHECK-DAG:    Stmt_S2[i0] -> Stmt_S0[1 + i0] : i0 >= 0 and i0 <= 98
+; CHECK:      Reduction dependences:
+; CHECK-DAG:    Stmt_S1[i0, i1] -> Stmt_S1[i0, 1 + i1] : i0 <= 99 and i0 >= 0 and i1 <= 98 and i1 >= 0
+;
+;    void f(int *sum) {
+;      for (int i = 0; i < 100; i++) {
+; S0:    *sum *= 42;
+;        for (int j = 0; j < 100; j++)
+; S1:      *sum += i * j;
+; S2:    *sum *= 7;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %exitcond1 = icmp ne i32 %i.0, 100
+  br i1 %exitcond1, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %tmp = load i32* %sum, align 4
+  %mul = mul nsw i32 %tmp, 42
+  store i32 %mul, i32* %sum, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %S0
+  %j.0 = phi i32 [ 0, %S0 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 100
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  br label %S1
+
+S1:                                               ; preds = %for.body3
+  %mul4 = mul nsw i32 %i.0, %j.0
+  %tmp2 = load i32* %sum, align 4
+  %add = add nsw i32 %tmp2, %mul4
+  store i32 %add, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S1
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %S2
+
+S2:                                               ; preds = %for.end
+  %tmp3 = load i32* %sum, align 4
+  %mul5 = mul nsw i32 %tmp3, 7
+  store i32 %mul5, i32* %sum, align 4
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %S2
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/reduction_simple_privatization_deps_w_parameter.ll b/final/test/Dependences/reduction_simple_privatization_deps_w_parameter.ll
new file mode 100644
index 0000000..f223619
--- /dev/null
+++ b/final/test/Dependences/reduction_simple_privatization_deps_w_parameter.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK:      RAW dependences:
+; CHECK-DAG:    Stmt_S0[] -> Stmt_S1[o0] : N >= 11 and o0 <= 1023 and o0 >= 0
+; CHECK-DAG:    Stmt_S1[i0] -> Stmt_S2[] : N >= 11 and i0 <= 1023 and i0 >= 0
+; CHECK:      WAR dependences:
+; CHECK:       [N] -> {  }
+; CHECK:      WAW dependences:
+; CHECK-DAG:    Stmt_S0[] -> Stmt_S1[o0] : N >= 11 and o0 <= 1023 and o0 >= 0
+; CHECK-DAG:    Stmt_S1[i0] -> Stmt_S2[] : N >= 11 and i0 <= 1023 and i0 >= 0
+; CHECK:   Reduction dependences:
+; CHECK:        Stmt_S1[i0] -> Stmt_S1[1 + i0] : N >= 11 and i0 <= 1022 and i0 >= 0
+;
+;    void f(int *sum, int N) {
+;      if (N >= 10) {
+; S0:    *sum = 0;
+;        for (int i = 0; i < 1024; i++)
+; S1:      *sum += i;
+; S2:    *sum = *sum * 3;
+;      }
+;    }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum, i32 %N) {
+entry:
+  br label %entry.1
+
+entry.1:
+  %excond = icmp sgt i32 %N, 10
+  br i1 %excond, label %S0, label %f.end
+
+S0:
+  store i32 0, i32* %sum, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %S0
+  %i.0 = phi i32 [ 0, %S0 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %S1, label %S2
+
+S1:                                               ; preds = %for.cond
+  %tmp = load i32* %sum, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S1
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+S2:                                               ; preds = %for.cond
+  %tmp1 = load i32* %sum, align 4
+  %mul = mul nsw i32 %tmp1, 3
+  store i32 %mul, i32* %sum, align 4
+  br label %f.end
+
+f.end:
+  ret void
+}
diff --git a/final/test/Dependences/reduction_two_reductions_different_rloops.ll b/final/test/Dependences/reduction_two_reductions_different_rloops.ll
new file mode 100644
index 0000000..4470e4e
--- /dev/null
+++ b/final/test/Dependences/reduction_two_reductions_different_rloops.ll
@@ -0,0 +1,73 @@
+; RUN: opt %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s
+;
+; CHECK: RAW dependences:
+; CHECK:   {  }
+; CHECK: WAR dependences:
+; CHECK:   {  }
+; CHECK: WAW dependences:
+; CHECK:   {  }
+; CHECK: Reduction dependences:
+; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0
+; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[1 + i0, i1] : i0 <= 1022 and i0 >= 0 and i1 <= 1023 and i1 >= 0
+;
+; void f(int *restrict A, int *restrict B, int *restrict Values) {
+;   for (int i = 0; i < 1024; i++) {
+;     for (int j = 0; j < 1024; j++) {
+;       A[i] += Values[i + j - 1];
+;       B[j] += Values[i + j + 42];
+;     }
+;   }
+; }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %B, i32* noalias %Values)  {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc11, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc12, %for.inc11 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end13
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %add = add nsw i32 %i.0, %j.0
+  %sub = add nsw i32 %add, -1
+  %arrayidx = getelementptr inbounds i32* %Values, i32 %sub
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx4 = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp2 = load i32* %arrayidx4, align 4
+  %add5 = add nsw i32 %tmp2, %tmp
+  store i32 %add5, i32* %arrayidx4, align 4
+  %add6 = add nsw i32 %i.0, %j.0
+  %add7 = add nsw i32 %add6, 42
+  %arrayidx8 = getelementptr inbounds i32* %Values, i32 %add7
+  %tmp3 = load i32* %arrayidx8, align 4
+  %arrayidx9 = getelementptr inbounds i32* %B, i32 %j.0
+  %tmp4 = load i32* %arrayidx9, align 4
+  %add10 = add nsw i32 %tmp4, %tmp3
+  store i32 %add10, i32* %arrayidx9, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.end
+  %inc12 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end13:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Dependences/sequential_loops.ll b/final/test/Dependences/sequential_loops.ll
new file mode 100644
index 0000000..772eb48
--- /dev/null
+++ b/final/test/Dependences/sequential_loops.ll
@@ -0,0 +1,296 @@
+; RUN: opt -S %loadPolly -basicaa -polly-dependences -analyze -polly-dependences-analysis-type=value-based < %s | FileCheck %s -check-prefix=VALUE
+; RUN: opt -S %loadPolly -basicaa -polly-dependences -analyze -polly-dependences-analysis-type=memory-based < %s | FileCheck %s -check-prefix=MEMORY
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+;     for(i = 0; i < 100; i++ )
+; S1:   A[i] = 2;
+;
+;     for (i = 0; i < 10; i++ )
+; S2:   A[i]  = 5;
+;
+;     for (i = 0; i < 200; i++ )
+; S3:   A[i] = 5;
+
+define void @sequential_writes() {
+entry:
+  %A = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  br label %S3
+
+S3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  store i32 7, i32* %arrayidx.3
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %S3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; VALUE: region: 'S1 => exit.3' in function 'sequential_writes':
+; VALUE:   RAW dependences:
+; VALUE:     {  }
+; VALUE:   WAR dependences:
+; VALUE:     {  }
+; VALUE:   WAW dependences:
+; VALUE:     {
+; VALUE:       Stmt_S1[i0] -> Stmt_S2[i0] : i0 >= 0 and i0 <= 9;
+; VALUE:       Stmt_S2[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 9;
+; VALUE:       Stmt_S1[i0] -> Stmt_S3[i0] : i0 >= 10 and i0 <= 99
+; VALUE:     }
+
+; MEMORY: region: 'S1 => exit.3' in function 'sequential_writes':
+; MEMORY:   RAW dependences:
+; MEMORY:     {  }
+; MEMORY:   WAR dependences:
+; MEMORY:     {  }
+; MEMORY:   WAW dependences:
+; MEMORY:     {
+; MEMORY:       Stmt_S1[i0] -> Stmt_S2[i0] : i0 <= 9 and i0 >= 0;
+; MEMORY:       Stmt_S2[i0] -> Stmt_S3[i0] : i0 <= 9 and i0 >= 0;
+; MEMORY:       Stmt_S1[i0] -> Stmt_S3[i0] : i0 <= 99 and i0 >= 0
+; MEMORY:     }
+
+;     for(i = 0; i < 100; i++ )
+; S1:   A[i] = 2;
+;
+;     for (i = 0; i < 10; i++ )
+; S2:   A[i]  = 5;
+;
+;     for (i = 0; i < 200; i++ )
+; S3:   B[i] = A[i];
+
+define void @read_after_writes() {
+entry:
+  %A = alloca [200 x i32]
+  %B = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  br label %S3
+
+S3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
+  %arrayidx.3.a = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  %arrayidx.3.b = getelementptr [200 x i32]* %B, i64 0, i64 %indvar.3
+  %val = load i32* %arrayidx.3.a
+  store i32 %val, i32* %arrayidx.3.b
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %S3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; VALUE: region: 'S1 => exit.3' in function 'read_after_writes':
+; VALUE:   RAW dependences:
+; VALUE:     {
+; VALUE:       Stmt_S2[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 9;
+; VALUE:       Stmt_S1[i0] -> Stmt_S3[i0] : i0 >= 10 and i0 <= 99
+; VALUE:     }
+; VALUE:   WAR dependences:
+; VALUE:     {  }
+; VALUE:   WAW dependences:
+; VALUE:     {
+; VALUE:       Stmt_S1[i0] -> Stmt_S2[i0] : i0 >= 0 and i0 <= 9
+; VALUE:     }
+
+; MEMORY: region: 'S1 => exit.3' in function 'read_after_writes':
+; MEMORY:   RAW dependences:
+; MEMORY:     {
+; MEMORY:       Stmt_S2[i0] -> Stmt_S3[i0] : i0 <= 9 and i0 >= 0;
+; MEMORY:       Stmt_S1[i0] -> Stmt_S3[i0] : i0 <= 99 and i0 >= 0
+; MEMORY:     }
+; MEMORY:   WAR dependences:
+; MEMORY:     {  }
+; MEMORY:   WAW dependences:
+; MEMORY:     {
+; MEMORY:       Stmt_S1[i0] -> Stmt_S2[i0] : i0 <= 9 and i0 >= 0
+; MEMORY:     }
+
+;     for(i = 0; i < 100; i++ )
+; S1:   B[i] = A[i];
+;
+;     for (i = 0; i < 10; i++ )
+; S2:   A[i]  = 5;
+;
+;     for (i = 0; i < 200; i++ )
+; S3:   A[i]  = 10;
+
+define void @write_after_read() {
+entry:
+  %A = alloca [200 x i32]
+  %B = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1.a = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  %arrayidx.1.b = getelementptr [200 x i32]* %B, i64 0, i64 %indvar.1
+  %val = load i32* %arrayidx.1.a
+  store i32 %val, i32* %arrayidx.1.b
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  br label %S3
+
+S3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  store i32 10, i32* %arrayidx.3
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %S3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+; VALUE: region: 'S1 => exit.3' in function 'write_after_read':
+; VALUE:   RAW dependences:
+; VALUE:     {
+; VALUE:     }
+; VALUE:   WAR dependences:
+; VALUE:     {
+; VALUE:       Stmt_S1[i0] -> Stmt_S2[i0] : i0 <= 9 and i0 >= 0;
+; VALUE:       Stmt_S1[i0] -> Stmt_S3[i0] : i0 <= 99 and i0 >= 10
+; VALUE:     }
+; VALUE:   WAW dependences:
+; VALUE:     {
+; VALUE:       Stmt_S2[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 9
+; VALUE:     }
+
+; MEMORY: region: 'S1 => exit.3' in function 'write_after_read':
+; MEMORY:   RAW dependences:
+; MEMORY:     {
+; MEMORY:     }
+; MEMORY:   WAR dependences:
+; MEMORY:     {
+; MEMORY:        Stmt_S1[i0] -> Stmt_S2[i0] : i0 <= 9 and i0 >= 0;
+; MEMORY:        Stmt_S1[i0] -> Stmt_S3[i0] : i0 <= 99 and i0 >= 0
+; MEMORY:     }
+; MEMORY:   WAW dependences:
+; MEMORY:     {
+; MEMORY:        Stmt_S2[i0] -> Stmt_S3[i0] : i0 <= 9 and i0 >= 0
+; MEMORY:     }
+
+;     for(i = 0; i < 100; i++ )
+; S1:   A[i] = 10
+;
+;     for(i = 0; i < 100; i++ )
+; S2:   B[i] = A[i + p];
+
+define void @parametric_offset(i64 %p) {
+entry:
+  %A = alloca [200 x i32]
+  %B = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 10, i32* %arrayidx.1
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %sum = add i64 %indvar.2, %p
+  %arrayidx.2.a = getelementptr [200 x i32]* %A, i64 0, i64 %sum
+  %arrayidx.2.b = getelementptr [200 x i32]* %B, i64 0, i64 %indvar.2
+  %val = load i32* %arrayidx.2.a
+  store i32 %val, i32* %arrayidx.2.b
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  ret void
+}
+
+; VALUE: region: 'S1 => exit.2' in function 'parametric_offset':
+; VALUE:   RAW dependences:
+; VALUE:     [p] -> {
+; VALUE:       Stmt_S1[i0] -> Stmt_S2[-p + i0] :
+; VALUE:           i0 >= p and i0 <= 9 + p and p <= 190 and i0 <= 99 and i0 >= 0
+; VALUE:     }
+; VALUE:   WAR dependences:
+; VALUE:     [p] -> {
+; VALUE:     }
+; VALUE:   WAW dependences:
+; VALUE:     [p] -> {
+; VALUE:     }
+
+; MEMORY: region: 'S1 => exit.2' in function 'parametric_offset':
+; MEMORY:   RAW dependences:
+; MEMORY:     [p] -> {
+; MEMORY:       Stmt_S1[i0] -> Stmt_S2[-p + i0] :
+; MEMORY:           i0 >= p and i0 <= 99 and i0 >= 0 and i0 <= 9 + p
+; MEMORY:     }
+; MEMORY:   WAR dependences:
+; MEMORY:     [p] -> {
+; MEMORY:     }
+; MEMORY:   WAW dependences:
+; MEMORY:     [p] -> {
+; MEMORY:     }
diff --git a/final/test/IndependentBlocks/inter_bb_scalar_dep.ll b/final/test/IndependentBlocks/inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..376fe5e
--- /dev/null
+++ b/final/test/IndependentBlocks/inter_bb_scalar_dep.ll
@@ -0,0 +1,58 @@
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s -check-prefix=SCALARACCESS
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s -check-prefix=SCALARACCESS
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     for (i = 0; i < N; ++i) {
+;       A[i] = init + 2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+
+; CHECK: entry
+; CHECK: %init.s2a = alloca i64
+; CHECK: br label %for.i
+
+; SCALARACCESS-NOT: alloca
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+  %init = load i64* %init_ptr
+; SCALARACCESS-NOT: store
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init_plus_two = add i64 %init, 2
+; CHECK: %init.loadarray = load i64* %init.s2a
+; CHECK: %init_plus_two = add i64 %init.loadarray, 2
+; SCALARACCESS: %init_plus_two = add i64 %init, 2
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_plus_two, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
diff --git a/final/test/IndependentBlocks/intra_and_inter_bb_scalar_dep.ll b/final/test/IndependentBlocks/intra_and_inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..9f080fa
--- /dev/null
+++ b/final/test/IndependentBlocks/intra_and_inter_bb_scalar_dep.ll
@@ -0,0 +1,67 @@
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s -check-prefix=SCALARACCESS
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s -check-prefix=SCALARACCESS
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     for (i = 0; i < N; ++i) {
+;       init2 = *init_ptr;
+;       A[i] = init + init2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+
+; CHECK: entry
+; CHECK: %init.s2a = alloca i64
+; CHECK: br label %for.i
+
+; SCALARACCESS-NOT: alloca
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+  %init = load i64* %init_ptr
+; SCALARACCESS-NOT: store
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init_2 = load i64* %init_ptr
+  %init_sum = add i64 %init, %init_2
+; CHECK: %init_2 = load i64* %init_ptr
+; CHECK: %init.loadarray = load i64* %init.s2a
+; CHECK: %init_sum = add i64 %init.loadarray, %init_2
+
+; The SCEV of %init_sum is (%init + %init_2). It is referring to both an
+; UnknownValue in the same and in a different basic block. We want only the
+; reference to the different basic block to be replaced.
+
+; SCALARACCESS: %init_2 = load i64* %init_ptr
+; SCALARACCESS: %init_sum = add i64 %init, %init_2
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_sum, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
diff --git a/final/test/IndependentBlocks/intra_bb_scalar_dep.ll b/final/test/IndependentBlocks/intra_bb_scalar_dep.ll
new file mode 100644
index 0000000..f167a89
--- /dev/null
+++ b/final/test/IndependentBlocks/intra_bb_scalar_dep.ll
@@ -0,0 +1,54 @@
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     for (i = 0; i < N; ++i) {
+;       init = *init_ptr;
+;       A[i] = init + 2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+
+; CHECK: entry
+; CHECK: br label %for.i
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init = load i64* %init_ptr
+  %init_plus_two = add i64 %init, 2
+; The scalar evolution of %init_plus_two is (2 + %init). So we have a
+; non-trivial scalar evolution referring to a value in the same basic block.
+; We want to ensure that this scalar is not translated into a memory copy.
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_plus_two, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
diff --git a/final/test/IndependentBlocks/phi_outside_scop.ll b/final/test/IndependentBlocks/phi_outside_scop.ll
new file mode 100644
index 0000000..f56b087
--- /dev/null
+++ b/final/test/IndependentBlocks/phi_outside_scop.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @phi_nodes_outside() {
+entry:
+  br label %for.i.1
+
+for.i.1:
+  %i.1 = phi i32 [ %i.1.next, %for.i.1 ], [ 0, %entry ]
+  %i.1.next = add nsw i32 %i.1, 1
+  br i1 false, label %for.i.1 , label %for.i.2.preheader
+
+for.i.2.preheader:
+  br label %for.i.2
+
+for.i.2:
+; The value of %i.1.next is used outside of the scop in a PHI node.
+  %i.2 = phi i32 [ %i.2.next , %for.i.2 ], [ %i.1.next, %for.i.2.preheader ]
+  %i.2.next = add nsw i32 %i.2, 1
+  fence seq_cst
+  br i1 false, label %for.i.2, label %cleanup
+
+cleanup:
+  ret void
+}
+
+; CHECK:  store i32 %i.1.next, i32* %i.1.next.s2a
+
+; CHECK: for.i.2.preheader:
+; CHECK:    %i.1.next.loadoutside = load i32* %i.1.next.s2a
+
+; CHECK: for.i.2:
+; CHECK:    %i.2 = phi i32 [ %i.2.next, %for.i.2 ], [ %i.1.next.loadoutside, %for.i.2.preheader ]
+
diff --git a/final/test/IndependentBlocks/scalar_to_array.ll b/final/test/IndependentBlocks/scalar_to_array.ll
new file mode 100644
index 0000000..8358a87
--- /dev/null
+++ b/final/test/IndependentBlocks/scalar_to_array.ll
@@ -0,0 +1,270 @@
+; RUN: opt %loadPolly -basicaa -polly-independent < %s -S | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent < %s -S | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array -S < %s | FileCheck %s -check-prefix=SCALARACCESS
+; RUN: opt %loadPolly -basicaa -polly-independent -disable-polly-intra-scop-scalar-to-array < %s -S | FileCheck %s -check-prefix=SCALARACCESS
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 8
+
+define i32 @empty() nounwind {
+entry:
+  fence seq_cst
+  br label %for.cond
+
+for.cond:
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:
+  br label %for.inc
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:
+  fence seq_cst
+  ret i32 0
+}
+
+
+; CHECK: @array_access()
+define i32 @array_access() nounwind {
+entry:
+  fence seq_cst
+  br label %for.cond
+; CHECK: entry:
+; CHECK-NOT: alloca
+; SCALARACCESS: entry:
+; SCALARACCESS-NOT: alloca
+
+for.cond:
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %float = uitofp i64 %indvar to float
+  store float %float, float* %arrayidx
+  br label %for.inc
+
+; CHECK: for.body:
+; CHECK: %float = uitofp i64 %indvar to float
+; CHECK: store float %float, float* %arrayidx
+; SCALARACCESS: for.body:
+; SCALARACCESS: %float = uitofp i64 %indvar to float
+; SCALARACCESS: store float %float, float* %arrayidx
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:
+  fence seq_cst
+  ret i32 0
+}
+
+; CHECK: @intra_scop_dep()
+define i32 @intra_scop_dep() nounwind {
+entry:
+  fence seq_cst
+  br label %for.cond
+
+; CHECK: entry:
+; CHECK: %scalar.s2a = alloca float
+; CHECK: fence
+; SCALARACCESS: entry:
+; SCALARACCESS-NOT: alloca
+; SCALARACCESS: fence
+
+for.cond:
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body.a, label %return
+
+for.body.a:
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %scalar = load float* %arrayidx
+  br label %for.body.b
+
+; CHECK: for.body.a:
+; CHECK: %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+; CHECK: %scalar = load float* %arrayidx
+; CHECK: store float %scalar, float* %scalar.s2a
+; CHECK: br label %for.body.b
+
+; SCALARACCESS: for.body.a:
+; SCALARACCESS: %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+; SCALARACCESS: %scalar = load float* %arrayidx
+; SCALARACCESS-NOT: store
+; SCALARACCESS: br label %for.body.b
+
+for.body.b:
+  %arrayidx2 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %float = uitofp i64 %indvar to float
+  %sum = fadd float %scalar, %float
+  store float %sum, float* %arrayidx2
+  br label %for.inc
+
+; CHECK: for.body.b:
+; CHECK: %arrayidx2 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+; CHECK: %float = uitofp i64 %indvar to float
+; CHECK: %scalar.loadarray = load float* %scalar.s2a
+; CHECK: %sum = fadd float %scalar.loadarray, %float
+; CHECK: store float %sum, float* %arrayidx2
+; CHECK: br label %for.inc
+
+; SCALARACCESS: for.body.b:
+; SCALARACCESS: %arrayidx2 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+; SCALARACCESS: %float = uitofp i64 %indvar to float
+; SCALARACCESS-NOT: load
+; SCALARACCESS: %sum = fadd float %scalar, %float
+; SCALARACCESS: store float %sum, float* %arrayidx2
+; SCALARACCESS: br label %for.inc
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:
+  fence seq_cst
+  ret i32 0
+}
+
+; It is not possible to have a scop which accesses a scalar element that is
+; a global variable. All global variables are pointers containing possibly
+; a single element. Hence they do not need to be handled anyways.
+; Please note that this is still required when scalar to array rewritting is
+; disabled.
+
+; CHECK: @use_after_scop()
+define i32 @use_after_scop() nounwind {
+entry:
+  fence seq_cst
+  br label %for.head
+; CHECK: entry:
+; CHECK: %scalar.s2a = alloca float
+; CHECK: fence
+
+; SCALARACCESS: entry:
+; SCALARACCESS: %scalar.s2a = alloca float
+; SCALARACCESS: fence
+
+for.head:
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  br label %for.body
+
+for.body:
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %scalar = load float* %arrayidx
+  br label %for.inc
+
+; CHECK: for.body:
+; CHECK: %scalar = load float* %arrayidx
+; CHECK: store float %scalar, float* %scalar.s2a
+
+; SCALARACCESS: for.body:
+; SCALARACCESS: %scalar = load float* %arrayidx
+; SCALARACCESS: store float %scalar, float* %scalar.s2a
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.head, label %for.after
+
+for.after:
+  fence seq_cst
+  %return_value = fptosi float %scalar to i32
+  br label %return
+
+; CHECK: for.after:
+; CHECK: %scalar.loadoutside = load float* %scalar.s2a
+; CHECK: fence seq_cst
+; CHECK: %return_value = fptosi float %scalar.loadoutside to i32
+
+; SCALARACCESS: for.after:
+; SCALARACCESS: %scalar.loadoutside = load float* %scalar.s2a
+; SCALARACCESS: fence seq_cst
+; SCALARACCESS: %return_value = fptosi float %scalar.loadoutside to i32
+
+return:
+  ret i32 %return_value
+}
+
+; We currently do not transform scalar references, that have only read accesses
+; in the scop. There are two reasons for this:
+;
+;  o We don't introduce additional memory references which may yield to compile
+;    time overhead.
+;  o For integer values, such a translation may block the use of scalar
+;    evolution on those values.
+;
+; CHECK: @before_scop()
+define i32 @before_scop() nounwind {
+entry:
+  br label %preheader
+
+preheader:
+  %scalar = fadd float 4.0, 5.0
+  fence seq_cst
+  br label %for.cond
+
+for.cond:
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %preheader ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  store float %scalar, float* %arrayidx
+  br label %for.inc
+
+; CHECK: for.body:
+; CHECK: store float %scalar, float* %arrayidx
+
+; SCALARACCESS: for.body:
+; SCALARACCESS: store float %scalar, float* %arrayidx
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:
+  fence seq_cst
+  ret i32 0
+}
+
+; Currently not working
+; CHECK: @param_before_scop(
+define i32 @param_before_scop(float %scalar) nounwind {
+entry:
+  fence seq_cst
+  br label %for.cond
+; CHECK: entry:
+; CHECK: fence
+
+for.cond:
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  store float %scalar, float* %arrayidx
+  br label %for.inc
+
+; CHECK: for.body:
+; CHECK: store float %scalar, float* %arrayidx
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:
+  fence seq_cst
+  ret i32 0
+}
diff --git a/final/test/IndependentBlocks/scev-invalidated.ll b/final/test/IndependentBlocks/scev-invalidated.ll
new file mode 100644
index 0000000..0a95c87
--- /dev/null
+++ b/final/test/IndependentBlocks/scev-invalidated.ll
@@ -0,0 +1,22 @@
+; RUN: opt %loadPolly -polly-independent < %s
+target datalayout ="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @arc_either() {
+entry:
+  %ang2.2.reg2mem = alloca i64
+  br i1 undef, label %return, label %if.then6
+
+if.then6:
+  %rem7 = srem i64 undef, 1474560
+  br i1 false, label %if.else, label %return
+
+if.else:
+  %add16 = add nsw i64 %rem7, 1474560
+  %rem7.add16 = select i1 undef, i64 %rem7, i64 %add16
+  store i64 %rem7.add16, i64* %ang2.2.reg2mem
+  br label %return
+
+return:
+  ret void
+}
diff --git a/final/test/Isl/Ast/OpenMP/multiple_loops_outer_parallel.ll b/final/test/Isl/Ast/OpenMP/multiple_loops_outer_parallel.ll
new file mode 100644
index 0000000..f7cea3d
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/multiple_loops_outer_parallel.ll
@@ -0,0 +1,54 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -polly-parallel-force -analyze < %s | FileCheck %s
+;
+;       void jd(int *A) {
+; CHECK:  #pragma omp parallel for
+;         for (int i = 0; i < 1024; i++)
+;           A[i] = 1;
+; CHECK:  #pragma omp parallel for
+;         for (int i = 0; i < 1024; i++)
+;           A[i] = A[i] * 2;
+;       }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv1 = phi i64 [ %indvars.iv.next2, %for.inc ], [ 0, %entry ]
+  %exitcond3 = icmp ne i64 %indvars.iv1, 1024
+  br i1 %exitcond3, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv1
+  store i32 1, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next2 = add nuw nsw i64 %indvars.iv1, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc9, %for.end
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc9 ], [ 0, %for.end ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body4, label %for.end11
+
+for.body4:                                        ; preds = %for.cond2
+  %arrayidx6 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  %tmp = load i32* %arrayidx6, align 4
+  %mul = shl nsw i32 %tmp, 1
+  %arrayidx8 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %mul, i32* %arrayidx8, align 4
+  br label %for.inc9
+
+for.inc9:                                         ; preds = %for.body4
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond2
+
+for.end11:                                        ; preds = %for.cond2
+  ret void
+}
diff --git a/final/test/Isl/Ast/OpenMP/nested_loop_both_parallel.ll b/final/test/Isl/Ast/OpenMP/nested_loop_both_parallel.ll
new file mode 100644
index 0000000..08cfe0d
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/nested_loop_both_parallel.ll
@@ -0,0 +1,52 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; for (i = 0; i < 1024; i++)
+;   for (j = 0; j < 1024; j++)
+;     A[i][j] = 1;
+
+@A = common global [1024 x [1024 x i32]] zeroinitializer
+define void @bar() {
+start:
+  fence seq_cst
+  br label %loop.i
+
+loop.i:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.i.backedge ]
+  %exitcond.i = icmp ne i64 %i, 1024
+  br i1 %exitcond.i, label %loop.j, label %ret
+
+loop.j:
+  %j = phi i64 [ 0, %loop.i], [ %j.next, %loop.j.backedge ]
+  %exitcond.j = icmp ne i64 %j, 1024
+  br i1 %exitcond.j, label %loop.body, label %loop.i.backedge
+
+loop.body:
+  %scevgep = getelementptr [1024 x [1024 x i32] ]* @A, i64 0, i64 %j, i64 %i
+  store i32 1, i32* %scevgep
+  br label %loop.j.backedge
+
+loop.j.backedge:
+  %j.next = add nsw i64 %j, 1
+  br label %loop.j
+
+loop.i.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.i
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; Make sure we do not accidentally generate nested openmp parallel for
+; annotations.
+
+; CHECK:     #pragma omp parallel for
+; CHECK:     for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK-NOT:   #pragma omp parallel for
+; CHECK:       #pragma simd
+; CHECK-NOT:   #pragma omp parallel for
+; CHECK:       for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:         Stmt_loop_body(c0, c1);
diff --git a/final/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll b/final/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll
new file mode 100644
index 0000000..9bb8f24
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll
@@ -0,0 +1,49 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -polly-parallel-force -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+; int A[1024][1024];
+; void bar(int n) {
+;   for (i = 0; i < n; i++)
+;     for (j = 0; j < n; j++)
+;       A[i][j] = 1;
+; }
+@A = common global [1024 x [1024 x i32]] zeroinitializer
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.i
+
+loop.i:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.i.backedge ]
+  %exitcond.i = icmp ne i64 %i, %n
+  br i1 %exitcond.i, label %loop.j, label %ret
+
+loop.j:
+  %j = phi i64 [ 0, %loop.i], [ %j.next, %loop.j.backedge ]
+  %exitcond.j = icmp ne i64 %j, %n
+  br i1 %exitcond.j, label %loop.body, label %loop.i.backedge
+
+loop.body:
+  %scevgep = getelementptr [1024 x [1024 x i32] ]* @A, i64 0, i64 %j, i64 %i
+  store i32 1, i32* %scevgep
+  br label %loop.j.backedge
+
+loop.j.backedge:
+  %j.next = add nsw i64 %j, 1
+  br label %loop.j
+
+loop.i.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.i
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: if (n <= 1024 ? 1 : 0)
+; CHECK:   #pragma omp parallel for
+; CHECK:   for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:     #pragma simd
+; CHECK:     for (int c1 = 0; c1 < n; c1 += 1)
+; CHECK:       Stmt_loop_body(c0, c1);
diff --git a/final/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll b/final/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll
new file mode 100644
index 0000000..6626a5c
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll
@@ -0,0 +1,47 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -polly-parallel-force -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; for (i = 0; i < n; i++)
+;   for (j = 0; j < n; j++)
+;     A[j] = 1;
+
+@A = common global [1024 x i32] zeroinitializer
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.i
+
+loop.i:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.i.backedge ]
+  %exitcond.i = icmp ne i64 %i, %n
+  br i1 %exitcond.i, label %loop.j, label %ret
+
+loop.j:
+  %j = phi i64 [ 0, %loop.i], [ %j.next, %loop.j.backedge ]
+  %exitcond.j = icmp ne i64 %j, %n
+  br i1 %exitcond.j, label %loop.body, label %loop.i.backedge
+
+loop.body:
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %j
+  store i32 1, i32* %scevgep
+  br label %loop.j.backedge
+
+loop.j.backedge:
+  %j.next = add nsw i64 %j, 1
+  br label %loop.j
+
+loop.i.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.i
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   #pragma simd
+; CHECK:   #pragma omp parallel for
+; CHECK:   for (int c1 = 0; c1 < n; c1 += 1)
+; CHECK:     Stmt_loop_body(c0, c1);
diff --git a/final/test/Isl/Ast/OpenMP/nested_loop_outer_parallel.ll b/final/test/Isl/Ast/OpenMP/nested_loop_outer_parallel.ll
new file mode 100644
index 0000000..b8ca8ff
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/nested_loop_outer_parallel.ll
@@ -0,0 +1,46 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; for (i = 0; i < n; i++)
+;   for (j = 0; j < n; j++)
+;     A[i] = 1;
+
+@A = common global [1024 x i32] zeroinitializer
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.i
+
+loop.i:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.i.backedge ]
+  %exitcond.i = icmp ne i64 %i, %n
+  br i1 %exitcond.i, label %loop.j, label %ret
+
+loop.j:
+  %j = phi i64 [ 0, %loop.i], [ %j.next, %loop.j.backedge ]
+  %exitcond.j = icmp ne i64 %j, %n
+  br i1 %exitcond.j, label %loop.body, label %loop.i.backedge
+
+loop.body:
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i
+  store i32 1, i32* %scevgep
+  br label %loop.j.backedge
+
+loop.j.backedge:
+  %j.next = add nsw i64 %j, 1
+  br label %loop.j
+
+loop.i.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.i
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: #pragma omp parallel for
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   for (int c1 = 0; c1 < n; c1 += 1)
+; CHECK:     Stmt_loop_body(c0, c1);
diff --git a/final/test/Isl/Ast/OpenMP/single_loop_param_non_parallel.ll b/final/test/Isl/Ast/OpenMP/single_loop_param_non_parallel.ll
new file mode 100644
index 0000000..1b6dd62
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/single_loop_param_non_parallel.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; for (i = 0; i < n; i++)
+;   A[0] = i;
+
+@A = common global [1024 x i32] zeroinitializer
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 0
+  %exitcond = icmp ne i64 %i, %n
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  store i32 1, i32* %scevgep
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   Stmt_loop_body(c0)
diff --git a/final/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll b/final/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll
new file mode 100644
index 0000000..1480579
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -polly-parallel-force -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; for (i = 0; i < n; i++)
+;   A[i] = 1;
+
+@A = common global [1024 x i32] zeroinitializer
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i
+  %exitcond = icmp ne i64 %i, %n
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  store i32 1, i32* %scevgep
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: #pragma simd
+; CHECK: #pragma omp parallel for
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   Stmt_loop_body(c0)
diff --git a/final/test/Isl/Ast/OpenMP/single_loop_param_parallel_computeout.ll b/final/test/Isl/Ast/OpenMP/single_loop_param_parallel_computeout.ll
new file mode 100644
index 0000000..29a0bc4
--- /dev/null
+++ b/final/test/Isl/Ast/OpenMP/single_loop_param_parallel_computeout.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-ast -polly-parallel -polly-dependences-computeout=1 -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; for (i = 0; i < n; i++)
+;   A[i] = 1;
+
+@A = common global [1024 x i32] zeroinitializer
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i
+  %exitcond = icmp ne i64 %i, %n
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  store i32 1, i32* %scevgep
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK-NOT: #pragma simd
+; CHECK-NOT: #pragma omp parallel for
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   Stmt_loop_body(c0)
diff --git a/final/test/Isl/Ast/alias_simple_1.ll b/final/test/Isl/Ast/alias_simple_1.ll
new file mode 100644
index 0000000..d66a896
--- /dev/null
+++ b/final/test/Isl/Ast/alias_simple_1.ll
@@ -0,0 +1,58 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze < %s | FileCheck %s --check-prefix=NOAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -basicaa < %s | FileCheck %s --check-prefix=BASI
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -tbaa < %s | FileCheck %s --check-prefix=TBAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -scev-aa < %s | FileCheck %s --check-prefix=SCEV
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -globalsmodref-aa < %s | FileCheck %s --check-prefix=GLOB
+;
+;    int A[1024];
+;
+;
+;    void jd(float *B, int N) {
+;      for (int i = 0; i < N; i++)
+;        A[i] = B[i];
+;    }
+;
+; NOAA: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; BASI: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; TBAA: if (N <= 1024 ? 1 : 0)
+; SCEV: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; GLOB: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+@A = common global [1024 x i32] zeroinitializer, align 16
+
+define void @jd(float* nocapture readonly %B, i32 %N) {
+entry:
+  %cmp6 = icmp sgt i32 %N, 0
+  br i1 %cmp6, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]
+  %arrayidx = getelementptr inbounds float* %B, i64 %indvars.iv
+  %tmp = load float* %arrayidx, align 4, !tbaa !1
+  %conv = fptosi float %tmp to i32
+  %arrayidx2 = getelementptr inbounds [1024 x i32]* @A, i64 0, i64 %indvars.iv
+  store i32 %conv, i32* %arrayidx2, align 4, !tbaa !5
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %lftr.wideiv1 = trunc i64 %indvars.iv.next to i32
+  %exitcond2 = icmp eq i32 %lftr.wideiv1, %N
+  br i1 %exitcond2, label %for.end.loopexit, label %for.body
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void
+}
+
+!0 = !{!""}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"float", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !3, i64 0}
diff --git a/final/test/Isl/Ast/alias_simple_2.ll b/final/test/Isl/Ast/alias_simple_2.ll
new file mode 100644
index 0000000..3c4f513
--- /dev/null
+++ b/final/test/Isl/Ast/alias_simple_2.ll
@@ -0,0 +1,58 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze < %s | FileCheck %s --check-prefix=NOAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -basicaa < %s | FileCheck %s --check-prefix=BASI
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -tbaa < %s | FileCheck %s --check-prefix=TBAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -scev-aa < %s | FileCheck %s --check-prefix=SCEV
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -globalsmodref-aa < %s | FileCheck %s --check-prefix=GLOB
+;
+;    int A[1024], B[1024];
+;
+;
+;    void jd(int N) {
+;      for (int i = 0; i < N; i++)
+;        A[i] = B[i];
+;    }
+;
+; NOAA: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; BASI: if (N <= 1024 ? 1 : 0)
+; TBAA: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; SCEV: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; GLOB: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+@A = common global [1024 x i32] zeroinitializer, align 16
+@B = common global [1024 x i32] zeroinitializer, align 16
+
+define void @jd(i32 %N) {
+entry:
+  %cmp6 = icmp sgt i32 %N, 0
+  br i1 %cmp6, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]
+  %arrayidx = getelementptr inbounds  [1024 x i32]* @B, i64 0, i64 %indvars.iv
+  %tmp = load i32* %arrayidx, align 4, !tbaa !5
+  %arrayidx2 = getelementptr inbounds [1024 x i32]* @A, i64 0, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4, !tbaa !5
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %lftr.wideiv1 = trunc i64 %indvars.iv.next to i32
+  %exitcond2 = icmp eq i32 %lftr.wideiv1, %N
+  br i1 %exitcond2, label %for.end.loopexit, label %for.body
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void
+}
+
+!0 = !{!""}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"float", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !3, i64 0}
diff --git a/final/test/Isl/Ast/alias_simple_3.ll b/final/test/Isl/Ast/alias_simple_3.ll
new file mode 100644
index 0000000..10ff3f0
--- /dev/null
+++ b/final/test/Isl/Ast/alias_simple_3.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze < %s | FileCheck %s --check-prefix=NOAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -basicaa < %s | FileCheck %s --check-prefix=BASI
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -tbaa < %s | FileCheck %s --check-prefix=TBAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -scev-aa < %s | FileCheck %s --check-prefix=SCEV
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -globalsmodref-aa < %s | FileCheck %s --check-prefix=GLOB
+;
+;    int A[1024];
+;    float B[1024];
+;
+;    void jd(int N) {
+;      for (int i = 0; i < N; i++)
+;        A[i] = B[i];
+;    }
+;
+; NOAA: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; BASI: if (N <= 1024 ? 1 : 0)
+; TBAA: if (N <= 1024 ? 1 : 0)
+; SCEV: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+; GLOB: if ((N <= 1024 ? 1 : 0) && (&MemRef_A[N] <= &MemRef_B[0] || &MemRef_B[N] <= &MemRef_A[0]))
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+@A = common global [1024 x i32] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+define void @jd(i32 %N) {
+entry:
+  %cmp6 = icmp sgt i32 %N, 0
+  br i1 %cmp6, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]
+  %arrayidx = getelementptr inbounds  [1024 x float]* @B, i64 0, i64 %indvars.iv
+  %tmp = load float* %arrayidx, align 4, !tbaa !1
+  %conv = fptosi float %tmp to i32
+  %arrayidx2 = getelementptr inbounds [1024 x i32]* @A, i64 0, i64 %indvars.iv
+  store i32 %conv, i32* %arrayidx2, align 4, !tbaa !5
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %lftr.wideiv1 = trunc i64 %indvars.iv.next to i32
+  %exitcond2 = icmp eq i32 %lftr.wideiv1, %N
+  br i1 %exitcond2, label %for.end.loopexit, label %for.body
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void
+}
+
+!0 = !{!""}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"float", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !3, i64 0}
diff --git a/final/test/Isl/Ast/aliasing_multiple_alias_groups.ll b/final/test/Isl/Ast/aliasing_multiple_alias_groups.ll
new file mode 100644
index 0000000..a54a9cd
--- /dev/null
+++ b/final/test/Isl/Ast/aliasing_multiple_alias_groups.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze          < %s | FileCheck %s --check-prefix=NOAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze -tbaa    < %s | FileCheck %s --check-prefix=TBAA
+;
+;    void jd(int *Int0, int *Int1, float *Float0, float *Float1) {
+;      for (int i = 0; i < 1024; i++) {
+;        Int0[i] = Int1[i];
+;        Float0[i] = Float1[i];
+;      }
+;    }
+;
+; NOAA:      if (1 && (
+; NOAA-DAG:    &MemRef_Float0[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Float0[0]
+; NOAA-DAG:    &MemRef_Float1[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Float1[0]
+; NOAA-DAG:    &MemRef_Int1[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Int1[0]
+; NOAA-DAG:    &MemRef_Float0[1024] <= &MemRef_Float1[0] || &MemRef_Float1[1024] <= &MemRef_Float0[0]
+; NOAA-DAG:    &MemRef_Int1[1024] <= &MemRef_Float0[0] || &MemRef_Float0[1024] <= &MemRef_Int1[0]
+; NOAA:      ))
+;
+; TBAA:      if (1 && (
+; TBAA-DAG:    &MemRef_Int0[1024] <= &MemRef_Int1[0] || &MemRef_Int1[1024] <= &MemRef_Int0[0]
+; TBAA-DAG:    &MemRef_Float1[1024] <= &MemRef_Float0[0] || &MemRef_Float0[1024] <= &MemRef_Float1[0]
+; TBAA:      ))
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* nocapture %Int0, i32* nocapture readonly %Int1, float* nocapture %Float0, float* nocapture readonly %Float1) {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %arrayidx = getelementptr inbounds i32* %Int1, i64 %indvars.iv
+  %tmp = load i32* %arrayidx, align 4, !tbaa !0
+  %arrayidx2 = getelementptr inbounds i32* %Int0, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4, !tbaa !0
+  %arrayidx4 = getelementptr inbounds float* %Float1, i64 %indvars.iv
+  %tmp1 = load float* %arrayidx4, align 4, !tbaa !4
+  %arrayidx6 = getelementptr inbounds float* %Float0, i64 %indvars.iv
+  store float %tmp1, float* %arrayidx6, align 4, !tbaa !4
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 1024
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+!0 = !{!1, !1, i64 0}
+!1 = !{!"int", !2, i64 0}
+!2 = !{!"omnipotent char", !3, i64 0}
+!3 = !{!"Simple C/C++ TBAA"}
+!4 = !{!5, !5, i64 0}
+!5 = !{!"float", !2, i64 0}
diff --git a/final/test/Isl/Ast/aliasing_parametric_simple_1.ll b/final/test/Isl/Ast/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..64bf9af
--- /dev/null
+++ b/final/test/Isl/Ast/aliasing_parametric_simple_1.ll
@@ -0,0 +1,39 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze %s | FileCheck %s
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c];
+;    }
+;
+; CHECK: if (1 && (&MemRef_A[1024] <= &MemRef_B[c] || &MemRef_B[c + 1] <= &MemRef_A[0]))
+; CHECK:     for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK:       Stmt_for_body(c0);
+; CHECK: else
+; CHECK:     /* original code */
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %idxprom = sext i32 %c to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/aliasing_parametric_simple_2.ll b/final/test/Isl/Ast/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..e8add3a
--- /dev/null
+++ b/final/test/Isl/Ast/aliasing_parametric_simple_2.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-ast -analyze < %s | FileCheck %s
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c - 10] + B[5];
+;    }
+;
+; CHECK: if (1 && (&MemRef_A[1024] <= &MemRef_B[c >= 15 ? 5 : c - 10] || &MemRef_B[c <= 15 ? 6 : c - 9] <= &MemRef_A[0]))
+; CHECK:     for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK:       Stmt_for_body(c0);
+; CHECK: else
+; CHECK:    /* original code */
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %sub = add nsw i32 %c, -10
+  %idxprom = sext i32 %sub to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 5
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx3 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_constant.ll b/final/test/Isl/Ast/dependence_distance_constant.ll
new file mode 100644
index 0000000..36eec43
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_constant.ll
@@ -0,0 +1,52 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;        void f(int *A, int N) {
+; CHECK:   #pragma minimal dependence distance: 1
+;          for (int j = 0; j < N; j++)
+; CHECK:     #pragma minimal dependence distance: 8
+;            for (int i = 0; i < N; i++)
+;              A[i + 8] = A[i] + 1;
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %j.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %cmp = icmp slt i32 %j.0, %N
+  br i1 %cmp, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %i.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, %N
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  %add4 = add nsw i32 %i.0, 8
+  %arrayidx5 = getelementptr inbounds i32* %A, i32 %add4
+  store i32 %add, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %j.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_multiple_constant.ll b/final/test/Isl/Ast/dependence_distance_multiple_constant.ll
new file mode 100644
index 0000000..f7a9ba5
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_multiple_constant.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;        void f(int *restrict A, int *restrict B, int N) {
+; CHECK:   #pragma minimal dependence distance: 5
+;          for (int i = 0; i < N; i++) {
+;            A[i + 7] = A[i] + 1;
+;            B[i + 5] = B[i] + 1;
+;          }
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %B, i32 %N) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  %add1 = add nsw i32 %i.0, 7
+  %arrayidx2 = getelementptr inbounds i32* %A, i32 %add1
+  store i32 %add, i32* %arrayidx2, align 4
+  %arrayidx3 = getelementptr inbounds i32* %B, i32 %i.0
+  %tmp1 = load i32* %arrayidx3, align 4
+  %add4 = add nsw i32 %tmp1, 1
+  %add5 = add nsw i32 %i.0, 5
+  %arrayidx6 = getelementptr inbounds i32* %B, i32 %add5
+  store i32 %add4, i32* %arrayidx6, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_parametric.ll b/final/test/Isl/Ast/dependence_distance_parametric.ll
new file mode 100644
index 0000000..4478662
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_parametric.ll
@@ -0,0 +1,52 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;        void f(int *A, int N, int c) {
+; CHECK:   #pragma minimal dependence distance: 1
+;          for (int j = 0; j < N; j++)
+; CHECK:     #pragma minimal dependence distance: c >= 1 ? c : -c
+;            for (int i = 0; i < N; i++)
+;              A[i + c] = A[i] + 1;
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A, i32 %N, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %j.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %cmp = icmp slt i32 %j.0, %N
+  br i1 %cmp, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %i.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, %N
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  %add4 = add nsw i32 %i.0, %c
+  %arrayidx5 = getelementptr inbounds i32* %A, i32 %add4
+  store i32 %add, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %j.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_parametric_expr.ll b/final/test/Isl/Ast/dependence_distance_parametric_expr.ll
new file mode 100644
index 0000000..d225fad
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_parametric_expr.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;        void f(int *A, int N, int c, int v) {
+; CHECK:   #pragma minimal dependence distance: 1
+;          for (int j = 0; j < N; j++)
+; CHECK:     #pragma minimal dependence distance: c + v >= 1 ? c + v : -c - v
+;            for (int i = 0; i < N; i++)
+;              A[i + c + v] = A[i] + 1;
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A, i32 %N, i32 %c, i32 %v) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc7, %entry
+  %j.0 = phi i32 [ 0, %entry ], [ %inc8, %for.inc7 ]
+  %cmp = icmp slt i32 %j.0, %N
+  br i1 %cmp, label %for.body, label %for.end9
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %i.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, %N
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  %add4 = add nsw i32 %i.0, %c
+  %add5 = add nsw i32 %add4, %v
+  %arrayidx6 = getelementptr inbounds i32* %A, i32 %add5
+  store i32 %add, i32* %arrayidx6, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %j.0, 1
+  br label %for.cond
+
+for.end9:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_varying.ll b/final/test/Isl/Ast/dependence_distance_varying.ll
new file mode 100644
index 0000000..3d9bdb0
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_varying.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;         void f(int *A, int N) {
+; CHECK:    #pragma minimal dependence distance: ((N - 1) % 2) + 1
+;           for (int i = 0; i < N; i++)
+;             A[i] = A[N - i] + 1;
+;         }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %sub = sub nsw i32 %N, %i.0
+  %arrayidx = getelementptr inbounds i32* %A, i32 %sub
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  %arrayidx1 = getelementptr inbounds i32* %A, i32 %i.0
+  store i32 %add, i32* %arrayidx1, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_varying_in_outer_loop.ll b/final/test/Isl/Ast/dependence_distance_varying_in_outer_loop.ll
new file mode 100644
index 0000000..932612e
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_varying_in_outer_loop.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-canonicalize -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;        void f(int *restrict A, int *restrict sum) {
+; CHECK:   #pragma minimal dependence distance: 1
+;          for (int j = 0; j < 1024; j++)
+; CHECK:     #pragma minimal dependence distance: 1
+;            for (int i = j; i < 1024; i++)
+;              A[i - 3] = A[j] * 2 + A[j] + 2;
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc7, %entry
+  %j.0 = phi i32 [ 0, %entry ], [ %inc8, %for.inc7 ]
+  %exitcond1 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end9
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %i.0 = phi i32 [ %j.0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %j.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = mul nsw i32 %tmp, 3
+  %add5 = add nsw i32 %add, 2
+  %sub = add nsw i32 %i.0, -3
+  %arrayidx6 = getelementptr inbounds i32* %A, i32 %sub
+  store i32 %add5, i32* %arrayidx6, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %j.0, 1
+  br label %for.cond
+
+for.end9:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/dependence_distance_varying_multiple.ll b/final/test/Isl/Ast/dependence_distance_varying_multiple.ll
new file mode 100644
index 0000000..23a261a
--- /dev/null
+++ b/final/test/Isl/Ast/dependence_distance_varying_multiple.ll
@@ -0,0 +1,70 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+;        void f(int *restrict A, int *restrict B, int *restrict C, int *restrict D,
+;               int *restrict E, int N) {
+; CHECK:   #pragma minimal dependence distance: N >= 35 ? 1 : N >= 17 && N <= 34 ? 2 : 5
+;          for (int i = 0; i < N; i++) {
+;            A[i] = A[100 - 2 * i] + 1;
+;            B[i] = B[100 - 3 * i] + 1;
+;            C[i] = C[100 - 4 * i] + 1;
+;            D[i] = D[100 - 5 * i] + 1;
+;            E[i] = E[100 - 6 * i] + 1;
+;          }
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %B, i32* noalias %C, i32* noalias %D, i32* noalias %E, i32 %N) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %mul = shl nsw i32 %i.0, 1
+  %sub = sub nsw i32 100, %mul
+  %arrayidx = getelementptr inbounds i32* %A, i32 %sub
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  %arrayidx1 = getelementptr inbounds i32* %A, i32 %i.0
+  store i32 %add, i32* %arrayidx1, align 4
+  %tmp1 = mul i32 %i.0, -3
+  %sub3 = add i32 %tmp1, 100
+  %arrayidx4 = getelementptr inbounds i32* %B, i32 %sub3
+  %tmp2 = load i32* %arrayidx4, align 4
+  %add5 = add nsw i32 %tmp2, 1
+  %arrayidx6 = getelementptr inbounds i32* %B, i32 %i.0
+  store i32 %add5, i32* %arrayidx6, align 4
+  %mul7 = shl nsw i32 %i.0, 2
+  %sub8 = sub nsw i32 100, %mul7
+  %arrayidx9 = getelementptr inbounds i32* %C, i32 %sub8
+  %tmp3 = load i32* %arrayidx9, align 4
+  %add10 = add nsw i32 %tmp3, 1
+  %arrayidx11 = getelementptr inbounds i32* %C, i32 %i.0
+  store i32 %add10, i32* %arrayidx11, align 4
+  %tmp4 = mul i32 %i.0, -5
+  %sub13 = add i32 %tmp4, 100
+  %arrayidx14 = getelementptr inbounds i32* %D, i32 %sub13
+  %tmp5 = load i32* %arrayidx14, align 4
+  %add15 = add nsw i32 %tmp5, 1
+  %arrayidx16 = getelementptr inbounds i32* %D, i32 %i.0
+  store i32 %add15, i32* %arrayidx16, align 4
+  %tmp6 = mul i32 %i.0, -6
+  %sub18 = add i32 %tmp6, 100
+  %arrayidx19 = getelementptr inbounds i32* %E, i32 %sub18
+  %tmp7 = load i32* %arrayidx19, align 4
+  %add20 = add nsw i32 %tmp7, 1
+  %arrayidx21 = getelementptr inbounds i32* %E, i32 %i.0
+  store i32 %add20, i32* %arrayidx21, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_clauses_multidimensional_access.ll b/final/test/Isl/Ast/reduction_clauses_multidimensional_access.ll
new file mode 100644
index 0000000..3ecc54a
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_clauses_multidimensional_access.ll
@@ -0,0 +1,68 @@
+; RUN: opt %loadPolly -polly-delinearize -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK: #pragma known-parallel reduction (^ : sum)
+;        void f(int N, int M, int P, int sum[P][M]) {
+;          for (int i = 0; i < N; i++)
+;            for (int j = 0; j < P; j++)
+; CHECK:       #pragma simd
+;              for (int k = 0; k < M; k++)
+;                sum[j][k] ^= j;
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32 %N, i32 %M, i32 %P, i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc11, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc12, %for.inc11 ]
+  %cmp = icmp slt i32 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end13
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc8, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc9, %for.inc8 ]
+  %cmp2 = icmp slt i32 %j.0, %P
+  br i1 %cmp2, label %for.body3, label %for.end10
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %cmp5 = icmp slt i32 %k.0, %M
+  br i1 %cmp5, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %tmp = mul nsw i32 %j.0, %M
+  %arrayidx.sum = add i32 %tmp, %k.0
+  %arrayidx7 = getelementptr inbounds i32* %sum, i32 %arrayidx.sum
+  %tmp1 = load i32* %arrayidx7, align 4
+  %xor = xor i32 %tmp1, %j.0
+  store i32 %xor, i32* %arrayidx7, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %for.end
+  %inc9 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end10:                                        ; preds = %for.cond1
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.end10
+  %inc12 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end13:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_clauses_onedimensional_access.ll b/final/test/Isl/Ast/reduction_clauses_onedimensional_access.ll
new file mode 100644
index 0000000..a5143c7
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_clauses_onedimensional_access.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK: #pragma known-parallel reduction (^ : sum)
+;        void f(int N, int M, int *sum) {
+;          for (int i = 0; i < N; i++)
+; CHECK:    #pragma simd
+;            for (int j = 0; j < M; j++)
+;              sum[j] ^= j;
+;        }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32 %N, i32 %M, i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %cmp = icmp slt i32 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %cmp2 = icmp slt i32 %j.0, %M
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %j.0
+  %tmp = load i32* %arrayidx, align 4
+  %xor = xor i32 %tmp, %j.0
+  store i32 %xor, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_dependences_equal_non_reduction_dependences.ll b/final/test/Isl/Ast/reduction_dependences_equal_non_reduction_dependences.ll
new file mode 100644
index 0000000..1c84308
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_dependences_equal_non_reduction_dependences.ll
@@ -0,0 +1,57 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; This loopnest contains a reduction which imposes the same dependences as the
+; accesses to the array A. We need to ensure we do __not__ parallelize anything
+; here.
+;
+; CHECK: #pragma minimal dependence distance: 1
+; CHECK-NOT: pragma
+; CHECK-NOT: reduction
+;
+;    void AandSum(int *restrict sum, int *restrict A) {
+;      for (int i = 0; i < 1024; i++) {
+;        A[i] = A[i] + A[i - 1];
+;        A[i - 1] = A[i] + A[i - 2];
+;        *sum += i;
+;      }
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @AandSum(i32* noalias %sum, i32* noalias %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %sub = add nsw i32 %i.0, -1
+  %arrayidx1 = getelementptr inbounds i32* %A, i32 %sub
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx2 = getelementptr inbounds i32* %A, i32 %i.0
+  store i32 %add, i32* %arrayidx2, align 4
+  %sub4 = add nsw i32 %i.0, -2
+  %arrayidx5 = getelementptr inbounds i32* %A, i32 %sub4
+  %tmp2 = load i32* %arrayidx5, align 4
+  %add6 = add nsw i32 %add, %tmp2
+  %sub7 = add nsw i32 %i.0, -1
+  %arrayidx8 = getelementptr inbounds i32* %A, i32 %sub7
+  store i32 %add6, i32* %arrayidx8, align 4
+  %tmp3 = load i32* %sum, align 4
+  %add9 = add nsw i32 %tmp3, %i.0
+  store i32 %add9, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_different_reduction_clauses.ll b/final/test/Isl/Ast/reduction_different_reduction_clauses.ll
new file mode 100644
index 0000000..664692e
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_different_reduction_clauses.ll
@@ -0,0 +1,55 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK: #pragma simd reduction (+ : sum{{[1,2]}}, sum{{[1,2]}}) reduction (* : prod) reduction (| : or) reduction (& : and)
+; CHECK: #pragma known-parallel reduction (+ : sum{{[1,2]}}, sum{{[1,2]}}) reduction (* : prod) reduction (| : or) reduction (& : and)
+; CHECK: for (int c0 = 0; c0 < N; c0 += 1)
+; CHECK:   Stmt_for_body(c0);
+;
+;    void f(int N, int *restrict sum1, int *restrict sum2, int *restrict prod,
+;           int *restrict and, int *restrict or ) {
+;      for (int i = 0; i < N; i++) {
+;        *sum1 += i;
+;        *sum2 += i + 1;
+;        *prod *= i;
+;        *and &= i;
+;        * or |= i;
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32 %N, i32* noalias %sum1, i32* noalias %sum2, i32* noalias %prod, i32* noalias %and, i32* noalias %or) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp = load i32* %sum1, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %sum1, align 4
+  %add1 = add nsw i32 %i.0, 1
+  %tmp1 = load i32* %sum2, align 4
+  %add2 = add nsw i32 %tmp1, %add1
+  store i32 %add2, i32* %sum2, align 4
+  %tmp2 = load i32* %prod, align 4
+  %mul = mul nsw i32 %tmp2, %i.0
+  store i32 %mul, i32* %prod, align 4
+  %tmp3 = load i32* %and, align 4
+  %and3 = and i32 %tmp3, %i.0
+  store i32 %and3, i32* %and, align 4
+  %tmp4 = load i32* %or, align 4
+  %or4 = or i32 %tmp4, %i.0
+  store i32 %or4, i32* %or, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_in_one_dimension.ll b/final/test/Isl/Ast/reduction_in_one_dimension.ll
new file mode 100644
index 0000000..ed21d61
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_in_one_dimension.ll
@@ -0,0 +1,57 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; Verify that we won't privatize anything in the outer dimension
+;
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c0 = 0; c0 < 2 * n; c0 += 1)
+; CHECK:      #pragma simd reduction
+; CHECK:      for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:        Stmt_for_body3(c0, c1);
+;
+;    void foo(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+;        for (long j = 0; j < 1024; j++)
+;          A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @foo(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_loop_reversal.ll b/final/test/Isl/Ast/reduction_loop_reversal.ll
new file mode 100644
index 0000000..25ee3d7
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_loop_reversal.ll
@@ -0,0 +1,66 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT: #pragma simd{{\s*$}}
+; CHECK: #pragma simd reduction
+; CHECK: Stmt_S0(n - c1)
+; CHECK: #pragma simd{{\s*$}}
+; CHECK: Stmt_S1(n - c1)
+;
+;    void rlr(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+; S0:    A[0] += i;
+;      for (long i = 0; i < 2 * n; i++)
+; S1:    A[i + 1] = 1;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rlr(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %tmp = load i32* %A, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %A, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc8, %for.end
+  %i1.0 = phi i32 [ 0, %for.end ], [ %inc9, %for.inc8 ]
+  %mul3 = shl nsw i32 %n, 1
+  %cmp4 = icmp slt i32 %i1.0, %mul3
+  br i1 %cmp4, label %for.body5, label %for.end10
+
+for.body5:                                        ; preds = %for.cond2
+  br label %S1
+
+S1:                                               ; preds = %for.body5
+  %add6 = add nsw i32 %i1.0, 1
+  %arrayidx7 = getelementptr inbounds i32* %A, i32 %add6
+  store i32 1, i32* %arrayidx7, align 4
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %S1
+  %inc9 = add nsw i32 %i1.0, 1
+  br label %for.cond2
+
+for.end10:                                        ; preds = %for.cond2
+  ret void
+}
+
diff --git a/final/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule.ll b/final/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule.ll
new file mode 100644
index 0000000..0285dbb
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT: #pragma simd{{\s*$}}
+; CHECK: #pragma simd reduction
+; CHECK: Stmt_S0(2 * n - c1)
+; CHECK: #pragma simd{{\s*$}}
+; CHECK: Stmt_S1
+; CHECK: #pragma simd reduction
+; CHECK: Stmt_S0(2 * n - c1)
+; CHECK-NOT: #pragma simd{{\s*$}}
+;
+;    void rmalrs(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+; S0:    A[0] += i;
+;      for (long i = 0; i < 2 * n; i++)
+; S1:    A[i + 1] = 1;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmalrs(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %tmp = load i32* %A, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %A, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc8, %for.end
+  %i1.0 = phi i32 [ 0, %for.end ], [ %inc9, %for.inc8 ]
+  %mul3 = shl nsw i32 %n, 1
+  %cmp4 = icmp slt i32 %i1.0, %mul3
+  br i1 %cmp4, label %for.body5, label %for.end10
+
+for.body5:                                        ; preds = %for.cond2
+  br label %S1
+
+S1:                                               ; preds = %for.body5
+  %add6 = add nsw i32 %i1.0, 1
+  %arrayidx7 = getelementptr inbounds i32* %A, i32 %add6
+  store i32 1, i32* %arrayidx7, align 4
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %S1
+  %inc9 = add nsw i32 %i1.0, 1
+  br label %for.cond2
+
+for.end10:                                        ; preds = %for.cond2
+  ret void
+}
+
diff --git a/final/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule_2.ll b/final/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule_2.ll
new file mode 100644
index 0000000..7d99cc9
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule_2.ll
@@ -0,0 +1,76 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK:    #pragma known-parallel reduction
+; CHECK:    for (int c0 = 0; c0 <= 2; c0 += 1) {
+; CHECK:      if (c0 == 2) {
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c1 = 1; c1 < 2 * n; c1 += 2)
+; CHECK:          Stmt_S0(c1);
+; CHECK:      } else if (c0 == 1) {
+; CHECK:        #pragma simd
+; CHECK:        for (int c1 = 0; c1 < 2 * n; c1 += 1)
+; CHECK:          Stmt_S1(c1);
+; CHECK:      } else
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c1 = -2 * n + 2; c1 <= 0; c1 += 2)
+; CHECK:          Stmt_S0(-c1);
+; CHECK:    }
+;
+;    void rmalrs2(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+; S0:    A[0] += i;
+;      for (long i = 0; i < 2 * n; i++)
+; S1:    A[i + 1] = 1;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmalrs2(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %tmp = load i32* %A, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %A, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc8, %for.end
+  %i1.0 = phi i32 [ 0, %for.end ], [ %inc9, %for.inc8 ]
+  %mul3 = shl nsw i32 %n, 1
+  %cmp4 = icmp slt i32 %i1.0, %mul3
+  br i1 %cmp4, label %for.body5, label %for.end10
+
+for.body5:                                        ; preds = %for.cond2
+  br label %S1
+
+S1:                                               ; preds = %for.body5
+  %add6 = add nsw i32 %i1.0, 1
+  %arrayidx7 = getelementptr inbounds i32* %A, i32 %add6
+  store i32 1, i32* %arrayidx7, align 4
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %S1
+  %inc9 = add nsw i32 %i1.0, 1
+  br label %for.cond2
+
+for.end10:                                        ; preds = %for.cond2
+  ret void
+}
+
diff --git a/final/test/Isl/Ast/reduction_modulo_schedule.ll b/final/test/Isl/Ast/reduction_modulo_schedule.ll
new file mode 100644
index 0000000..f4dfef6
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_schedule.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT: #pragma simd{{\s*$}}
+; CHECK: #pragma simd reduction
+; CHECK: Stmt_S0
+; CHECK: #pragma simd{{\s*$}}
+; CHECK: Stmt_S1
+; CHECK: #pragma simd reduction
+; CHECK: Stmt_S0
+; CHECK-NOT: #pragma simd{{\s*$}}
+;
+;    void rms(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+; S0:    A[0] += i;
+;      for (long i = 0; i < 2 * n; i++)
+; S1:    A[i + 1] = 1;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rms(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br label %S0
+
+S0:                                               ; preds = %for.body
+  %tmp = load i32* %A, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %A, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %S0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %for.inc8, %for.end
+  %i1.0 = phi i32 [ 0, %for.end ], [ %inc9, %for.inc8 ]
+  %mul3 = shl nsw i32 %n, 1
+  %cmp4 = icmp slt i32 %i1.0, %mul3
+  br i1 %cmp4, label %for.body5, label %for.end10
+
+for.body5:                                        ; preds = %for.cond2
+  br label %S1
+
+S1:                                               ; preds = %for.body5
+  %add6 = add nsw i32 %i1.0, 1
+  %arrayidx7 = getelementptr inbounds i32* %A, i32 %add6
+  store i32 1, i32* %arrayidx7, align 4
+  br label %for.inc8
+
+for.inc8:                                         ; preds = %S1
+  %inc9 = add nsw i32 %i1.0, 1
+  br label %for.cond2
+
+for.end10:                                        ; preds = %for.cond2
+  ret void
+}
+
diff --git a/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll
new file mode 100644
index 0000000..4360ea6
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c0 = 0; c0 <= 1; c0 += 1) {
+; CHECK:      if (c0 == 1) {
+; CHECK:        for (int c1 = 1; c1 < 2 * n; c1 += 2)
+; CHECK:          #pragma simd reduction
+; CHECK:          for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK:            Stmt_for_body3(c1, c3);
+; CHECK:      } else
+; CHECK:        for (int c1 = 0; c1 < 2 * n; c1 += 2)
+; CHECK:          #pragma simd reduction
+; CHECK:          for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK:            Stmt_for_body3(c1, c3);
+; CHECK:    }
+;
+;    void rmsmd(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+;        for (long j = 0; j < 1024; j++)
+;          A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmsmd(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll
new file mode 100644
index 0000000..5b33b4e
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll
@@ -0,0 +1,64 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; Verify that the outer dimension doesnt't carry reduction dependences
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c1 = 0; c1 < 2 * n; c1 += 1) {
+; CHECK:      if (c1 % 2 == 0) {
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK:          Stmt_for_body3(c1, c3);
+; CHECK:      } else
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK:          Stmt_for_body3(c1, c3);
+; CHECK:    }
+;
+;    void rmsmd2(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+;        for (long j = 0; j < 1024; j++)
+;          A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmsmd2(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll
new file mode 100644
index 0000000..52bc242
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll
@@ -0,0 +1,62 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; Verify that the outer dimension doesnt't carry reduction dependences
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c1 = 0; c1 < 2 * n; c1 += 1)
+; CHECK:      #pragma simd reduction
+; CHECK:      for (int c3 = 0; c3 <= 1023; c3 += 1) {
+; CHECK:        if (c3 % 2 == 0) {
+; CHECK:          Stmt_for_body3(c1, c3);
+; CHECK:        } else
+; CHECK:          Stmt_for_body3(c1, c3);
+; CHECK:      }
+;
+;    void rmsmd3(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+;        for (long j = 0; j < 1024; j++)
+;          A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmsmd3(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll
new file mode 100644
index 0000000..1ecc549
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll
@@ -0,0 +1,62 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; Verify that the outer dimension doesnt't carry reduction dependences
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c1 = 0; c1 < 2 * n; c1 += 1)
+; CHECK:      #pragma simd reduction
+; CHECK:      for (int c3 = -1023; c3 <= 1023; c3 += 1) {
+; CHECK:        if (c3 <= 0 && -c3 % 2 == 0)
+; CHECK:          Stmt_for_body3(c1, -c3);
+; CHECK:        } else if (c3 >= 1 && (c3 - 1) % 2 == 0)
+; CHECK:          Stmt_for_body3(c1, c3);
+; CHECK:      }
+;
+;    void rmsmd4(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+;        for (long j = 0; j < 1024; j++)
+;          A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmsmd4(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_5.ll b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_5.ll
new file mode 100644
index 0000000..23b26a2
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_5.ll
@@ -0,0 +1,65 @@
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; Verify that only the outer dimension needs privatization
+;
+; CHECK:    #pragma known-parallel reduction
+; CHECK:    for (int c1 = 0; c1 <= 1023; c1 += 1) {
+; CHECK:      if (c1 % 2 == 0) {
+; CHECK-NOT:    #pragma simd reduction
+; CHECK:        #pragma simd
+; CHECK:        for (int c3 = 0; c3 < 2 * n; c3 += 1)
+; CHECK:          Stmt_for_body3(c3, c1);
+; CHECK:      } else
+; CHECK-NOT:    #pragma simd reduction
+; CHECK:        #pragma simd
+; CHECK:        for (int c3 = -2 * n + 1; c3 <= 0; c3 += 1)
+; CHECK:          Stmt_for_body3(-c3, c1);
+; CHECK:    }
+;
+;    void rmsmd5(int *A, long n) {
+;      for (long i = 0; i < 2 * n; i++)
+;        for (long j = 0; j < 1024; j++)
+;          A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmsmd5(i32* %A, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %mul = shl nsw i32 %n, 1
+  %cmp = icmp slt i32 %i.0, %mul
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_multiple_dimensions.ll b/final/test/Isl/Ast/reduction_multiple_dimensions.ll
new file mode 100644
index 0000000..aefc507
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_multiple_dimensions.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c0 = 0; c0 <= 2047; c0 += 1)
+; CHECK:      for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c2 = 0; c2 <= 511; c2 += 1)
+; CHECK:          Stmt_for_body6(c0, c1, c2);
+;
+;    void rmd(int *A) {
+;      for (long i = 0; i < 2048; i++)
+;        for (long j = 0; j < 1024; j++)
+;          for (long k = 0; k < 512; k++)
+;            A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond2 = icmp ne i32 %i.0, 2048
+  br i1 %exitcond2, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc7, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc8, %for.inc7 ]
+  %exitcond1 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond1, label %for.body3, label %for.end9
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %k.0, 512
+  br i1 %exitcond, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end9:                                         ; preds = %for.cond1
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end9
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_multiple_dimensions_2.ll b/final/test/Isl/Ast/reduction_multiple_dimensions_2.ll
new file mode 100644
index 0000000..404040f
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_multiple_dimensions_2.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c0 = 0; c0 <= 2047; c0 += 1)
+; CHECK:      for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c2 = 0; c2 <= 511; c2 += 1)
+; CHECK:          Stmt_for_body6(c0, c1, c2);
+;
+;    void rmd2(int *A) {
+;      for (long i = 0; i < 2048; i++)
+;        for (long j = 0; j < 1024; j++)
+;          for (long k = 0; k < 512; k++)
+;            A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmd2(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond2 = icmp ne i32 %i.0, 2048
+  br i1 %exitcond2, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc7, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc8, %for.inc7 ]
+  %exitcond1 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond1, label %for.body3, label %for.end9
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %k.0, 512
+  br i1 %exitcond, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end9:                                         ; preds = %for.cond1
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end9
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_multiple_dimensions_3.ll b/final/test/Isl/Ast/reduction_multiple_dimensions_3.ll
new file mode 100644
index 0000000..b37b9a5
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_multiple_dimensions_3.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c0 = 0; c0 <= 2047; c0 += 1)
+; CHECK:      for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c2 = 0; c2 <= 511; c2 += 1)
+; CHECK:          Stmt_for_body6(c0, c1, c2);
+;
+;    void rmd3(int *A) {
+;      for (long i = 0; i < 2048; i++)
+;        for (long j = 0; j < 1024; j++)
+;          for (long k = 0; k < 512; k++)
+;            A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmd3(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond2 = icmp ne i32 %i.0, 2048
+  br i1 %exitcond2, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc7, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc8, %for.inc7 ]
+  %exitcond1 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond1, label %for.body3, label %for.end9
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %k.0, 512
+  br i1 %exitcond, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end9:                                         ; preds = %for.cond1
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end9
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/reduction_multiple_dimensions_4.ll b/final/test/Isl/Ast/reduction_multiple_dimensions_4.ll
new file mode 100644
index 0000000..3445dbe
--- /dev/null
+++ b/final/test/Isl/Ast/reduction_multiple_dimensions_4.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK-NOT:#pragma known-parallel reduction
+; CHECK:    #pragma known-parallel
+; CHECK:    for (int c0 = 0; c0 <= 2047; c0 += 1)
+; CHECK:      for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:        #pragma simd reduction
+; CHECK:        for (int c2 = 0; c2 <= 511; c2 += 1)
+; CHECK:          Stmt_for_body6(c0, c1, c2);
+;
+;    void rmd4(int *A) {
+;      for (long i = 0; i < 2048; i++)
+;        for (long j = 0; j < 1024; j++)
+;          for (long k = 0; k < 512; k++)
+;            A[i] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @rmd4(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond2 = icmp ne i32 %i.0, 2048
+  br i1 %exitcond2, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc7, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc8, %for.inc7 ]
+  %exitcond1 = icmp ne i32 %j.0, 1024
+  br i1 %exitcond1, label %for.body3, label %for.end9
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %k.0, 512
+  br i1 %exitcond, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end9:                                         ; preds = %for.cond1
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end9
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/Ast/rlr___%for.cond---%for.end10.jscop b/final/test/Isl/Ast/rlr___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..fc50d5c
--- /dev/null
+++ b/final/test/Isl/Ast/rlr___%for.cond---%for.end10.jscop
@@ -0,0 +1,32 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end10",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S0[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S0",
+         "schedule" : "[n] -> { Stmt_S0[i0] -> scattering[0, n - i0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S1[i0] -> MemRef_A[1 + i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S1[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S1",
+         "schedule" : "[n] -> { Stmt_S1[i0] -> scattering[1, n - i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmalrs2___%for.cond---%for.end10.jscop b/final/test/Isl/Ast/rmalrs2___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..c84f0a0
--- /dev/null
+++ b/final/test/Isl/Ast/rmalrs2___%for.cond---%for.end10.jscop
@@ -0,0 +1,32 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end10",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S0[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S0",
+         "schedule" : "[n] -> { Stmt_S0[i0] -> scattering[0, -i0, 0]: i0 % 2 = 0; Stmt_S0[i0] -> scattering[2, i0, 0]: i0 % 2 = 1 }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S1[i0] -> MemRef_A[1 + i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S1[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S1",
+         "schedule" : "[n] -> { Stmt_S1[i0] -> scattering[1, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmalrs___%for.cond---%for.end10.jscop b/final/test/Isl/Ast/rmalrs___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..9740b57
--- /dev/null
+++ b/final/test/Isl/Ast/rmalrs___%for.cond---%for.end10.jscop
@@ -0,0 +1,32 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end10",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S0[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S0",
+         "schedule" : "[n] -> { Stmt_S0[i0] -> scattering[0, 2 * n - i0, 0]: i0 % 2 = 0; Stmt_S0[i0] -> scattering[2, 2  * n - i0, 0]: i0 % 2 = 1 }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S1[i0] -> MemRef_A[1 + i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S1[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S1",
+         "schedule" : "[n] -> { Stmt_S1[i0] -> scattering[1, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmd2___%for.cond---%for.end12.jscop b/final/test/Isl/Ast/rmd2___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..bca9793
--- /dev/null
+++ b/final/test/Isl/Ast/rmd2___%for.cond---%for.end12.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end12",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body6[i0, i1, i2] : i0 >= 0 and i0 <= 2047 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 511 }",
+         "name" : "Stmt_for_body6",
+         "schedule" : "{ Stmt_for_body6[i0, i1, i2] -> scattering[0, i1, 0, i0, 0, i2, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmd3___%for.cond---%for.end12.jscop b/final/test/Isl/Ast/rmd3___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..7cd7570
--- /dev/null
+++ b/final/test/Isl/Ast/rmd3___%for.cond---%for.end12.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end12",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body6[i0, i1, i2] : i0 >= 0 and i0 <= 2047 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 511 }",
+         "name" : "Stmt_for_body6",
+         "schedule" : "{ Stmt_for_body6[i0, i1, i2] -> scattering[0, i2, 0, i1, 0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmd4___%for.cond---%for.end12.jscop b/final/test/Isl/Ast/rmd4___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..b29c322
--- /dev/null
+++ b/final/test/Isl/Ast/rmd4___%for.cond---%for.end12.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end12",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body6[i0, i1, i2] : i0 >= 0 and i0 <= 2047 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 511 }",
+         "name" : "Stmt_for_body6",
+         "schedule" : "{ Stmt_for_body6[i0, i1, i2] -> scattering[0, i2, 0, i0, 0, i1, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmd___%for.cond---%for.end12.jscop b/final/test/Isl/Ast/rmd___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..be7cdc2
--- /dev/null
+++ b/final/test/Isl/Ast/rmd___%for.cond---%for.end12.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end12",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body6[i0, i1, i2] : i0 >= 0 and i0 <= 2047 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 511 }",
+         "name" : "Stmt_for_body6",
+         "schedule" : "{ Stmt_for_body6[i0, i1, i2] -> scattering[0, i0, 0, i1, 0, i2, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rms___%for.cond---%for.end10.jscop b/final/test/Isl/Ast/rms___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..15a6930
--- /dev/null
+++ b/final/test/Isl/Ast/rms___%for.cond---%for.end10.jscop
@@ -0,0 +1,32 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end10",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S0[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S0[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S0",
+         "schedule" : "[n] -> { Stmt_S0[i0] -> scattering[0, i0, 0]: i0 % 2 = 0; Stmt_S0[i0] -> scattering[2, i0, 0]: i0 % 2 = 1 }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_S1[i0] -> MemRef_A[1 + i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_S1[i0] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 }",
+         "name" : "Stmt_S1",
+         "schedule" : "[n] -> { Stmt_S1[i0] -> scattering[1, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmsmd2___%for.cond---%for.end6.jscop b/final/test/Isl/Ast/rmsmd2___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..38cb44b
--- /dev/null
+++ b/final/test/Isl/Ast/rmsmd2___%for.cond---%for.end6.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "[n] -> { Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0]: i0 % 2 = 0; Stmt_for_body3[i0, i1] -> scattering[0, i0, 1, i1, 0]: i0 % 2 = 1 }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmsmd3___%for.cond---%for.end6.jscop b/final/test/Isl/Ast/rmsmd3___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..44d71a3
--- /dev/null
+++ b/final/test/Isl/Ast/rmsmd3___%for.cond---%for.end6.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "[n] -> { Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0]: i1 % 2 = 0; Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 1]: i1 % 2 = 1 }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmsmd4___%for.cond---%for.end6.jscop b/final/test/Isl/Ast/rmsmd4___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..9bfd4aa
--- /dev/null
+++ b/final/test/Isl/Ast/rmsmd4___%for.cond---%for.end6.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "[n] -> { Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, -i1, 0]: i1 % 2 = 0; Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 1]: i1 % 2 = 1 }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmsmd5___%for.cond---%for.end6.jscop b/final/test/Isl/Ast/rmsmd5___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..ee1c3dd
--- /dev/null
+++ b/final/test/Isl/Ast/rmsmd5___%for.cond---%for.end6.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "[n] -> { Stmt_for_body3[i0, i1] -> scattering[0, i1, 0, i0, 0]: i1 % 2 = 0; Stmt_for_body3[i0, i1] -> scattering[0, i1, 1, -i0, 0]: i1 % 2 = 1 }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/rmsmd___%for.cond---%for.end6.jscop b/final/test/Isl/Ast/rmsmd___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..8a8678a
--- /dev/null
+++ b/final/test/Isl/Ast/rmsmd___%for.cond---%for.end6.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "[n] -> {  : n >= -2147483648 and n <= 2147483647 }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "[n] -> { Stmt_for_body3[i0, i1] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "[n] -> { Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= -1 + 2n and n >= 1 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "[n] -> { Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0]: i0 % 2 = 0; Stmt_for_body3[i0, i1] -> scattering[1, i0, 0, i1, 0]: i0 % 2 = 1 }"
+      }
+   ]
+}
diff --git a/final/test/Isl/Ast/run-time-condition.ll b/final/test/Isl/Ast/run-time-condition.ll
new file mode 100644
index 0000000..fedada1
--- /dev/null
+++ b/final/test/Isl/Ast/run-time-condition.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -analyze < %s | FileCheck %s
+
+; for (i = 0; i < 1024; i++)
+;   A[i] = B[i];
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @run-time-condition(i16* noalias %A, i16* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %indvar = phi i64 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i64 %indvar, 1024
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i16* %B, i64 0
+  %load = load i16* %arrayidx
+  %add10 = add nsw i16 %load, 1
+  %arrayidx13 = getelementptr inbounds i16* %A, i64 %indvar
+  store i16 %add10, i16* %arrayidx13, align 2
+  %inc = add nsw i64 %indvar, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+; CHECK: if (1)
+; CHECK:     for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK:       Stmt_for_body(c0);
+; CHECK: else
+; CHECK:     {  /* original code */ }
+
diff --git a/final/test/Isl/Ast/simple-run-time-condition.ll b/final/test/Isl/Ast/simple-run-time-condition.ll
new file mode 100644
index 0000000..9bf52f2
--- /dev/null
+++ b/final/test/Isl/Ast/simple-run-time-condition.ll
@@ -0,0 +1,98 @@
+; RUN: opt %loadPolly -polly-ast -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, int o, double A[n][m], long p, long q) {
+;
+; if (o >= 0)
+;   for (long i = 0; i < n; i++)
+;     for (long j = 0; j < m; j++)
+;         A[i+p][j+q] = 1.0;
+; else
+;   for (long i = 0; i < n; i++)
+;     for (long j = 0; j < m; j++)
+;         A[i+p][j+q-100] = 1.0;
+;
+
+; This test case is meant to verify that the run-time condition generated
+; for the delinearization is simplified such that conditions that would not
+; cause any code to be executed are not generated.
+
+; CHECK: if (
+; CHECK: ({{(q == 100 && o <= 0|o <= 0 && q == 100)}})
+; CHECK: ||
+; CHECK: ({{(q == 0 && o >= 1)|(o >= 1 && q == 0)}})
+; CHECK: ? 1 : 0)
+
+; CHECK:     if (o >= 1) {
+; CHECK:       for (int c1 = 0; c1 < n; c1 += 1)
+; CHECK:         for (int c2 = 0; c2 < m; c2 += 1)
+; CHECK:           Stmt_for_j(c1, c2);
+; CHECK:     } else
+; CHECK:       for (int c1 = 0; c1 < n; c1 += 1)
+; CHECK:         for (int c2 = 0; c2 < m; c2 += 1)
+; CHECK:           Stmt_for_j_1(c1, c2);
+
+; CHECK: else
+; CHECK:     {  /* original code */ }
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A, i64 %p, i64 %q) {
+entry:
+  br label %cond
+
+cond:
+  %cmp = icmp sgt i64 %o, 0
+  br i1 %cmp, label %for.i, label %for.i.1
+
+for.i:
+  %i = phi i64 [ 0, %cond ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j.inc ]
+  %offset0 = add nsw i64 %i, %p
+  %subscript0 = mul i64 %offset0, %m
+  %offset1 = add nsw i64 %j, %q
+  %subscript1 = add i64 %offset1, %subscript0
+  %idx = getelementptr inbounds double* %A, i64 %subscript1
+  store double 1.0, double* %idx
+  br label %for.j.inc
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+for.i.1:
+  %i.1 = phi i64 [ 0, %cond ], [ %i.inc.1, %for.i.inc.1 ]
+  br label %for.j.1
+
+for.j.1:
+  %j.1 = phi i64 [ 0, %for.i.1 ], [ %j.inc.1, %for.j.inc.1 ]
+  %offset0.1 = add nsw i64 %i.1, %p
+  %subscript0.1 = mul i64 %offset0.1, %m
+  %offset1.1 = add nsw i64 %j.1, %q
+  %subscript1.1 = add i64 %offset1.1, %subscript0.1
+  %subscript1.2 = sub i64 %subscript1.1, 100
+  %idx.1 = getelementptr inbounds double* %A, i64 %subscript1.2
+  store double 1.0, double* %idx.1
+  br label %for.j.inc.1
+
+for.j.inc.1:
+  %j.inc.1 = add nsw i64 %j.1, 1
+  %j.exitcond.1 = icmp eq i64 %j.inc.1, %m
+  br i1 %j.exitcond.1, label %for.i.inc.1, label %for.j.1
+
+for.i.inc.1:
+  %i.inc.1 = add nsw i64 %i.1, 1
+  %i.exitcond.1 = icmp eq i64 %i.inc.1, %n
+  br i1 %i.exitcond.1, label %end, label %for.i.1
+
+end:
+  ret void
+}
diff --git a/final/test/Isl/Ast/single_loop_strip_mine.ll b/final/test/Isl/Ast/single_loop_strip_mine.ll
new file mode 100644
index 0000000..e61c2a8
--- /dev/null
+++ b/final/test/Isl/Ast/single_loop_strip_mine.ll
@@ -0,0 +1,41 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -basicaa -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s -check-prefix=CHECK-VECTOR
+
+; for (i = 0; i < 1024; i++)
+;   A[i] = B[i];
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @single_loop_strip_mine(i16* noalias %A, i16* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %indvar = phi i64 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i64 %indvar, 1024
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i16* %B, i64 0
+  %load = load i16* %arrayidx
+  %add10 = add nsw i16 %load, 1
+  %arrayidx13 = getelementptr inbounds i16* %A, i64 %indvar
+  store i16 %add10, i16* %arrayidx13, align 2
+  %inc = add nsw i64 %indvar, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK:     Stmt_for_body(c0);
+
+; CHECK-VECTOR: #pragma known-parallel
+; CHECK-VECTOR: for (int c0 = 0; c0 <= 1023; c0 += 4)
+; CHECK-VECTOR:     #pragma simd
+; CHECK-VECTOR:     for (int c1 = c0; c1 <= c0 + 3; c1 += 1)
+; CHECK-VECTOR:           Stmt_for_body(c1);
+
+
diff --git a/final/test/Isl/Ast/single_loop_strip_mine___%for.cond---%for.end.jscop b/final/test/Isl/Ast/single_loop_strip_mine___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..7dcf837
--- /dev/null
+++ b/final/test/Isl/Ast/single_loop_strip_mine___%for.cond---%for.end.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_B[0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 1023 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> [o0, i0] : exists (e0 = [(o0)/4]: 4e0 = o0 and o0 <= i0 and o0 >= -3 + i0 and i0 >= 0 and i0 <= 1023) }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/20100617.ll b/final/test/Isl/CodeGen/20100617.ll
new file mode 100644
index 0000000..d34b43a
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100617.ll
@@ -0,0 +1,19 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @init_array() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond1, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.cond1 ], [ 0, %entry ] ; <i64> [#uses=1]
+  br i1 false, label %for.cond1, label %for.end32
+
+for.cond1:                                        ; preds = %for.cond
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end32:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100622.ll b/final/test/Isl/CodeGen/20100622.ll
new file mode 100644
index 0000000..2e02404
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100622.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+; RUN: opt %loadPolly -polly-detect -analyze  < %s | not FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
+target triple = "i386-portbld-freebsd8.0"
+
+define void @MAIN__() nounwind {
+entry:
+  br i1 undef, label %bb6.preheader, label %bb3
+
+bb3:                                              ; preds = %bb3, %entry
+  br i1 undef, label %bb6.preheader, label %bb3
+
+bb6.preheader:                                    ; preds = %bb3, %entry
+  br i1 undef, label %bb11, label %bb9.preheader
+
+bb9.preheader:                                    ; preds = %bb6.preheader
+  br label %bb11
+
+bb11:                                             ; preds = %bb9.preheader, %bb6.preheader
+  br label %bb15
+
+bb15:                                             ; preds = %bb15, %bb11
+  br i1 undef, label %bb26.loopexit, label %bb15
+
+bb26.loopexit:                                    ; preds = %bb15
+  br i1 undef, label %bb31, label %bb29.preheader
+
+bb29.preheader:                                   ; preds = %bb26.loopexit
+  br label %bb29
+
+bb29:                                             ; preds = %bb29, %bb29.preheader
+  %indvar47 = phi i32 [ 0, %bb29.preheader ], [ %indvar.next48, %bb29 ] ; <i32> [#uses=1]
+  %indvar.next48 = add i32 %indvar47, 1           ; <i32> [#uses=2]
+  %exitcond50 = icmp eq i32 %indvar.next48, undef ; <i1> [#uses=1]
+  br i1 %exitcond50, label %bb31, label %bb29
+
+bb31:                                             ; preds = %bb29, %bb26.loopexit
+  %errtot.3 = phi float [ undef, %bb26.loopexit ], [ undef, %bb29 ] ; <float> [#uses=0]
+  ret void
+}
+
+; CHECK: SCOP:
diff --git a/final/test/Isl/CodeGen/20100707.ll b/final/test/Isl/CodeGen/20100707.ll
new file mode 100644
index 0000000..c34e668
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100707.ll
@@ -0,0 +1,27 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @clause_SetSplitField(i32 %Length) nounwind inlinehint {
+entry:
+  br i1 undef, label %bb1, label %bb6
+
+bb1:                                              ; preds = %entry
+  unreachable
+
+bb6:                                              ; preds = %entry
+  %tmp = zext i32 %Length to i64                  ; <i64> [#uses=1]
+  br label %bb8
+
+bb7:                                              ; preds = %bb8
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %bb8
+
+bb8:                                              ; preds = %bb7, %bb6
+  %indvar = phi i64 [ %indvar.next, %bb7 ], [ 0, %bb6 ] ; <i64> [#uses=2]
+  %exitcond = icmp ne i64 %indvar, %tmp           ; <i1> [#uses=1]
+  br i1 %exitcond, label %bb7, label %return
+
+return:                                           ; preds = %bb8
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100707_2.ll b/final/test/Isl/CodeGen/20100707_2.ll
new file mode 100644
index 0000000..fb1e85b
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100707_2.ll
@@ -0,0 +1,115 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@win193 = external global [4 x [36 x double]], align 32 ; <[4 x [36 x double]]*> [#uses=3]
+@sb_sample = external global [2 x [2 x [18 x [32 x double]]]], align 32 ; <[2 x [2 x [18 x [32 x double]]]]*> [#uses=2]
+
+define void @mdct_sub48() nounwind {
+entry:
+  br i1 undef, label %bb, label %bb54
+
+bb:                                               ; preds = %entry
+  br label %bb54
+
+bb3:                                              ; preds = %bb50
+  br label %bb8
+
+bb4:                                              ; preds = %bb8
+  br label %bb8
+
+bb8:                                              ; preds = %bb4, %bb3
+  br i1 undef, label %bb4, label %bb9
+
+bb9:                                              ; preds = %bb8
+  br label %bb48
+
+bb25:                                             ; preds = %bb48
+  br i1 false, label %bb26, label %bb27
+
+bb26:                                             ; preds = %bb48, %bb25
+  br label %bb37
+
+bb27:                                             ; preds = %bb25
+  br i1 undef, label %bb32, label %bb35
+
+bb32:                                             ; preds = %bb27
+  br label %bb37
+
+bb34:                                             ; preds = %bb35
+  %0 = getelementptr inbounds [36 x double]* undef, i64 0, i64 0 ; <double*> [#uses=0]
+  %1 = getelementptr inbounds [18 x [32 x double]]* undef, i64 0, i64 0 ; <[32 x double]*> [#uses=1]
+  %2 = getelementptr inbounds [32 x double]* %1, i64 0, i64 0 ; <double*> [#uses=0]
+  %3 = getelementptr inbounds [36 x double]* undef, i64 0, i64 0 ; <double*> [#uses=0]
+  %4 = sub nsw i32 17, %k.4                       ; <i32> [#uses=1]
+  %5 = getelementptr inbounds [2 x [2 x [18 x [32 x double]]]]* @sb_sample, i64 0, i64 0 ; <[2 x [18 x [32 x double]]]*> [#uses=1]
+  %6 = getelementptr inbounds [2 x [18 x [32 x double]]]* %5, i64 0, i64 0 ; <[18 x [32 x double]]*> [#uses=1]
+  %7 = sext i32 %4 to i64                         ; <i64> [#uses=1]
+  %8 = getelementptr inbounds [18 x [32 x double]]* %6, i64 0, i64 %7 ; <[32 x double]*> [#uses=1]
+  %9 = getelementptr inbounds [32 x double]* %8, i64 0, i64 0 ; <double*> [#uses=1]
+  %10 = load double* %9, align 8                  ; <double> [#uses=0]
+  %11 = fsub double 0.000000e+00, undef           ; <double> [#uses=1]
+  %12 = getelementptr inbounds double* getelementptr inbounds ([4 x [36 x double]]* @win193, i64 0, i64 2, i64 4), i64 0 ; <double*> [#uses=1]
+  store double %11, double* %12, align 8
+  %13 = add nsw i32 %k.4, 9                       ; <i32> [#uses=1]
+  %14 = add nsw i32 %k.4, 18                      ; <i32> [#uses=1]
+  %15 = getelementptr inbounds [4 x [36 x double]]* @win193, i64 0, i64 0 ; <[36 x double]*> [#uses=1]
+  %16 = sext i32 %14 to i64                       ; <i64> [#uses=1]
+  %17 = getelementptr inbounds [36 x double]* %15, i64 0, i64 %16 ; <double*> [#uses=1]
+  %18 = load double* %17, align 8                 ; <double> [#uses=0]
+  %19 = sext i32 %k.4 to i64                      ; <i64> [#uses=1]
+  %20 = getelementptr inbounds [18 x [32 x double]]* undef, i64 0, i64 %19 ; <[32 x double]*> [#uses=1]
+  %21 = sext i32 %band.2 to i64                   ; <i64> [#uses=1]
+  %22 = getelementptr inbounds [32 x double]* %20, i64 0, i64 %21 ; <double*> [#uses=1]
+  %23 = load double* %22, align 8                 ; <double> [#uses=0]
+  %24 = sext i32 %39 to i64                       ; <i64> [#uses=1]
+  %25 = getelementptr inbounds [4 x [36 x double]]* @win193, i64 0, i64 %24 ; <[36 x double]*> [#uses=1]
+  %26 = getelementptr inbounds [36 x double]* %25, i64 0, i64 0 ; <double*> [#uses=1]
+  %27 = load double* %26, align 8                 ; <double> [#uses=0]
+  %28 = sub nsw i32 17, %k.4                      ; <i32> [#uses=1]
+  %29 = getelementptr inbounds [2 x [2 x [18 x [32 x double]]]]* @sb_sample, i64 0, i64 0 ; <[2 x [18 x [32 x double]]]*> [#uses=1]
+  %30 = getelementptr inbounds [2 x [18 x [32 x double]]]* %29, i64 0, i64 0 ; <[18 x [32 x double]]*> [#uses=1]
+  %31 = sext i32 %28 to i64                       ; <i64> [#uses=1]
+  %32 = getelementptr inbounds [18 x [32 x double]]* %30, i64 0, i64 %31 ; <[32 x double]*> [#uses=1]
+  %33 = getelementptr inbounds [32 x double]* %32, i64 0, i64 0 ; <double*> [#uses=1]
+  %34 = load double* %33, align 8                 ; <double> [#uses=0]
+  %35 = sext i32 %13 to i64                       ; <i64> [#uses=1]
+  %36 = getelementptr inbounds double* getelementptr inbounds ([4 x [36 x double]]* @win193, i64 0, i64 2, i64 4), i64 %35 ; <double*> [#uses=1]
+  store double 0.000000e+00, double* %36, align 8
+  %37 = sub nsw i32 %k.4, 1                       ; <i32> [#uses=1]
+  br label %bb35
+
+bb35:                                             ; preds = %bb34, %bb27
+  %k.4 = phi i32 [ %37, %bb34 ], [ 8, %bb27 ]     ; <i32> [#uses=6]
+  br i1 undef, label %bb34, label %bb36
+
+bb36:                                             ; preds = %bb35
+  unreachable
+
+bb37:                                             ; preds = %bb32, %bb26
+  %38 = add nsw i32 %band.2, 1                    ; <i32> [#uses=1]
+  br label %bb48
+
+bb48:                                             ; preds = %bb37, %bb9
+  %band.2 = phi i32 [ %38, %bb37 ], [ 0, %bb9 ]   ; <i32> [#uses=2]
+  %39 = load i32* null, align 8                   ; <i32> [#uses=1]
+  br i1 undef, label %bb26, label %bb25
+
+bb50:                                             ; preds = %bb54
+  br i1 undef, label %bb3, label %bb51
+
+bb51:                                             ; preds = %bb50
+  br i1 undef, label %bb52, label %bb53
+
+bb52:                                             ; preds = %bb51
+  unreachable
+
+bb53:                                             ; preds = %bb51
+  br label %bb54
+
+bb54:                                             ; preds = %bb53, %bb, %entry
+  br i1 undef, label %bb50, label %return
+
+return:                                           ; preds = %bb54
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100708.ll b/final/test/Isl/CodeGen/20100708.ll
new file mode 100644
index 0000000..3d660e5
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100708.ll
@@ -0,0 +1,18 @@
+; RUN: opt %loadPolly -polly-detect < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define fastcc void @execute() nounwind {
+entry:
+  br i1 undef, label %check_stack.exit456.thread, label %bb.i451.preheader
+
+bb.i451.preheader:                                ; preds = %bb116
+  br label %bb.i451
+
+bb.i451:                                          ; preds = %bb.i451, %bb.i451.preheader
+  br label %bb.i451
+
+check_stack.exit456.thread:                       ; preds = %bb116
+  unreachable
+
+}
diff --git a/final/test/Isl/CodeGen/20100708_2.ll b/final/test/Isl/CodeGen/20100708_2.ll
new file mode 100644
index 0000000..9b758f1
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100708_2.ll
@@ -0,0 +1,28 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define void @init_array() nounwind {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb4, %bb
+  br i1 undef, label %bb2, label %bb5
+
+bb2:                                              ; preds = %bb3, %bb1
+  %indvar = phi i64 [ %indvar.next, %bb3 ], [ 0, %bb1 ] ; <i64> [#uses=1]
+  %tmp3 = trunc i64 undef to i32                  ; <i32> [#uses=1]
+  br i1 false, label %bb3, label %bb4
+
+bb3:                                              ; preds = %bb2
+  %tmp = srem i32 %tmp3, 1024                     ; <i32> [#uses=0]
+  store double undef, double* undef
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %bb2
+
+bb4:                                              ; preds = %bb2
+  br label %bb1
+
+bb5:                                              ; preds = %bb1
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100713.ll b/final/test/Isl/CodeGen/20100713.ll
new file mode 100644
index 0000000..54714fd
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100713.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @fft_float(i32 %NumSamples) nounwind {
+  br label %bb18
+
+bb18:                                             ; preds = %bb17
+  br i1 false, label %bb19, label %bb22
+
+bb19:                                             ; preds = %bb18
+  %a = uitofp i32 %NumSamples to double           ; <double> [#uses=1]
+  br label %bb21
+
+bb20:                                             ; preds = %bb21
+  %1 = load float* undef, align 4                 ; <float> [#uses=0]
+  %2 = fpext float undef to double                ; <double> [#uses=1]
+  %3 = fdiv double %2, %a ; <double> [#uses=0]
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %bb21
+
+bb21:                                             ; preds = %bb20, %bb19
+  %indvar = phi i64 [ %indvar.next, %bb20 ], [ 0, %bb19 ] ; <i64> [#uses=1]
+  br i1 false, label %bb20, label %bb22.loopexit
+
+bb22.loopexit:                                    ; preds = %bb21
+  br label %bb22
+
+bb22:                                             ; preds = %bb22.loopexit, %bb18
+  br label %return
+
+return:                                           ; preds = %bb22
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100713_2.ll b/final/test/Isl/CodeGen/20100713_2.ll
new file mode 100644
index 0000000..5d59e85
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100713_2.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define hidden void @luaD_callhook() nounwind {
+entry:
+  br i1 undef, label %bb, label %return
+
+bb:                                               ; preds = %entry
+  br i1 undef, label %bb1, label %return
+
+bb1:                                              ; preds = %bb
+  %0 = sub nsw i64 undef, undef                   ; <i64> [#uses=1]
+  br i1 false, label %bb2, label %bb3
+
+bb2:                                              ; preds = %bb1
+  br label %bb4
+
+bb3:                                              ; preds = %bb1
+  br label %bb4
+
+bb4:                                              ; preds = %bb3, %bb2
+  br i1 undef, label %bb5, label %bb6
+
+bb5:                                              ; preds = %bb4
+  unreachable
+
+bb6:                                              ; preds = %bb4
+  %1 = getelementptr inbounds i8* undef, i64 %0   ; <i8*> [#uses=0]
+  ret void
+
+return:                                           ; preds = %bb, %entry
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100717.ll b/final/test/Isl/CodeGen/20100717.ll
new file mode 100644
index 0000000..5652ff2
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100717.ll
@@ -0,0 +1,39 @@
+; RUN: opt %loadPolly  -polly-codegen-isl -disable-output < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @matrixTranspose(double** %A) nounwind {
+entry:
+  br label %bb4
+
+bb:                                               ; preds = %bb4
+  %0 = add nsw i32 %i.0, 1                        ; <i32> [#uses=1]
+  br label %bb2
+
+bb1:                                              ; preds = %bb2
+  %1 = getelementptr inbounds double** %A, i64 0  ; <double**> [#uses=0]
+  %2 = getelementptr inbounds double** %A, i64 0  ; <double**> [#uses=0]
+  %3 = getelementptr inbounds double** %A, i64 0  ; <double**> [#uses=0]
+  %4 = sext i32 %j.0 to i64                       ; <i64> [#uses=1]
+  %5 = getelementptr inbounds double** %A, i64 %4 ; <double**> [#uses=1]
+  %6 = load double** %5, align 8                  ; <double*> [#uses=0]
+  %7 = add nsw i32 %j.0, 1                        ; <i32> [#uses=1]
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb
+  %j.0 = phi i32 [ %0, %bb ], [ %7, %bb1 ]        ; <i32> [#uses=3]
+  %8 = icmp sle i32 %j.0, 50                      ; <i1> [#uses=1]
+  br i1 %8, label %bb1, label %bb3
+
+bb3:                                              ; preds = %bb2
+  %9 = add nsw i32 %i.0, 1                        ; <i32> [#uses=1]
+  br label %bb4
+
+bb4:                                              ; preds = %bb3, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %9, %bb3 ]      ; <i32> [#uses=3]
+  %10 = icmp sle i32 %i.0, 50                     ; <i1> [#uses=1]
+  br i1 %10, label %bb, label %return
+
+return:                                           ; preds = %bb4
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100718-DomInfo-2.ll b/final/test/Isl/CodeGen/20100718-DomInfo-2.ll
new file mode 100644
index 0000000..a51d3e3
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100718-DomInfo-2.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-codegen-isl -verify-dom-info -disable-output < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @getNonAffNeighbour() nounwind {
+entry:
+  br i1 undef, label %bb, label %bb6
+
+bb:                                               ; preds = %entry
+  br i1 false, label %bb1, label %bb2
+
+bb1:                                              ; preds = %bb
+  br label %bb16
+
+bb2:                                              ; preds = %bb
+  br i1 false, label %bb3, label %bb4
+
+bb3:                                              ; preds = %bb2
+  br label %bb16
+
+bb4:                                              ; preds = %bb2
+  br label %bb16
+
+bb6:                                              ; preds = %entry
+  br i1 false, label %bb7, label %bb9
+
+bb7:                                              ; preds = %bb6
+  br label %bb16
+
+bb9:                                              ; preds = %bb6
+  br label %bb16
+
+bb16:                                             ; preds = %bb9, %bb7, %bb4, %bb3, %bb1
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100718-DomInfo.ll b/final/test/Isl/CodeGen/20100718-DomInfo.ll
new file mode 100644
index 0000000..afc9db0
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100718-DomInfo.ll
@@ -0,0 +1,28 @@
+; RUN: opt %loadPolly -polly-codegen-isl -verify-dom-info -disable-output < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @intrapred_luma_16x16(i32 %predmode) nounwind {
+entry:
+  switch i32 %predmode, label %bb81 [
+    i32 0, label %bb25
+    i32 1, label %bb26
+  ]
+
+bb23:                                             ; preds = %bb25
+  %indvar.next95 = add i64 %indvar94, 1           ; <i64> [#uses=1]
+  br label %bb25
+
+bb25:                                             ; preds = %bb23, %entry
+  %indvar94 = phi i64 [ %indvar.next95, %bb23 ], [ 0, %entry ] ; <i64> [#uses=1]
+  br i1 false, label %bb23, label %return
+
+bb26:                                             ; preds = %entry
+  ret void
+
+bb81:                                             ; preds = %entry
+  ret void
+
+return:                                           ; preds = %bb25
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20100720-MultipleConditions.ll b/final/test/Isl/CodeGen/20100720-MultipleConditions.ll
new file mode 100644
index 0000000..ba28c32
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100720-MultipleConditions.ll
@@ -0,0 +1,96 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s
+
+;int bar1();
+;int bar2();
+;int bar3();
+;int k;
+;#define N 100
+;int A[N];
+;
+;int main() {
+;  int i, j, z;
+;
+;  __sync_synchronize();
+;  for (i = 0; i < N; i++) {
+;    if (i < 50)
+;      A[i] = 8;
+;    if (i < 4)
+;      A[i] = 9;
+;    if (i < 3)
+;      A[i] = 10;
+;  }
+;  __sync_synchronize();
+;
+;  return A[z];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [100 x i32] zeroinitializer, align 16 ; <[100 x i32]*> [#uses=2]
+@k = common global i32 0, align 4                 ; <i32*> [#uses=0]
+
+define i32 @main() nounwind {
+; <label>:0
+  fence seq_cst
+  br label %1
+
+; <label>:1                                       ; preds = %12, %0
+  %indvar = phi i64 [ %indvar.next, %12 ], [ 0, %0 ] ; <i64> [#uses=4]
+  %scevgep = getelementptr [100 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=3]
+  %i.0 = trunc i64 %indvar to i32                 ; <i32> [#uses=3]
+  %exitcond = icmp ne i64 %indvar, 100            ; <i1> [#uses=1]
+  br i1 %exitcond, label %2, label %13
+
+; <label>:2                                       ; preds = %1
+  %3 = icmp slt i32 %i.0, 50                      ; <i1> [#uses=1]
+  br i1 %3, label %4, label %5
+
+; <label>:4                                       ; preds = %2
+  store i32 8, i32* %scevgep
+  br label %5
+
+; <label>:5                                       ; preds = %4, %2
+  %6 = icmp slt i32 %i.0, 4                       ; <i1> [#uses=1]
+  br i1 %6, label %7, label %8
+
+; <label>:7                                       ; preds = %5
+  store i32 9, i32* %scevgep
+  br label %8
+
+; <label>:8                                       ; preds = %7, %5
+  %9 = icmp slt i32 %i.0, 3                       ; <i1> [#uses=1]
+  br i1 %9, label %10, label %11
+
+; <label>:10                                      ; preds = %8
+  store i32 10, i32* %scevgep
+  br label %11
+
+; <label>:11                                      ; preds = %10, %8
+  br label %12
+
+; <label>:12                                      ; preds = %11
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %1
+
+; <label>:13                                      ; preds = %1
+  fence seq_cst
+  %14 = sext i32 undef to i64                     ; <i64> [#uses=1]
+  %15 = getelementptr inbounds i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0), i64 %14 ; <i32*> [#uses=1]
+  %16 = load i32* %15                             ; <i32> [#uses=1]
+  ret i32 %16
+}
+
+; CHECK: for (c2=0;c2<=2;c2++) {
+; CHECK:     S0(c2);
+; CHECK:       S1(c2);
+; CHECK:         S2(c2);
+; CHECK: }
+; CHECK: S0(3);
+; CHECK: S1(3);
+; CHECK: for (c2=4;c2<=49;c2++) {
+; CHECK:     S0(c2);
+; CHECK: }
+; CHECK: S0: Stmt_4
+; CHECK: S1: Stmt_7
+; CHECK: S2: Stmt_10
diff --git a/final/test/Isl/CodeGen/20100809-IndependentBlock.ll b/final/test/Isl/CodeGen/20100809-IndependentBlock.ll
new file mode 100644
index 0000000..2cafc00
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100809-IndependentBlock.ll
@@ -0,0 +1,31 @@
+; RUN: opt %loadPolly -polly-codegen-isl -disable-output < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define void @cfft2([2 x float]* %x) nounwind {
+entry:
+  %d.1.reg2mem = alloca [2 x float]*              ; <[2 x float]**> [#uses=3]
+  br i1 undef, label %bb2, label %bb34
+
+bb2:                                              ; preds = %bb34, %entry
+  ret void
+
+bb20:                                             ; preds = %bb34
+  store [2 x float]* undef, [2 x float]** %d.1.reg2mem
+  br i1 false, label %bb21, label %bb23
+
+bb21:                                             ; preds = %bb20
+  %0 = getelementptr inbounds [2 x float]* %x, i64 undef ; <[2 x float]*> [#uses=1]
+  store [2 x float]* %0, [2 x float]** %d.1.reg2mem
+  br label %bb23
+
+bb23:                                             ; preds = %bb21, %bb20
+  %d.1.reload = load [2 x float]** %d.1.reg2mem   ; <[2 x float]*> [#uses=1]
+  br i1 undef, label %bb29, label %bb34
+
+bb29:                                             ; preds = %bb23
+  %1 = getelementptr inbounds [2 x float]* %d.1.reload, i64 undef ; <[2 x float]*> [#uses=0]
+  br label %bb34
+
+bb34:                                             ; preds = %bb29, %bb23, %entry
+  br i1 undef, label %bb20, label %bb2
+}
diff --git a/final/test/Isl/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll b/final/test/Isl/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll
new file mode 100644
index 0000000..e975995
--- /dev/null
+++ b/final/test/Isl/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll
@@ -0,0 +1,30 @@
+; RUN: opt %loadPolly -polly-codegen-isl -disable-output < %s
+target datalayout =
+"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.inc ], [ 0, %entry ] ; <i64> [#uses=2]
+  %exitcond = icmp ne i64 %indvar1, 1024          ; <i1> [#uses=1]
+  br label %a
+
+a:                                                ; preds = %for.cond
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %a
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %a
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc07, %for.end
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20101030-Overflow.ll b/final/test/Isl/CodeGen/20101030-Overflow.ll
new file mode 100644
index 0000000..9303c26
--- /dev/null
+++ b/final/test/Isl/CodeGen/20101030-Overflow.ll
@@ -0,0 +1,22 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @compdecomp() nounwind {
+entry:
+  %max = alloca i64
+  %i = load i64* undef
+  br label %bb37
+
+bb37:                                             ; preds = %bb36, %bb28
+  %tmp = icmp ugt i64 %i, 0
+  br i1 %tmp, label %bb38, label %bb39
+
+bb38:                                             ; preds = %bb37
+  store i64 %i, i64* %max
+  br label %bb39
+
+bb39:                                             ; preds = %bb38, %bb37
+  unreachable
+
+}
diff --git a/final/test/Isl/CodeGen/20101103-Overflow3.ll b/final/test/Isl/CodeGen/20101103-Overflow3.ll
new file mode 100644
index 0000000..11661b0
--- /dev/null
+++ b/final/test/Isl/CodeGen/20101103-Overflow3.ll
@@ -0,0 +1,24 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define void @Reflection_coefficients(i16* %r) nounwind {
+bb20:
+  %indvar3.lcssa20.reload = load i64* undef
+  %tmp = mul i64 %indvar3.lcssa20.reload, -1
+  %tmp5 = add i64 %tmp, 8
+  br label %bb22
+
+bb21:                                             ; preds = %bb22
+  %r_addr.1.moved.to.bb21 = getelementptr i16* %r, i64 0
+  store i16 0, i16* %r_addr.1.moved.to.bb21, align 2
+  %indvar.next = add i64 %indvar, 1
+  br label %bb22
+
+bb22:                                             ; preds = %bb21, %bb20
+  %indvar = phi i64 [ %indvar.next, %bb21 ], [ 0, %bb20 ]
+  %exitcond = icmp ne i64 %indvar, %tmp5
+  br i1 %exitcond, label %bb21, label %return
+
+return:                                           ; preds = %bb22
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20101103-signmissmatch.ll b/final/test/Isl/CodeGen/20101103-signmissmatch.ll
new file mode 100644
index 0000000..48bb30d
--- /dev/null
+++ b/final/test/Isl/CodeGen/20101103-signmissmatch.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define void @CleanNet() nounwind {
+entry:
+  %firstVia.0.reg2mem = alloca i64
+  br label %bb7
+
+bb7:                                              ; preds = %bb7, %entry
+  br i1 undef, label %bb7, label %bb8
+
+bb8:                                              ; preds = %bb7
+  %indvar5.lcssa.reload = load i64* undef
+  %tmp17 = mul i64 %indvar5.lcssa.reload, -1
+  %tmp18 = add i64 0, %tmp17
+  br label %bb18
+
+bb13:                                             ; preds = %bb18
+  %0 = icmp ult i64 %i.1, 0
+  br i1 %0, label %bb14, label %bb17
+
+bb14:                                             ; preds = %bb13
+  store i64 %i.1, i64* %firstVia.0.reg2mem
+  br label %bb17
+
+bb17:                                             ; preds = %bb14, %bb13
+  %indvar.next16 = add i64 %indvar15, 1
+  br label %bb18
+
+bb18:                                             ; preds = %bb17, %bb8
+  %indvar15 = phi i64 [ %indvar.next16, %bb17 ], [ 0, %bb8 ]
+  %i.1 = add i64 %tmp18, %indvar15
+  br i1 undef, label %bb13, label %bb25
+
+bb25:                                             ; preds = %bb18
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20110226-Ignore-Dead-Code.ll b/final/test/Isl/CodeGen/20110226-Ignore-Dead-Code.ll
new file mode 100644
index 0000000..f890a85
--- /dev/null
+++ b/final/test/Isl/CodeGen/20110226-Ignore-Dead-Code.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() nounwind {
+.split:
+  br label %0
+
+.loopexit.loopexit:                               ; preds = %.preheader.us
+  br label %.loopexit.simregexit
+
+.loopexit.simregexit:                             ; preds = %.loopexit.loopexit, %._crit_edge
+  br label %.loopexit
+
+.loopexit:                                        ; preds = %.loopexit.simregexit
+  %indvar.next16 = add i64 %indvar15, 1
+  %exitcond53 = icmp eq i64 %indvar.next16, 2048
+  br i1 %exitcond53, label %2, label %0
+
+; <label>:0                                       ; preds = %.loopexit, %.split
+  %indvar15 = phi i64 [ 0, %.split ], [ %indvar.next16, %.loopexit ]
+  br label %.simregentry
+
+.simregentry:                                     ; preds = %0
+  %indvar15.ph = phi i64 [ %indvar15, %0 ]
+  %tmp67 = add i64 %indvar15, 1
+  %i.06 = trunc i64 %tmp67 to i32
+  %tmp25 = add i64 undef, 1
+  %1 = icmp slt i32 %i.06, 2048
+  br i1 %1, label %.lr.ph.preheader, label %._crit_edge.simregexit
+
+.lr.ph.preheader:                                 ; preds = %.simregentry
+  br label %.lr.ph
+
+.lr.ph:                                           ; preds = %.lr.ph, %.lr.ph.preheader
+  %indvar33 = phi i64 [ %indvar.next34, %.lr.ph ], [ 0, %.lr.ph.preheader ]
+  %indvar.next34 = add i64 %indvar33, 1
+  %exitcond40 = icmp eq i64 %indvar.next34, 0
+  br i1 %exitcond40, label %._crit_edge.loopexit, label %.lr.ph
+
+._crit_edge.loopexit:                             ; preds = %.lr.ph
+  br label %._crit_edge.simregexit
+
+._crit_edge.simregexit:                           ; preds = %.simregentry, %._crit_edge.loopexit
+  br label %._crit_edge
+
+._crit_edge:                                      ; preds = %._crit_edge.simregexit
+  br i1 false, label %.loopexit.simregexit, label %.preheader.us.preheader
+
+.preheader.us.preheader:                          ; preds = %._crit_edge
+  br label %.preheader.us
+
+.preheader.us:                                    ; preds = %.preheader.us, %.preheader.us.preheader
+  %exitcond26.old = icmp eq i64 undef, %tmp25
+  br i1 false, label %.loopexit.loopexit, label %.preheader.us
+
+; <label>:2                                       ; preds = %.loopexit
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20110226-PHI-Node-removed.ll b/final/test/Isl/CodeGen/20110226-PHI-Node-removed.ll
new file mode 100644
index 0000000..a786530
--- /dev/null
+++ b/final/test/Isl/CodeGen/20110226-PHI-Node-removed.ll
@@ -0,0 +1,30 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() nounwind {
+.split:
+  br label %0
+
+.loopexit:                                        ; preds = %.lr.ph, %0
+  %indvar.next16 = add i64 %indvar15, 1
+  %exitcond53 = icmp eq i64 %indvar.next16, 2048
+  br i1 %exitcond53, label %1, label %0
+
+; <label>:0                                       ; preds = %.loopexit, %.split
+  %indvar15 = phi i64 [ 0, %.split ], [ %indvar.next16, %.loopexit ]
+  %tmp59 = sub i64 2046, %indvar15
+  %tmp38 = and i64 %tmp59, 4294967295
+  %tmp39 = add i64 %tmp38, 1
+  br i1 false, label %.lr.ph, label %.loopexit
+
+.lr.ph:                                           ; preds = %.lr.ph, %0
+  %indvar33 = phi i64 [ %indvar.next34, %.lr.ph ], [ 0, %0 ]
+  %indvar.next34 = add i64 %indvar33, 1
+  %exitcond40 = icmp eq i64 %indvar.next34, %tmp39
+  br i1 %exitcond40, label %.loopexit, label %.lr.ph
+
+; <label>:1                                       ; preds = %.loopexit
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20110312-Fail-without-basicaa.ll b/final/test/Isl/CodeGen/20110312-Fail-without-basicaa.ll
new file mode 100644
index 0000000..d1936ff
--- /dev/null
+++ b/final/test/Isl/CodeGen/20110312-Fail-without-basicaa.ll
@@ -0,0 +1,27 @@
+; This should be run without alias analysis enabled.
+;RUN: opt %loadPolly -polly-independent < %s
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %t.02.reg2mem = alloca float
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  store float 0.000000e+00, float* %t.02.reg2mem
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry.split
+  %j.01 = phi i32 [ 0, %entry.split ], [ %inc1, %for.body ]
+  %t.02.reload = load float* %t.02.reg2mem
+  %inc = fadd float %t.02.reload, 1.000000e+00
+  %inc1 = add nsw i32 %j.01, 1
+  %exitcond = icmp eq i32 %inc1, 5000001
+  store float %inc, float* %t.02.reg2mem
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  %conv = fptosi float %inc to i32
+  ret i32 %conv
+}
diff --git a/final/test/Isl/CodeGen/20120316-InvalidCast.ll b/final/test/Isl/CodeGen/20120316-InvalidCast.ll
new file mode 100644
index 0000000..e3f09b6
--- /dev/null
+++ b/final/test/Isl/CodeGen/20120316-InvalidCast.ll
@@ -0,0 +1,20 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+
+target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32"
+target triple = "hexagon-unknown-linux-gnu"
+
+define void @fixup_gotos(i32* %A, i32* %data) nounwind {
+entry:
+  br label %if
+
+if:
+  %cond = icmp eq i32* %A, null
+  br i1 %cond, label %last, label %then
+
+then:
+  store i32 1, i32* %data, align 4
+  br label %last
+
+last:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/20120403-RHS-type-mismatch.ll b/final/test/Isl/CodeGen/20120403-RHS-type-mismatch.ll
new file mode 100644
index 0000000..fd797ca
--- /dev/null
+++ b/final/test/Isl/CodeGen/20120403-RHS-type-mismatch.ll
@@ -0,0 +1,27 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+
+; We just check that this compilation does not crash.
+
+target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32"
+target triple = "hexagon-unknown-linux-gnu"
+
+define void @init() nounwind {
+entry:
+  %hi.129.reg2mem = alloca i64
+  br label %for.body
+
+for.cond5.preheader:                              ; preds = %for.body
+  br label %for.body7
+
+for.body:                                         ; preds = %for.body, %entry
+  br i1 undef, label %for.body, label %for.cond5.preheader
+
+for.body7:                                        ; preds = %for.body7, %for.cond5.preheader
+  %i.128 = phi i64 [ 0, %for.cond5.preheader ], [ %inc07, %for.body7 ]
+  %inc07 = add nsw i64 %i.128, 1
+  store i64 undef, i64* %hi.129.reg2mem
+  br i1 false, label %for.body7, label %for.end18
+
+for.end18:                                        ; preds = %for.body7
+  unreachable
+}
diff --git a/final/test/Isl/CodeGen/20130211-getNumberOfIterations.ll b/final/test/Isl/CodeGen/20130211-getNumberOfIterations.ll
new file mode 100644
index 0000000..ce2a984
--- /dev/null
+++ b/final/test/Isl/CodeGen/20130211-getNumberOfIterations.ll
@@ -0,0 +1,29 @@
+; RUN: opt %loadPolly -polly-codegen-isl -polly-vectorizer=polly < %s
+; RUN: opt %loadPolly -polly-codegen-isl -polly-vectorizer=bb < %s
+
+; This test case checks that the polly vectorizer does not crash when
+; calculating the number of iterations.
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@b = external global [2048 x i64], align 16
+
+define void @foo(i64 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %indvar = phi i64 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i64 %indvar, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds [2048 x i64]* @b, i64 0, i64 %indvar
+  store i64 1, i64* %arrayidx
+  %inc = add nsw i64 %indvar, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
diff --git a/final/test/Isl/CodeGen/20130221.ll b/final/test/Isl/CodeGen/20130221.ll
new file mode 100644
index 0000000..22a079c
--- /dev/null
+++ b/final/test/Isl/CodeGen/20130221.ll
@@ -0,0 +1,21 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @list_sequence(i32* %A) {
+entry:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %for.body ]
+  %i.inc = add nsw i32 %i, 1
+  %cmp5 = icmp slt i32 %i.inc, 2
+  br i1 %cmp5, label %for.body, label %for.next
+
+for.next:
+  store i32 %i.inc, i32* %A
+  br label %for.end
+
+for.end:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll b/final/test/Isl/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll
new file mode 100644
index 0000000..f3b3551
--- /dev/null
+++ b/final/test/Isl/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll
@@ -0,0 +1,71 @@
+; This test checks that we do not accidently mutate the debug info when
+; inserting loop parallel metadata.
+; RUN: opt %loadPolly < %s  -S -polly -polly-codegen-isl -polly-ast-detect-parallel | FileCheck %s
+; CHECK-NOT: !7 = !{!7}
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global i32* null, align 8
+
+; Function Attrs: nounwind uwtable
+define void @foo() {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !9, metadata !19), !dbg !20
+  %0 = load i32** @A, align 8, !dbg !21, !tbaa !23
+  br label %for.body, !dbg !27
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %arrayidx = getelementptr inbounds i32* %0, i64 %indvars.iv, !dbg !21
+  %1 = load i32* %arrayidx, align 4, !dbg !21, !tbaa !30
+  %add = add nsw i32 %1, 1, !dbg !21
+  store i32 %add, i32* %arrayidx, align 4, !dbg !21, !tbaa !30
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !27
+  %exitcond = icmp eq i64 %indvars.iv, 1, !dbg !27
+  br i1 %exitcond, label %for.end, label %for.body, !dbg !27
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !32
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
+
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!15, !16}
+!llvm.ident = !{!17}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 \001\00\000\00\001", !1, !2, !2, !3, !12, !2} ; [ DW_TAG_compile_unit ] [/local/mnt/workspace/build/tip-Release/t2.c] [DW_LANG_C99]
+!1 = !{!"t2.c", !"/local/mnt/workspace/build/tip-Release"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00foo\00foo\00\003\000\001\000\000\000\001\003", !1, !5, !6, null, void ()* @foo, null, null, !8} ; [ DW_TAG_subprogram ] [line 3] [def] [foo]
+!5 = !{!"0x29", !1}    ; [ DW_TAG_file_type ] [/local/mnt/workspace/build/tip-Release/t2.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{null}
+!8 = !{!9}
+!9 = !{!"0x100\00i\004\000", !10, !5, !11} ; [ DW_TAG_auto_variable ] [i] [line 4]
+!10 = !{!"0xb\004\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [/local/mnt/workspace/build/tip-Release/t2.c]
+!11 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!12 = !{!13}
+!13 = !{!"0x34\00A\00A\00\002\000\001", null, !5, !14, i32** @A, null} ; [ DW_TAG_variable ] [A] [line 2] [def]
+!14 = !{!"0xf\00\000\0064\0064\000\000", null, null, !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
+!15 = !{i32 2, !"Dwarf Version", i32 4}
+!16 = !{i32 2, !"Debug Info Version", i32 2}
+!17 = !{!"clang version 3.6.0 "}
+!18 = !{i32 0}
+!19 = !{!"0x102"}               ; [ DW_TAG_expression ]
+!20 = !MDLocation(line: 4, column: 12, scope: !10)
+!21 = !MDLocation(line: 5, column: 5, scope: !22)
+!22 = !{!"0xb\004\003\001", !1, !10} ; [ DW_TAG_lexical_block ] [/local/mnt/workspace/build/tip-Release/t2.c]
+!23 = !{!24, !24, i64 0}
+!24 = !{!"any pointer", !25, i64 0}
+!25 = !{!"omnipotent char", !26, i64 0}
+!26 = !{!"Simple C/C++ TBAA"}
+!27 = !MDLocation(line: 4, column: 3, scope: !28)
+!28 = !{!"0xb\002", !1, !29} ; [ DW_TAG_lexical_block ] [/local/mnt/workspace/build/tip-Release/t2.c]
+!29 = !{!"0xb\001", !1, !22} ; [ DW_TAG_lexical_block ] [/local/mnt/workspace/build/tip-Release/t2.c]
+!30 = !{!31, !31, i64 0}
+!31 = !{!"int", !25, i64 0}
+!32 = !MDLocation(line: 6, column: 1, scope: !4)
diff --git a/final/test/Isl/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll b/final/test/Isl/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll
new file mode 100644
index 0000000..a0afac3
--- /dev/null
+++ b/final/test/Isl/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll
@@ -0,0 +1,64 @@
+; RUN: opt %loadPolly -polly-codegen-isl -polly-ast-detect-parallel -S < %s | FileCheck %s
+;
+; Check that we mark multiple parallel loops correctly including the memory instructions.
+;
+; CHECK-DAG:  %polly.loop_cond[[COuter:[0-9]*]] = icmp sle i64 %polly.indvar{{[0-9]*}}, 1022
+; CHECK-DAG:  br i1 %polly.loop_cond[[COuter]], label %polly.loop_header{{[0-9]*}}, label %polly.loop_exit{{[0-9]*}}, !llvm.loop ![[IDOuter:[0-9]*]]
+;
+; CHECK-DAG:  %polly.loop_cond[[CInner:[0-9]*]] = icmp sle i64 %polly.indvar{{[0-9]*}}, 510
+; CHECK-DAG:  br i1 %polly.loop_cond[[CInner]], label %polly.loop_header{{[0-9]*}}, label %polly.loop_exit{{[0-9]*}}, !llvm.loop ![[IDInner:[0-9]*]]
+;
+; CHECK-DAG: store i32 %{{[a-z_0-9]*}}, i32* %{{[a-z_0-9]*}}, {{[ ._!,a-zA-Z0-9]*}}, !llvm.mem.parallel_loop_access !4
+;
+; CHECK-DAG: ![[IDOuter]] = distinct !{![[IDOuter]]}
+; CHECK-DAG: ![[IDInner]] = distinct !{![[IDInner]]}
+; CHECK-DAG: !4 = !{![[IDOuter]], ![[IDInner]]}
+;
+;    void jd(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        for (int j = 0; j < 512; j++)
+;          A[i * 512 + j] = i + j;
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc5, %entry
+  %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc5 ], [ 0, %entry ]
+  %exitcond6 = icmp ne i64 %indvars.iv3, 1024
+  br i1 %exitcond6, label %for.body, label %for.end7
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body ]
+  %exitcond = icmp ne i64 %indvars.iv, 512
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %tmp = add nsw i64 %indvars.iv3, %indvars.iv
+  %tmp7 = shl nsw i64 %indvars.iv3, 9
+  %tmp8 = add nsw i64 %tmp7, %indvars.iv
+  %arrayidx = getelementptr inbounds i32* %A, i64 %tmp8
+  %tmp9 = trunc i64 %tmp to i32
+  store i32 %tmp9, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc5
+
+for.inc5:                                         ; preds = %for.end
+  %indvars.iv.next4 = add nuw nsw i64 %indvars.iv3, 1
+  br label %for.cond
+
+for.end7:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/LoopParallelMD/single_loop_param_parallel.ll b/final/test/Isl/CodeGen/LoopParallelMD/single_loop_param_parallel.ll
new file mode 100644
index 0000000..28858c0
--- /dev/null
+++ b/final/test/Isl/CodeGen/LoopParallelMD/single_loop_param_parallel.ll
@@ -0,0 +1,87 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=SEQUENTIAL
+; RUN: opt %loadPolly -polly-codegen-isl -polly-ast-detect-parallel -S < %s | FileCheck %s -check-prefix=PARALLEL
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+; This is a trivially parallel loop. We just use it to ensure that we actually
+; emit the right information.
+;
+; for (i = 0; i < n; i++)
+;   A[i] = 1;
+;
+@A = common global [1024 x i32] zeroinitializer
+define void @test-one(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %exitcond = icmp ne i64 %i, %n
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i
+  store i32 1, i32* %scevgep
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; SEQUENTIAL: @test-one
+; SEQUENTIAL-NOT: !llvm.mem.parallel_loop_access
+; SEQUENTIAL-NOT: !llvm.loop
+
+; PARALLEL: @test-one
+; PARALLEL: store i32 1, i32* %scevgep1, {{[ ._!,a-zA-Z0-9]*}}, !llvm.mem.parallel_loop_access ![[LoopID:[0-9]*]]
+; PARALLEL:  br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit, !llvm.loop ![[LoopID]]
+
+; This loop has memory dependences that require at least a simple dependence
+; analysis to detect the parallelism.
+;
+; for (i = 0; i < n; i++)
+;   A[2 * i] = A[2 * i + 1];
+;
+define void @test-two(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %exitcond = icmp ne i64 %i, %n
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  %loadoffset1 = mul nsw i64 %i, 2
+  %loadoffset2 = add nsw i64 %loadoffset1, 1
+  %scevgepload = getelementptr [1024 x i32]* @A, i64 0, i64 %loadoffset2
+  %val = load i32* %scevgepload
+  %storeoffset = mul i64 %i, 2
+  %scevgepstore = getelementptr [1024 x i32]* @A, i64 0, i64 %storeoffset
+  store i32 %val, i32* %scevgepstore
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; SEQUENTIAL: @test-two
+; SEQUENTIAL-NOT: !llvm.mem.parallel_loop_access
+; SEQUENTIAL-NOT: !llvm.loop
+
+; PARALLEL: @test-two
+; PARALLEL: %val_p_scalar_ = load i32* %scevgep, {{[ ._!,a-zA-Z0-9]*}}, !llvm.mem.parallel_loop_access ![[LoopID:[0-9]*]]
+; PARALLEL: store i32 %val_p_scalar_, i32* %scevgep1, {{[ ._!,a-zA-Z0-9]*}}, !llvm.mem.parallel_loop_access ![[LoopID]]
+; PARALLEL:  br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit, !llvm.loop ![[LoopID]]
diff --git a/final/test/Isl/CodeGen/MemAccess/bad_alignment.ll b/final/test/Isl/CodeGen/MemAccess/bad_alignment.ll
new file mode 100644
index 0000000..aeff96a
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/bad_alignment.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -analyze 2>&1 < %s | FileCheck %s
+;
+; Check that we do not allow to access elements not accessed before because the
+; alignment information would become invalid.
+;
+; CHECK: JScop file changes the accessed memory
+;
+;    void bad_alignment(int *A) {
+;      for (int i = 0; i < 1024; i += 2)
+;        A[i] = i;
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @bad_alignment(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %cmp = icmp slt i64 %indvars.iv, 1024
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
+  %tmp = trunc i64 %indvars.iv to i32
+  store i32 %tmp, i32* %arrayidx, align 8
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/bad_alignment___%for.cond---%for.end.jscop b/final/test/Isl/CodeGen/MemAccess/bad_alignment___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..7f4fb66
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/bad_alignment___%for.cond---%for.end.jscop
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => polly.merge_new_and_old",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[1] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 511 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset.ll b/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset.ll
new file mode 100644
index 0000000..36dbf12
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset.ll
@@ -0,0 +1,43 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed -polly-codegen-isl -instnamer < %s -S | FileCheck %s
+
+;int A[100];
+;
+;int codegen_constant_offset() {
+;  for (int i = 0; i < 12; i++)
+;    A[13] = A[i] + A[i-1];
+;
+;  return 0;
+;}
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@A = common global [100 x i32] zeroinitializer, align 4
+
+define i32 @codegen_constant_offset() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %tmp1 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %tmp = add i32 %tmp1, -1
+  %arrayidx4 = getelementptr [100 x i32]* @A, i32 0, i32 %tmp
+  %arrayidx = getelementptr [100 x i32]* @A, i32 0, i32 %tmp1
+  %exitcond = icmp ne i32 %tmp1, 12
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp2 = load i32* %arrayidx, align 4
+  %tmp5 = load i32* %arrayidx4, align 4
+  %add = add nsw i32 %tmp2, %tmp5
+  store i32 %add, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 13), align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %tmp1, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+; CHECK: load i32* getelementptr inbounds ([100 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 10)
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop b/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..034183d
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop
@@ -0,0 +1,25 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[-1 + i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[13] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop.transformed b/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop.transformed
new file mode 100644
index 0000000..424137c
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop.transformed
@@ -0,0 +1,25 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[10] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[-1 + i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[13] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple.ll b/final/test/Isl/CodeGen/MemAccess/codegen_simple.ll
new file mode 100644
index 0000000..0afcff8
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple.ll
@@ -0,0 +1,43 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed -polly-codegen-isl -instnamer < %s -S | FileCheck %s
+
+;int A[100];
+;
+;int codegen_simple () {
+;  for (int i = 0; i < 12; i++)
+;    A[13] = A[i] + A[i-1];
+;
+;  return 0;
+;}
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@A = common global [100 x i32] zeroinitializer, align 4
+
+define i32 @codegen_simple() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %tmp1 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %tmp = add i32 %tmp1, -1
+  %arrayidx4 = getelementptr [100 x i32]* @A, i32 0, i32 %tmp
+  %arrayidx = getelementptr [100 x i32]* @A, i32 0, i32 %tmp1
+  %exitcond = icmp ne i32 %tmp1, 12
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp2 = load i32* %arrayidx, align 4
+  %tmp5 = load i32* %arrayidx4, align 4
+  %add = add nsw i32 %tmp2, %tmp5
+  store i32 %add, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 13), align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %tmp1, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+; CHECK: load i32* getelementptr inbounds ([100 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0)
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop b/final/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..034183d
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop
@@ -0,0 +1,25 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[-1 + i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[13] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop.transformed b/final/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop.transformed
new file mode 100644
index 0000000..320c3cb
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop.transformed
@@ -0,0 +1,25 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[0] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[-1 + i0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[13] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll b/final/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll
new file mode 100644
index 0000000..ccc01df
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll
@@ -0,0 +1,41 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed -polly-codegen-isl -instnamer < %s -S | FileCheck %s
+;
+;float A[100];
+;
+;int codegen_simple () {
+;  for (int i = 0; i < 12; i++)
+;    A[13] = A[i] + A[i-1];
+;
+;  return 0;
+;}
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+
+@A = common global [100 x float] zeroinitializer, align 4
+
+define i32 @codegen_simple() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %tmp1 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %tmp = add i32 %tmp1, -1
+  %arrayidx4 = getelementptr [100 x float]* @A, i32 0, i32 %tmp
+  %arrayidx = getelementptr [100 x float]* @A, i32 0, i32 %tmp1
+  %exitcond = icmp ne i32 %tmp1, 12
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp2 = load float* %arrayidx, align 4
+  %tmp5 = load float* %arrayidx4, align 4
+  %add = fadd float %tmp2, %tmp5
+  store float %add, float* getelementptr inbounds ([100 x float]* @A, i32 0, i32 13), align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %tmp1, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+; CHECK: load float* getelementptr inbounds ([100 x float]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0)
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple_md.ll b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md.ll
new file mode 100644
index 0000000..6d1de11
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md.ll
@@ -0,0 +1,75 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHOUTCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHOUTCONST %s
+
+;int A[1040];
+;
+;int codegen_simple_md() {
+;  for (int i = 0; i < 32; ++i)
+;    for (int j = 0; j < 32; ++j)
+;      A[32*i+j] = 100;
+;
+;  return 0;
+;}
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@A = common global [1040 x i32] zeroinitializer, align 4
+
+define i32 @codegen_simple_md() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %exitcond1 = icmp ne i32 %i.0, 32
+  br i1 %exitcond1, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 32
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %mul = shl nsw i32 %i.0, 5
+  %add = add nsw i32 %mul, %j.0
+  %arrayidx = getelementptr inbounds [1040 x i32]* @A, i32 0, i32 %add
+  store i32 100, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret i32 0
+}
+
+; WITHCONST:  %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHCONST:  %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHCONST:  %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
+; WITHCONST:  %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
+; WITHCONST:  %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
+; WITHCONST:  %[[SUM2:[._a-zA-Z0-9]+]] = add nsw i64 %[[SUM1]], 5
+; WITHCONST:  %[[ACC:[._a-zA-Z0-9]*]] = getelementptr i32* getelementptr inbounds ([1040 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM2]]
+; WITHCONST:  store i32 100, i32* %[[ACC]]
+
+; WITHOUTCONST:  %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHOUTCONST:  %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHOUTCONST:  %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
+; WITHOUTCONST:  %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
+; WITHOUTCONST:  %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
+; WITHOUTCONST:  %[[ACC:[._a-zA-Z0-9]*]] = getelementptr i32* getelementptr inbounds ([1040 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM1]]
+; WITHOUTCONST:  store i32 100, i32* %[[ACC]]
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..180c44f
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_A[32i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= 31 and i1 >= 0 and i1 <= 31 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "{ Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withconst b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withconst
new file mode 100644
index 0000000..0894776
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withconst
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_A[16i0 + 2i1 + 5] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= 31 and i1 >= 0 and i1 <= 31 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "{ Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withoutconst b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withoutconst
new file mode 100644
index 0000000..e1fa4ed
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withoutconst
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end6",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_A[16i0 + 2i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= 31 and i1 >= 0 and i1 <= 31 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "{ Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll
new file mode 100644
index 0000000..7db1e1f
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll
@@ -0,0 +1,71 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHOUTCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHOUTCONST %s
+;
+;float A[1040];
+;
+;int codegen_simple_md() {
+;  for (int i = 0; i < 32; ++i)
+;    for (int j = 0; j < 32; ++j)
+;      A[32*i+j] = 100;
+;}
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+
+@A = common global [1040 x float] zeroinitializer, align 4
+
+define void @codegen_simple_md() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %exitcond1 = icmp ne i32 %i.0, 32
+  br i1 %exitcond1, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 32
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %mul = shl nsw i32 %i.0, 5
+  %add = add nsw i32 %mul, %j.0
+  %arrayidx = getelementptr inbounds [1040 x float]* @A, i32 0, i32 %add
+  store float 100.0, float* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
+
+; WITHCONST:  %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHCONST:  %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHCONST:  %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
+; WITHCONST:  %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
+; WITHCONST:  %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
+; WITHCONST:  %[[SUM2:[._a-zA-Z0-9]+]] = add nsw i64 %[[SUM1]], 5
+; WITHCONST:  %[[ACC:[._a-zA-Z0-9]*]] = getelementptr float* getelementptr inbounds ([1040 x float]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM2]]
+; WITHCONST:  store float 1.000000e+02, float* %[[ACC]]
+
+; WITHOUTCONST:  %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHOUTCONST:  %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHOUTCONST:  %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
+; WITHOUTCONST:  %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
+; WITHOUTCONST:  %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
+; WITHOUTCONST:  %[[ACC:[._a-zA-Z0-9]*]] = getelementptr float* getelementptr inbounds ([1040 x float]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM1]]
+; WITHOUTCONST:  store float 1.000000e+02, float* %[[ACC]]
diff --git a/final/test/Isl/CodeGen/MemAccess/default_aligned_new_access_function.ll b/final/test/Isl/CodeGen/MemAccess/default_aligned_new_access_function.ll
new file mode 100644
index 0000000..9e89550
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/default_aligned_new_access_function.ll
@@ -0,0 +1,41 @@
+; RUN: opt %loadPolly -basicaa -polly-import-jscop -polly-import-jscop-dir=%S -analyze < %s | FileCheck %s
+;
+; Check that we allow the new access functions even though they access
+; different locations than the original ones (but the alignment is the
+; default, thus there is no problem).
+;
+; CHECK-DAG: New access function '{ Stmt_for_body[i0] -> MemRef_B[0] }'detected in JSCOP file
+; CHECK-DAG: New access function '{ Stmt_for_body[i0] -> MemRef_A[i0] }'detected in JSCOP file
+;
+;    void simple_stride(int *restrict A, int *restrict B) {
+;      for (int i = 0; i < 16; i++)
+;        A[i * 2] = B[i * 2];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @simple_stride(i32* noalias %A, i32* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 16
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp = shl nsw i64 %indvars.iv, 1
+  %arrayidx = getelementptr inbounds i32* %B, i64 %tmp
+  %tmp4 = load i32* %arrayidx, align 4
+  %tmp5 = shl nsw i64 %indvars.iv, 1
+  %arrayidx3 = getelementptr inbounds i32* %A, i64 %tmp5
+  store i32 %tmp4, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple.ll b/final/test/Isl/CodeGen/MemAccess/simple.ll
new file mode 100644
index 0000000..f665652
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple.ll
@@ -0,0 +1,66 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed -stats < %s 2>&1  | FileCheck %s
+; REQUIRES: asserts
+
+;int A[100];
+;int B[100];
+;
+;int simple()
+;{
+;  int i, j;
+;  for (i = 0; i < 12; i++) {
+;      A[i] = i;
+;  }
+;
+;  for (i = 0; i < 12; i++) {
+;      B[i] = i;
+;  }
+;
+;  return 0;
+;}
+;
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@A = common global [100 x i32] zeroinitializer, align 4
+@B = common global [100 x i32] zeroinitializer, align 4
+
+define i32 @simple() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %arrayidx = getelementptr [100 x i32]* @A, i32 0, i32 %0
+  %exitcond1 = icmp ne i32 %0, 12
+  br i1 %exitcond1, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  store i32 %0, i32* %arrayidx
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc11, %for.end
+  %1 = phi i32 [ 0, %for.end ], [ %inc13, %for.inc11 ]
+  %arrayidx10 = getelementptr [100 x i32]* @B, i32 0, i32 %1
+  %exitcond = icmp ne i32 %1, 12
+  br i1 %exitcond, label %for.body7, label %for.end14
+
+for.body7:                                        ; preds = %for.cond4
+  store i32 %1, i32* %arrayidx10
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.body7
+  %inc13 = add nsw i32 %1, 1
+  br label %for.cond4
+
+for.end14:                                        ; preds = %for.cond4
+  ret i32 0
+}
+; CHECK: 2 polly-import-jscop
diff --git a/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..4742285
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop.transformed b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop.transformed
new file mode 100644
index 0000000..0a33fe8
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop.transformed
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop
new file mode 100644
index 0000000..88fafec
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop
@@ -0,0 +1,28 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end14",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body7[i0] -> MemRef_B[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body7[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body7",
+         "schedule" : "{ Stmt_for_body7[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed
new file mode 100644
index 0000000..b1808f1
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed
@@ -0,0 +1,28 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end14",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body7[i0] -> MemRef_B[0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body7[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body7",
+         "schedule" : "{ Stmt_for_body7[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop
new file mode 100644
index 0000000..56289bf
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond4 => for.end14",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body7[i0] -> MemRef_B[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body7[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body7",
+         "schedule" : "{ Stmt_for_body7[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop.transformed b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop.transformed
new file mode 100644
index 0000000..6152943
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop.transformed
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond4 => for.end14",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body7[i0] -> MemRef_B[0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body7[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body7",
+         "schedule" : "{ Stmt_for_body7[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple_analyze.ll b/final/test/Isl/CodeGen/MemAccess/simple_analyze.ll
new file mode 100644
index 0000000..2ebf7eb
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple_analyze.ll
@@ -0,0 +1,76 @@
+;RUN: opt %loadPolly -polly-import-jscop -analyze -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed < %s | FileCheck %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed -polly-codegen-isl -polly-vectorizer=polly -S < %s | FileCheck %s --check-prefix=JSCOPVEC
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+
+@A = common global [100 x i32] zeroinitializer, align 4
+@B = common global [100 x i32] zeroinitializer, align 4
+
+define i32 @simple() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %arrayidx = getelementptr [100 x i32]* @A, i32 0, i32 %0
+  %exitcond1 = icmp ne i32 %0, 12
+  br i1 %exitcond1, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  store i32 %0, i32* %arrayidx
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc11, %for.end
+  %1 = phi i32 [ 0, %for.end ], [ %inc13, %for.inc11 ]
+  %arrayidx10 = getelementptr [100 x i32]* @B, i32 0, i32 %1
+  %exitcond = icmp ne i32 %1, 12
+  br i1 %exitcond, label %for.body7, label %for.end14
+
+for.body7:                                        ; preds = %for.cond4
+  store i32 %1, i32* %arrayidx10
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.body7
+  %inc13 = add nsw i32 %1, 1
+  br label %for.cond4
+
+for.end14:                                        ; preds = %for.cond4
+  ret i32 0
+}
+; CHECK-DAG: New access function '{ Stmt_for_body7[i0] -> MemRef_B[0] }'detected in JSCOP file
+; CHECK-DAG: New access function '{ Stmt_for_body[i0] -> MemRef_A[0] }'detected in JSCOP file
+
+; Verify that the new access function (see above) is actually used during vector code generation.
+
+; JSCOPVEC:  store i32 0, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 1, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 2, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 3, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 4, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 5, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 6, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 7, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 8, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 9, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 10, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+; JSCOPVEC:  store i32 11, i32* getelementptr inbounds ([100 x i32]* @B, i32 0, i32 0)
+
+; JSCOPVEC:  store i32 0, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 1, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 2, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 3, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 4, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 5, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 6, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 7, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 8, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 9, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 10, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
+; JSCOPVEC:  store i32 11, i32* getelementptr inbounds ([100 x i32]* @A, i32 0, i32 0)
diff --git a/final/test/Isl/CodeGen/MemAccess/simple_stride___%for.cond---%for.end.jscop b/final/test/Isl/CodeGen/MemAccess/simple_stride___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..0fe6461
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple_stride___%for.cond---%for.end.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_B[0] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 15 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/MemAccess/simple_stride_test.ll b/final/test/Isl/CodeGen/MemAccess/simple_stride_test.ll
new file mode 100644
index 0000000..7ca8fc5
--- /dev/null
+++ b/final/test/Isl/CodeGen/MemAccess/simple_stride_test.ll
@@ -0,0 +1,47 @@
+; RUN: opt %loadPolly -basicaa -polly-import-jscop -polly-import-jscop-dir=%S -polly-codegen-isl -polly-vectorizer=polly -S < %s | FileCheck %s
+;
+; Check that we use the correct __new__ strides:
+;    stride zero for B
+;    stride one for A
+;
+; CHECK:  %polly.access.B = getelementptr i32* %B, i64 0
+; CHECK:  %[[BC:[._a-zA-Z0-9]*]] = bitcast i32* %polly.access.B to <1 x i32>*
+; CHECK:  %[[LD:[._a-zA-Z0-9]*]] = load <1 x i32>* %[[BC]], align 8
+; CHECK:  %[[SV:[._a-zA-Z0-9]*]] = shufflevector <1 x i32> %[[LD]], <1 x i32> %[[LD]], <16 x i32> zeroinitializer
+;
+; CHECK:  %polly.access.A = getelementptr i32* %A, i64 0
+; CHECK:  %[[VP:[._a-zA-Z0-9]*]] = bitcast i32* %polly.access.A to <16 x i32>*
+; CHECK:  store <16 x i32> %[[SV]], <16 x i32>* %[[VP]], align 8
+;
+;    void simple_stride(int *restrict A, int *restrict B) {
+;      for (int i = 0; i < 16; i++)
+;        A[i * 2] = B[i * 2];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @simple_stride(i32* noalias %A, i32* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 16
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp = shl nsw i64 %indvars.iv, 1
+  %arrayidx = getelementptr inbounds i32* %B, i64 %tmp
+  %tmp4 = load i32* %arrayidx, align 4
+  %tmp5 = shl nsw i64 %indvars.iv, 1
+  %arrayidx3 = getelementptr inbounds i32* %A, i64 %tmp5
+  store i32 %tmp4, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-iv.ll b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-iv.ll
new file mode 100644
index 0000000..9226d60
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-iv.ll
@@ -0,0 +1,44 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; This code has failed the scev based code generation as the scev in the scop
+; contains an AddRecExpr of an outer loop. When generating code, we did not
+; properly forward the value of this expression to the subfunction.
+
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; AST:  Stmt_for_j(c0);
+
+; IR: @single_parallel_loop.polly.subfn
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+
+define void @single_parallel_loop() nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc], [ 0, %entry ]
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ %indvar.j.next, %for.j], [ 0, %for.i ]
+  %sum = add i64 %indvar.j, %indvar.i
+  %scevgep = getelementptr [1024 x float]* @A, i64 0, i64 %sum
+  store float 0.0, float *%scevgep
+  %indvar.j.next = add i64 %indvar.j, 1
+  %exitcond.j = icmp slt i64 %indvar.j.next, 1024
+  br i1 %exitcond.j, label %for.j, label %for.i.inc
+
+for.i.inc:
+  fence seq_cst
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, 1024
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-2.ll b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-2.ll
new file mode 100644
index 0000000..2593228
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-2.ll
@@ -0,0 +1,32 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; AST: #pragma simd
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; AST:   Stmt_for_i(c0);
+
+; IR: getelementptr inbounds { [1024 x double]* }* %polly.par.userContext, i32 0, i32 0
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @kernel_trmm([1024 x double]* %B) {
+entry:
+  br label %for.cond1.preheader
+
+for.cond1.preheader:
+  %extern = add i64 1, 0
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i ], [ 0, %for.cond1.preheader ]
+  %getelementptr = getelementptr [1024 x double]* %B, i64 %extern, i64 %indvar.i
+  store double 0.000000e+00, double* %getelementptr
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, 1024
+  br i1 %exitcond.i, label %for.i, label %end
+
+end:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-3.ll b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-3.ll
new file mode 100644
index 0000000..7ecc27d
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-3.ll
@@ -0,0 +1,65 @@
+; RUN: opt %loadPolly -basicaa -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -basicaa -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+; RUN: opt %loadPolly -basicaa -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; The interesting part of this test case is the instruction:
+;   %tmp = bitcast i8* %call to i64**
+; which is not part of the scop. In the SCEV based code generation not '%tmp',
+; but %call is a parameter of the SCoP and we need to make sure its value is
+; properly forwarded to the subfunction.
+
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 < cols; c0 += 1)
+; AST:   Stmt_for_body(c0);
+
+; IR: @foo.polly.subfn
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i64 %cols, i8* noalias %call) {
+entry:
+  %tmp = bitcast i8* %call to i64**
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ %indvar.next, %for.body ], [ 0, %entry ]
+  %arrayidx = getelementptr inbounds i64** %tmp, i64 0
+  %tmp1 = load i64** %arrayidx, align 8
+  %arrayidx.2 = getelementptr inbounds i64* %tmp1, i64 %indvar
+  store i64 1, i64* %arrayidx.2, align 4
+  %indvar.next = add nsw i64 %indvar, 1
+  %cmp = icmp slt i64 %indvar.next, %cols
+  br i1 %cmp, label %for.body, label %end
+
+end:
+  ret void
+}
+
+; Another variation of this test case, now with even more of the index
+; expression defined outside of the scop.
+
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 < cols; c0 += 1)
+; AST:   Stmt_for_body(c0);
+
+; IR: @bar.polly.subfn
+
+define void @bar(i64 %cols, i8* noalias %call) {
+entry:
+  %tmp = bitcast i8* %call to i64**
+  %arrayidx = getelementptr inbounds i64** %tmp, i64 0
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ %indvar.next, %for.body ], [ 0, %entry ]
+  %tmp1 = load i64** %arrayidx, align 8
+  %arrayidx.2 = getelementptr inbounds i64* %tmp1, i64 %indvar
+  store i64 1, i64* %arrayidx.2, align 4
+  %indvar.next = add nsw i64 %indvar, 1
+  %cmp = icmp slt i64 %indvar.next, %cols
+  br i1 %cmp, label %for.body, label %end
+
+end:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values.ll b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values.ll
new file mode 100644
index 0000000..1a31995
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values.ll
@@ -0,0 +1,48 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=IR
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=IR
+
+; Make sure we correctly forward the reference to 'A' to the OpenMP subfunction.
+;
+; void loop_references_outer_ids(float *A) {
+;   for (long i = 0; i < 100; i++)
+;     A[i] = i;
+; }
+
+
+; AST: #pragma simd
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 <= 99; c0 += 1)
+; AST:   Stmt_for_body(c0);
+
+; IR-LABEL: polly.start:
+; IR-NEXT:  %0 = bitcast { float* }* %polly.par.userContext to i8*
+; IR-NEXT:  call void @llvm.lifetime.start(i64 8, i8* %0)
+; IR-NEXT:  %1 = getelementptr inbounds { float* }* %polly.par.userContext, i32 0, i32 0
+; IR-NEXT:  store float* %A, float** %1
+; IR-NEXT:  %polly.par.userContext1 = bitcast { float* }* %polly.par.userContext to i8*
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @loop_references_outer_ids(float* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i64 %i.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %conv = sitofp i64 %i.0 to float
+  %arrayidx = getelementptr inbounds float* %A, i64 %i.0
+  store float %conv, float* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i64 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll b/final/test/Isl/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll
new file mode 100644
index 0000000..222e45b
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll
@@ -0,0 +1,102 @@
+; RUN: opt %loadPolly -polly-parallel -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=IR
+; RUN: opt %loadPolly -polly-parallel -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=IR
+;
+; float A[100];
+;
+; void loop_references_outer_ids(long n) {
+;   for (long i = 0; i < 100; i++)
+;     for (long j = 0; j < 100; j++)
+;       for (long k = 0; k < n + i; k++)
+;         A[j] += i + j + k;
+; }
+
+; In this test case we verify that the j-loop is generated as OpenMP parallel
+; loop and that the values of 'i' and 'n', needed in the loop bounds of the
+; k-loop, are correctly passed to the subfunction.
+
+; AST: #pragma minimal dependence distance: 1
+; AST: for (int c0 = max(0, -n + 1); c0 <= 99; c0 += 1)
+; AST:   #pragma omp parallel for
+; AST:   for (int c1 = 0; c1 <= 99; c1 += 1)
+; AST:     #pragma minimal dependence distance: 1
+; AST:     for (int c2 = 0; c2 < n + c0; c2 += 1)
+; AST:       Stmt_for_body6(c0, c1, c2);
+
+; IR: %polly.par.userContext = alloca { i64, i64 }
+; IR: %4 = bitcast { i64, i64 }* %polly.par.userContext to i8*
+; IR-NEXT: call void @llvm.lifetime.start(i64 16, i8* %4)
+; IR-NEXT: %5 = getelementptr inbounds { i64, i64 }* %polly.par.userContext, i32 0, i32 0
+; IR-NEXT: store i64 %n, i64* %5
+; IR-NEXT: %6 = getelementptr inbounds { i64, i64 }* %polly.par.userContext, i32 0, i32 1
+; IR-NEXT: store i64 %polly.indvar, i64* %6
+; IR-NEXT: %polly.par.userContext1 = bitcast { i64, i64 }* %polly.par.userContext to i8*
+
+; IR-LABEL: @loop_references_outer_ids.polly.subfn(i8* %polly.par.userContext)
+; IR: %polly.par.userContext1 = bitcast i8* %polly.par.userContext to { i64, i64 }*
+; IR-NEXT: %0 = getelementptr inbounds { i64, i64 }* %polly.par.userContext1, i32 0, i32 0
+; IR-NEXT: %1 = load i64* %0
+; IR-NEXT: %2 = getelementptr inbounds { i64, i64 }* %polly.par.userContext1, i32 0, i32 1
+; IR-NEXT: %3 = load i64* %2
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+@A = common global [100 x float] zeroinitializer, align 16
+
+define void @loop_references_outer_ids(i64 %n) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc03, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %inc04, %for.inc03 ]
+  %exitcond1 = icmp ne i64 %i.0, 100
+  br i1 %exitcond1, label %for.body, label %for.end15
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc00, %for.body
+  %j.0 = phi i64 [ 0, %for.body ], [ %inc01, %for.inc00 ]
+  %exitcond = icmp ne i64 %j.0, 100
+  br i1 %exitcond, label %for.body3, label %for.end12
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i64 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %add = add nsw i64 %i.0, %n
+  %cmp5 = icmp slt i64 %k.0, %add
+  br i1 %cmp5, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %add7 = add nsw i64 %i.0, %j.0
+  %add8 = add nsw i64 %add7, %k.0
+  %conv = sitofp i64 %add8 to float
+  %arrayidx = getelementptr inbounds [100 x float]* @A, i64 0, i64 %j.0
+  %tmp = load float* %arrayidx, align 4
+  %add9 = fadd float %tmp, %conv
+  store float %add9, float* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i64 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc00
+
+for.inc00:                                        ; preds = %for.end
+  %inc01 = add nsw i64 %j.0, 1
+  br label %for.cond1
+
+for.end12:                                        ; preds = %for.cond1
+  br label %for.inc03
+
+for.inc03:                                        ; preds = %for.end12
+  %inc04 = add nsw i64 %i.0, 1
+  br label %for.cond
+
+for.end15:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/reference-other-bb.ll b/final/test/Isl/CodeGen/OpenMP/reference-other-bb.ll
new file mode 100644
index 0000000..aaecff7
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/reference-other-bb.ll
@@ -0,0 +1,27 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; IR: @foo.polly.subfn
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i32 %sendcount, i8* %recvbuf) {
+entry:
+  br label %sw.bb3
+
+sw.bb3:
+  %tmp = bitcast i8* %recvbuf to double*
+  %cmp75 = icmp sgt i32 %sendcount, 0
+  br i1 %cmp75, label %for.body, label %end
+
+for.body:
+  %i.16 = phi i32 [ %inc04, %for.body ], [ 0, %sw.bb3 ]
+  %idxprom11 = sext i32 %i.16 to i64
+  %arrayidx12 = getelementptr inbounds double* %tmp, i64 %idxprom11
+  store double 1.0, double* %arrayidx12, align 8
+  %inc04 = add nsw i32 %i.16, 1
+  %cmp7 = icmp slt i32 %inc04, %sendcount
+  br i1 %cmp7, label %for.body, label %end
+
+end:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/reference-preceeding-loop.ll b/final/test/Isl/CodeGen/OpenMP/reference-preceeding-loop.ll
new file mode 100644
index 0000000..54f89e1
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/reference-preceeding-loop.ll
@@ -0,0 +1,47 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+
+; - Test the case where scalar evolution references a loop that is outside
+;   of the scop, but does not contain the scop.
+; - Test the case where two parallel subfunctions are created.
+
+; AST: if (symbol >= p_2 + 1) {
+; AST-NEXT:   #pragma simd
+; AST-NEXT:   #pragma omp parallel for
+; AST-NEXT:   for (int c0 = 0; c0 < p_0 + symbol; c0 += 1)
+; AST-NEXT:     Stmt_while_body(c0);
+; AST-NEXT: } else
+; AST-NEXT:   #pragma simd
+; AST-NEXT:   #pragma omp parallel for
+; AST-NEXT:   for (int c0 = 0; c0 <= p_0 + p_2; c0 += 1)
+; AST-NEXT:     Stmt_while_body(c0);
+
+; IR: @update_model.polly.subfn
+; IR: @update_model.polly.subfn1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@cum_freq = external global [258 x i64], align 16
+
+define void @update_model(i64 %symbol) {
+entry:
+  br label %for.one
+
+for.one:
+  %i.1 = phi i64 [ %dec07, %for.one ], [ %symbol, %entry ]
+  %dec07 = add nsw i64 %i.1, -1
+  br i1 undef, label %for.one, label %while.body
+
+while.body:
+  %indvar = phi i64 [ %sub42, %while.body ], [ %i.1, %for.one ]
+  %sub42 = add nsw i64 %indvar, -1
+  %arrayidx44 = getelementptr inbounds [258 x i64]* @cum_freq, i64 0, i64 %sub42
+  store i64 1, i64* %arrayidx44, align 4
+  %cmp40 = icmp sgt i64 %sub42, 0
+  br i1 %cmp40, label %while.body, label %while.end
+
+while.end:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/single_loop.ll b/final/test/Isl/CodeGen/OpenMP/single_loop.ll
new file mode 100644
index 0000000..8b211c3
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/single_loop.ll
@@ -0,0 +1,118 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-import-jscop-dir=%S -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST-STRIDE4
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-import-jscop-dir=%S -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=IR-STRIDE4
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-import-jscop -polly-import-jscop-dir=%S -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=IR-STRIDE4
+
+; This extensive test case tests the creation of the full set of OpenMP calls
+; as well as the subfunction creation using a trivial loop as example.
+
+; #define N 1024
+; float A[N];
+;
+; void single_parallel_loop(void) {
+;   for (long i = 0; i < N; i++)
+;     A[i] = 1;
+; }
+
+; AST: #pragma simd
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; AST:   Stmt_S(c0);
+
+; AST-STRIDE4: #pragma omp parallel for
+; AST-STRIDE4: for (int c0 = 0; c0 <= 1023; c0 += 4)
+; AST-STRIDE4:   #pragma simd
+; AST-STRIDE4:   for (int c1 = c0; c1 <= c0 + 3; c1 += 1)
+; AST-STRIDE4:     Stmt_S(c1);
+
+; IR-LABEL: single_parallel_loop()
+; IR-NEXT: entry
+; IR-NEXT:   %polly.par.userContext = alloca
+
+; IR-LABEL: polly.start:
+; IR-NEXT:   %0 = bitcast {}* %polly.par.userContext to i8*
+; IR-NEXT:   call void @llvm.lifetime.start(i64 0, i8* %0)
+; IR-NEXT:   %polly.par.userContext1 = bitcast {}* %polly.par.userContext to i8*
+; IR-NEXT:   call void @GOMP_parallel_loop_runtime_start(void (i8*)* @single_parallel_loop.polly.subfn, i8* %polly.par.userContext1, i32 0, i64 0, i64 1024, i64 1)
+; IR-NEXT:   call void @single_parallel_loop.polly.subfn(i8* %polly.par.userContext1)
+; IR-NEXT:   call void @GOMP_parallel_end()
+; IR-NEXT:   %1 = bitcast {}* %polly.par.userContext to i8*
+; IR-NEXT:   call void @llvm.lifetime.end(i64 8, i8* %1)
+; IR-NEXT:   br label %polly.merge_new_and_old
+
+; IR: define internal void @single_parallel_loop.polly.subfn(i8* %polly.par.userContext) #1
+; IR-LABEL: polly.par.setup:
+; IR-NEXT:   %polly.par.LBPtr = alloca i64
+; IR-NEXT:   %polly.par.UBPtr = alloca i64
+; IR-NEXT:   %polly.par.userContext1 =
+; IR:   br label %polly.par.checkNext
+
+; IR-LABEL: polly.par.exit:
+; IR-NEXT:   call void @GOMP_loop_end_nowait()
+; IR-NEXT:   ret void
+
+; IR-LABEL: polly.par.checkNext:
+; IR-NEXT:   %[[parnext:[._a-zA-Z0-9]*]] = call i8 @GOMP_loop_runtime_next(i64* %polly.par.LBPtr, i64* %polly.par.UBPtr)
+; IR-NEXT:   %[[cmp:[._a-zA-Z0-9]*]] = icmp ne i8 %[[parnext]], 0
+; IR-NEXT:   br i1 %[[cmp]], label %polly.par.loadIVBounds, label %polly.par.exit
+
+; IR-LABEL: polly.par.loadIVBounds:
+; IR-NEXT:   %polly.par.LB = load i64* %polly.par.LBPtr
+; IR-NEXT:   %polly.par.UB = load i64* %polly.par.UBPtr
+; IR-NEXT:   %polly.par.UBAdjusted = sub i64 %polly.par.UB, 1
+; IR-NEXT:   br label %polly.loop_preheader
+
+; IR-LABEL: polly.loop_exit:
+; IR-NEXT:   br label %polly.par.checkNext
+
+; IR-LABEL: polly.loop_header:
+; IR-NEXT:   %polly.indvar = phi i64 [ %polly.par.LB, %polly.loop_preheader ], [ %polly.indvar_next, %polly.stmt.S ]
+; IR-NEXT:   br label %polly.stmt.S
+
+; IR-LABEL: polly.stmt.S:
+; IR-NEXT:   %[[gep:[._a-zA-Z0-9]*]] = getelementptr [1024 x float]* {{.*}}, i64 0, i64 %polly.indvar
+; IR-NEXT:   store float 1.000000e+00, float* %[[gep]]
+; IR-NEXT:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; IR-NEXT:   %polly.adjust_ub = sub i64 %polly.par.UBAdjusted, 1
+; IR-NEXT:   %polly.loop_cond = icmp sle i64 %polly.indvar, %polly.adjust_ub
+; IR-NEXT:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
+
+; IR-LABEL: polly.loop_preheader:
+; IR-NEXT:   br label %polly.loop_header
+
+; IR: attributes #1 = { "polly.skip.fn" }
+
+; IR-STRIDE4:   call void @GOMP_parallel_loop_runtime_start(void (i8*)* @single_parallel_loop.polly.subfn, i8* %polly.par.userContext1, i32 0, i64 0, i64 1024, i64 4)
+; IR-STRIDE4:  add nsw i64 %polly.indvar, 3
+; IR-STRIDE4:  %polly.indvar_next = add nsw i64 %polly.indvar, 4
+; IR-STRIDE4   %polly.adjust_ub = sub i64 %polly.par.UBAdjusted, 4
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+
+define void @single_parallel_loop() nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ %indvar.next, %for.inc], [ 0, %entry ]
+  %scevgep = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %S, label %exit
+
+S:
+  store float 1.0, float* %scevgep
+  br label %for.inc
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.i
+
+exit:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll b/final/test/Isl/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll
new file mode 100644
index 0000000..7a4192f
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+; RUN: opt %loadPolly -tbaa -polly-parallel -polly-parallel-force -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; #define N 1024
+; float A[N];
+;
+; void single_parallel_loop(void) {
+;   for (long i = 0; i < N; i++)
+;     A[i] = 1;
+; }
+
+; AST: #pragma simd
+; AST: #pragma omp parallel for
+; AST: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; AST:   Stmt_S(c0);
+
+; IR: @single_parallel_loop.polly.subfn
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @single_parallel_loop(float** %A) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ %indvar.next, %for.inc], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %S, label %exit
+
+S:
+  %ptr = load float** %A,  !tbaa !2
+  %scevgep = getelementptr float* %ptr, i64 %indvar
+  %val = load float* %scevgep, !tbaa !6
+  %sum = fadd float %val, 1.0
+  store float %sum, float* %scevgep, !tbaa !6
+  br label %for.inc
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  br label %for.i
+
+exit:
+  ret void
+}
+
+!2 = !{!"float", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!6 = !{!"float *ptr", !3, i64 0}
diff --git a/final/test/Isl/CodeGen/OpenMP/single_parallel_loop___%for.i---%exit.jscop b/final/test/Isl/CodeGen/OpenMP/single_parallel_loop___%for.i---%exit.jscop
new file mode 100644
index 0000000..971f196
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/single_parallel_loop___%for.i---%exit.jscop
@@ -0,0 +1,17 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.i => exit",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_S[i0] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_S[i0] : i0 >= 0 and i0 <= 1023 }",
+         "name" : "Stmt_S",
+         "schedule" : "{ Stmt_S[i0] -> scattering[floor(i0/4) * 4, i0] }"
+      }
+   ]
+}
diff --git a/final/test/Isl/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll b/final/test/Isl/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll
new file mode 100644
index 0000000..f861209
--- /dev/null
+++ b/final/test/Isl/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll
@@ -0,0 +1,47 @@
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-ast -analyze < %s | FileCheck %s -check-prefix=AST
+; RUN: opt %loadPolly -polly-parallel -polly-parallel-force -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s -check-prefix=IR
+
+; This test case verifies that we create correct code even if two OpenMP loops
+; share common outer variables.
+
+; AST: if (nj >= p_1 + 3) {
+; AST:   #pragma simd
+; AST:   #pragma omp parallel for
+; AST:   for (int c0 = 0; c0 < p_0 + nj - 1; c0 += 1)
+; AST:     Stmt_for_body35(c0);
+; AST: } else
+; AST:   #pragma simd
+; AST:   #pragma omp parallel for
+; AST:   for (int c0 = 0; c0 <= p_0 + p_1; c0 += 1)
+; AST:     Stmt_for_body35(c0);
+
+; IR: @foo.polly.subfn
+; IR: @foo.polly.subfn1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i64 %nj, [512 x double]* %R) {
+entry:
+  br label %for.cond1.preheader
+
+for.cond1.preheader:
+  %k.014 = phi i64 [ %inc87, %for.inc86 ], [ 0, %entry ]
+  %j.010 = add nsw i64 %k.014, 1
+  br i1 undef, label %for.body35, label %for.inc86
+
+for.body35:
+  %j.012 = phi i64 [ %j.0, %for.body35 ], [ %j.010, %for.cond1.preheader ]
+  %arrayidx39 = getelementptr inbounds [512 x double]* %R, i64 0, i64 %j.012
+  store double 0.000000e+00, double* %arrayidx39
+  %j.0 = add nsw i64 %j.012, 1
+  %cmp34 = icmp slt i64 %j.0, %nj
+  br i1 %cmp34, label %for.body35, label %for.inc86
+
+for.inc86:
+  %inc87 = add nsw i64 %k.014, 1
+  br i1 undef, label %for.cond1.preheader, label %for.end88
+
+for.end88:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/PHIInExit.ll b/final/test/Isl/CodeGen/PHIInExit.ll
new file mode 100644
index 0000000..7753dba
--- /dev/null
+++ b/final/test/Isl/CodeGen/PHIInExit.ll
@@ -0,0 +1,104 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct..0__pthread_mutex_s = type { i32, i32, i32, i32, i32, i32, %struct.__pthread_list_t }
+%struct.__pthread_list_t = type { %struct.__pthread_list_t*, %struct.__pthread_list_t* }
+%union.pthread_attr_t = type { i64, [12 x i32] }
+%union.pthread_mutex_t = type { %struct..0__pthread_mutex_s }
+%union.pthread_mutexattr_t = type { i32 }
+
+@_ZL20__gthrw_pthread_oncePiPFvvE = weak alias i32 (i32*, void ()*)* @pthread_once ; <i32 (i32*, void ()*)*> [#uses=0]
+@_ZL27__gthrw_pthread_getspecificj = weak alias i8* (i32)* @pthread_getspecific ; <i8* (i32)*> [#uses=0]
+@_ZL27__gthrw_pthread_setspecificjPKv = weak alias i32 (i32, i8*)* @pthread_setspecific ; <i32 (i32, i8*)*> [#uses=0]
+@_ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_ = weak alias i32 (i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create ; <i32 (i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)*> [#uses=0]
+@_ZL22__gthrw_pthread_cancelm = weak alias i32 (i64)* @pthread_cancel ; <i32 (i64)*> [#uses=0]
+@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = weak alias i32 (%union.pthread_mutex_t*)* @pthread_mutex_lock ; <i32 (%union.pthread_mutex_t*)*> [#uses=0]
+@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = weak alias i32 (%union.pthread_mutex_t*)* @pthread_mutex_trylock ; <i32 (%union.pthread_mutex_t*)*> [#uses=0]
+@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = weak alias i32 (%union.pthread_mutex_t*)* @pthread_mutex_unlock ; <i32 (%union.pthread_mutex_t*)*> [#uses=0]
+@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = weak alias i32 (%union.pthread_mutex_t*, %union.pthread_mutexattr_t*)* @pthread_mutex_init ; <i32 (%union.pthread_mutex_t*, %union.pthread_mutexattr_t*)*> [#uses=0]
+@_ZL26__gthrw_pthread_key_createPjPFvPvE = weak alias i32 (i32*, void (i8*)*)* @pthread_key_create ; <i32 (i32*, void (i8*)*)*> [#uses=0]
+@_ZL26__gthrw_pthread_key_deletej = weak alias i32 (i32)* @pthread_key_delete ; <i32 (i32)*> [#uses=0]
+@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = weak alias i32 (%union.pthread_mutexattr_t*)* @pthread_mutexattr_init ; <i32 (%union.pthread_mutexattr_t*)*> [#uses=0]
+@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = weak alias i32 (%union.pthread_mutexattr_t*, i32)* @pthread_mutexattr_settype ; <i32 (%union.pthread_mutexattr_t*, i32)*> [#uses=0]
+@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = weak alias i32 (%union.pthread_mutexattr_t*)* @pthread_mutexattr_destroy ; <i32 (%union.pthread_mutexattr_t*)*> [#uses=0]
+
+define void @_ZL6createP6node_tii3v_tS1_d() {
+entry:
+  br i1 undef, label %bb, label %bb5
+
+bb:                                               ; preds = %entry
+  br i1 false, label %bb1, label %bb3
+
+bb1:                                              ; preds = %bb
+  br label %bb3
+
+bb3:                                              ; preds = %bb1, %bb
+  %iftmp.99.0 = phi i64 [ undef, %bb1 ], [ 1, %bb ] ; <i64> [#uses=0]
+  br label %bb5
+
+bb5:                                              ; preds = %bb3, %entry
+  br i1 undef, label %return, label %bb7
+
+bb7:                                              ; preds = %bb5
+  unreachable
+
+return:                                           ; preds = %bb5
+  ret void
+}
+
+define i32 @pthread_once(i32*, void ()*) {
+  ret i32 0
+}
+
+define i8* @pthread_getspecific(i32) {
+  ret i8* null
+}
+
+define i32 @pthread_setspecific(i32, i8*) {
+  ret i32 0
+}
+
+define i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*) {
+  ret i32 0
+}
+
+define i32 @pthread_cancel(i64) {
+  ret i32 0
+}
+
+define i32 @pthread_mutex_lock(%union.pthread_mutex_t*) {
+  ret i32 0
+}
+
+define i32 @pthread_mutex_trylock(%union.pthread_mutex_t*) {
+  ret i32 0
+}
+
+define i32 @pthread_mutex_unlock(%union.pthread_mutex_t*) {
+  ret i32 0
+}
+
+define i32 @pthread_mutex_init(%union.pthread_mutex_t*, %union.pthread_mutexattr_t*) {
+  ret i32 0
+}
+
+define i32 @pthread_key_create(i32*, void (i8*)*) {
+  ret i32 0
+}
+
+define i32 @pthread_key_delete(i32) {
+  ret i32 0
+}
+
+define i32 @pthread_mutexattr_init(%union.pthread_mutexattr_t*) {
+  ret i32 0
+}
+
+define i32 @pthread_mutexattr_settype(%union.pthread_mutexattr_t*, i32) {
+  ret i32 0
+}
+
+define i32 @pthread_mutexattr_destroy(%union.pthread_mutexattr_t*) {
+  ret i32 0
+}
diff --git a/final/test/Isl/CodeGen/aliasing_different_base_and_access_type.ll b/final/test/Isl/CodeGen/aliasing_different_base_and_access_type.ll
new file mode 100644
index 0000000..3ab242d
--- /dev/null
+++ b/final/test/Isl/CodeGen/aliasing_different_base_and_access_type.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -S -polly-code-generator=isl -polly-codegen-isl < %s | FileCheck %s
+;
+; We have to cast %B to "short *" before we create RTCs.
+;
+; CHECK:   %polly.access.cast.B = bitcast i32* %B to i16*
+; CHECK-NEXT:   %polly.access.B = getelementptr i16* %polly.access.cast.B, i64 1024
+;
+; We should never access %B as an i32 pointer:
+;
+; CHECK-NOT: getelementptr i32* %B
+;
+;    void jd(int *A, int *B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = ((short *)B)[i];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp = bitcast i32* %B to i16*
+  %arrayidx = getelementptr inbounds i16* %tmp, i64 %indvars.iv
+  %tmp1 = load i16* %arrayidx, align 2
+  %conv = sext i16 %tmp1 to i32
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %conv, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/aliasing_different_pointer_types.ll b/final/test/Isl/CodeGen/aliasing_different_pointer_types.ll
new file mode 100644
index 0000000..90e8d2b
--- /dev/null
+++ b/final/test/Isl/CodeGen/aliasing_different_pointer_types.ll
@@ -0,0 +1,51 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-codegen-isl -S < %s | FileCheck %s
+;
+; Check that we cast the different pointer types correctly before we compare
+; them in the RTC's. We use i8* as max pointer type.
+;
+; CHECK: entry:
+; CHECK:   %polly.access.B = getelementptr float** %B, i64 1024
+; CHECK:   %polly.access.A = getelementptr double** %A, i64 0
+; CHECK:   %[[paBb:[._a-zA-Z0-9]]] = bitcast float** %polly.access.B to i8*
+; CHECK:   %[[paAb:[._a-zA-Z0-9]]] = bitcast double** %polly.access.A to i8*
+; CHECK:   %[[ALeB:[._a-zA-Z0-9]]] = icmp ule i8* %[[paBb]], %[[paAb]]
+; CHECK:   %polly.access.A1 = getelementptr double** %A, i64 1024
+; CHECK:   %polly.access.B2 = getelementptr float** %B, i64 0
+; CHECK:   %[[paA1b:[._a-zA-Z0-9]]] = bitcast double** %polly.access.A1 to i8*
+; CHECK:   %[[paB2b:[._a-zA-Z0-9]]] = bitcast float** %polly.access.B2 to i8*
+; CHECK:   %[[A1LeB2:[._a-zA-Z0-9]]] = icmp ule i8* %[[paA1b]], %[[paB2b]]
+; CHECK:   %[[le1OrLe2:[._a-zA-Z0-9]]] = or i1 %[[ALeB]], %[[A1LeB2]]
+; CHECK:   %[[orAndTrue:[._a-zA-Z0-9]]] = and i1 true, %[[le1OrLe2]]
+; CHECK:   br label %polly.split_new_and_old
+;
+;    void jd(double **A, float **B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = (double *)B[i];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(double** %A, float** %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds float** %B, i64 %indvars.iv
+  %tmp = load float** %arrayidx, align 8
+  %tmp1 = bitcast float* %tmp to double*
+  %arrayidx2 = getelementptr inbounds double** %A, i64 %indvars.iv
+  store double* %tmp1, double** %arrayidx2, align 8
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/aliasing_multidimensional_access.ll b/final/test/Isl/CodeGen/aliasing_multidimensional_access.ll
new file mode 100644
index 0000000..95238af
--- /dev/null
+++ b/final/test/Isl/CodeGen/aliasing_multidimensional_access.ll
@@ -0,0 +1,78 @@
+; RUN: opt %loadPolly -S -polly-codegen-isl -polly-code-generator=isl -polly-delinearize < %s | FileCheck %s
+;
+; Check that we calculate the maximal access into array A correctly.
+;
+; CHECK:  %[[TMP0:[._0-9a-zA-Z]*]] = mul i64 99, %m
+; CHECK:  %[[TMP1:[._0-9a-zA-Z]*]] = add i64 %[[TMP0]], 149
+; CHECK:  %[[TMP2:[._0-9a-zA-Z]*]] = mul i64 %[[TMP1]], %p
+; CHECK:  %[[TMP3:[._0-9a-zA-Z]*]] = add i64 %[[TMP2]], 150
+; CHECK:  %polly.access.A{{[0-9]*}} = getelementptr double* %A, i64 %[[TMP3]]
+;
+;    void foo(long n, long m, long p, double A[n][m][p], int *B) {
+;      for (long i = 0; i < 100; i++)
+;        for (long j = 0; j < 150; j++)
+;          for (long k = 0; k < 150; k++)
+;            A[i][j][k] = B[k];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo(i64 %n, i64 %m, i64 %p, double* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc03, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %inc04, %for.inc03 ]
+  %exitcond2 = icmp ne i64 %i.0, 100
+  br i1 %exitcond2, label %for.body, label %for.end15
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc00, %for.body
+  %j.0 = phi i64 [ 0, %for.body ], [ %inc01, %for.inc00 ]
+  %exitcond1 = icmp ne i64 %j.0, 150
+  br i1 %exitcond1, label %for.body3, label %for.end12
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i64 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i64 %k.0, 150
+  br i1 %exitcond, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %arrayidx = getelementptr inbounds i32* %B, i64 %k.0
+  %tmp3 = load i32* %arrayidx, align 2
+  %conv = sitofp i32 %tmp3 to double
+  %tmp4 = mul nuw i64 %m, %p
+  %tmp5 = mul nsw i64 %i.0, %tmp4
+  %tmp6 = mul nsw i64 %j.0, %p
+  %arrayidx7.sum = add i64 %tmp5, %tmp6
+  %arrayidx8.sum = add i64 %arrayidx7.sum, %k.0
+  %arrayidx9 = getelementptr inbounds double* %A, i64 %arrayidx8.sum
+  store double %conv, double* %arrayidx9, align 8
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i64 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc00
+
+for.inc00:                                        ; preds = %for.end
+  %inc01 = add nsw i64 %j.0, 1
+  br label %for.cond1
+
+for.end12:                                        ; preds = %for.cond1
+  br label %for.inc03
+
+for.inc03:                                        ; preds = %for.end12
+  %inc04 = add nsw i64 %i.0, 1
+  br label %for.cond
+
+for.end15:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/aliasing_parametric_simple_1.ll b/final/test/Isl/CodeGen/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..1e716f3
--- /dev/null
+++ b/final/test/Isl/CodeGen/aliasing_parametric_simple_1.ll
@@ -0,0 +1,45 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-codegen-isl -S < %s | FileCheck %s
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c];
+;    }
+;
+; CHECK:  %[[AMax:[._a-zA-Z0-9]*]] = getelementptr i32* %A, i64 1024
+; CHECK:  %[[BMin:[._a-zA-Z0-9]*]] = getelementptr i32* %B, i32 %c
+; CHECK:  %[[AltB:[._a-zA-Z0-9]*]] = icmp ule i32* %[[AMax]], %[[BMin]]
+; CHECK:  %[[Cext:[._a-zA-Z0-9]*]] = sext i32 %c to i64
+; CHECK:  %[[Cp1:[._a-zA-Z0-9]*]] = add nsw i64 %[[Cext]], 1
+; CHECK:  %[[BMax:[._a-zA-Z0-9]*]] = getelementptr i32* %B, i64 %[[Cp1]]
+; CHECK:  %[[AMin:[._a-zA-Z0-9]*]] = getelementptr i32* %A, i64 0
+; CHECK:  %[[BltA:[._a-zA-Z0-9]*]] = icmp ule i32* %[[BMax]], %[[AMin]]
+; CHECK:  %[[NoAlias:[._a-zA-Z0-9]*]] = or i1 %[[AltB]], %[[BltA]]
+; CHECK:  %[[RTC:[._a-zA-Z0-9]*]] = and i1 true, %[[NoAlias]]
+; CHECK:  br i1 %[[RTC]], label %polly.start, label %for.cond
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %idxprom = sext i32 %c to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/aliasing_parametric_simple_2.ll b/final/test/Isl/CodeGen/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..2665134
--- /dev/null
+++ b/final/test/Isl/CodeGen/aliasing_parametric_simple_2.ll
@@ -0,0 +1,57 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-codegen-isl -S < %s | FileCheck %s
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c - 10] + B[5];
+;    }
+;
+; CHECK:  %[[AMax:[._a-zA-Z0-9]*]] = getelementptr i32* %A, i64 1024
+; CHECK:  %[[m0:[._a-zA-Z0-9]*]] = sext i32 %c to i64
+; CHECK:  %[[m1:[._a-zA-Z0-9]*]] = icmp sge i64 %[[m0]], 15
+; CHECK:  %[[m2:[._a-zA-Z0-9]*]] = sext i32 %c to i64
+; CHECK:  %[[m3:[._a-zA-Z0-9]*]] = sub nsw i64 %[[m2]], 10
+; CHECK:  %[[m4:[._a-zA-Z0-9]*]] = select i1 %[[m1]], i64 5, i64 %[[m3]]
+; CHECK:  %[[BMin:[._a-zA-Z0-9]*]] = getelementptr i32* %B, i64 %[[m4]]
+; CHECK:  %[[AltB:[._a-zA-Z0-9]*]] = icmp ule i32* %[[AMax]], %[[BMin]]
+; CHECK:  %[[M0:[._a-zA-Z0-9]*]] = sext i32 %c to i64
+; CHECK:  %[[M1:[._a-zA-Z0-9]*]] = icmp sle i64 %[[M0]], 15
+; CHECK:  %[[M2:[._a-zA-Z0-9]*]] = sext i32 %c to i64
+; CHECK:  %[[M3:[._a-zA-Z0-9]*]] = sub nsw i64 %[[M2]], 9
+; CHECK:  %[[M4:[._a-zA-Z0-9]*]] = select i1 %[[M1]], i64 6, i64 %[[M3]]
+; CHECK:  %[[BMax:[._a-zA-Z0-9]*]] = getelementptr i32* %B, i64 %[[M4]]
+; CHECK:  %[[AMin:[._a-zA-Z0-9]*]] = getelementptr i32* %A, i64 0
+; CHECK:  %[[BltA:[._a-zA-Z0-9]*]] = icmp ule i32* %[[BMax]], %[[AMin]]
+; CHECK:  %[[NoAlias:[._a-zA-Z0-9]*]] = or i1 %[[AltB]], %[[BltA]]
+; CHECK:  %[[RTC:[._a-zA-Z0-9]*]] = and i1 true, %[[NoAlias]]
+; CHECK:  br i1 %[[RTC]], label %polly.start, label %for.cond
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %sub = add nsw i32 %c, -10
+  %idxprom = sext i32 %sub to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 5
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx3 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/aliasing_struct_element.ll b/final/test/Isl/CodeGen/aliasing_struct_element.ll
new file mode 100644
index 0000000..cb75d2e
--- /dev/null
+++ b/final/test/Isl/CodeGen/aliasing_struct_element.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -S -polly-code-generator=isl -polly-codegen-isl < %s | FileCheck %s
+;
+; We should only access (or compute the address of) "the first element" of %S
+; as it is a single struct not a struct array. The maximal access to S, thus
+; S->B[1023] is for ScalarEvolution an access with offset of 1423, 1023 for the
+; index inside the B part of S and 400 to skip the Dummy array in S. Note that
+; these numbers are relative to the actual type of &S->B[i] (char*) not to the
+; type of S (struct st *) or something else.
+;
+; Verify that we do not use the offset 1423 into a non existent S array when we
+; compute runtime alias checks but treat it as if it was a char array.
+;
+; CHECK: %polly.access.cast.S = bitcast %struct.st* %S to i8*
+; CHECK: %polly.access.S = getelementptr i8* %polly.access.cast.S, i64 1424
+;
+;    struct st {
+;      int Dummy[100];
+;      char B[100];
+;    };
+;
+;    void jd(int *A, struct st *S) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = S->B[i];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.st = type { [100 x i32], [100 x i8] }
+
+define void @jd(i32* %A, %struct.st* %S) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds %struct.st* %S, i64 0, i32 1, i64 %indvars.iv
+  %tmp = load i8* %arrayidx, align 1
+  %conv = sext i8 %tmp to i32
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %conv, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/alignment.ll b/final/test/Isl/CodeGen/alignment.ll
new file mode 100644
index 0000000..f4038c9
--- /dev/null
+++ b/final/test/Isl/CodeGen/alignment.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s
+;
+; Check that the special alignment information is kept
+;
+; CHECK: align 8
+; CHECK: align 8
+;
+;    void jd(int *A) {
+;      for (int i = 0; i < 1024; i += 2)
+;        A[i] = i;
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %cmp = icmp slt i64 %indvars.iv, 1024
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
+  %tmp = trunc i64 %indvars.iv to i32
+  store i32 %tmp, i32* %arrayidx, align 8
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/annotated_alias_scopes.ll b/final/test/Isl/CodeGen/annotated_alias_scopes.ll
new file mode 100644
index 0000000..d1a2655
--- /dev/null
+++ b/final/test/Isl/CodeGen/annotated_alias_scopes.ll
@@ -0,0 +1,79 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-codegen-isl -S < %s | FileCheck %s --check-prefix=SCOPES
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-codegen-isl -polly-annotate-alias-scopes=false -S < %s | FileCheck %s --check-prefix=NOSCOPES
+;
+; Check that we create alias scopes that indicate the accesses to A, B and C cannot alias in any way.
+;
+; SCOPES-LABEL: polly.stmt.for.body:
+; SCOPES:      %[[BIdx:[._a-zA-Z0-9]*]] = getelementptr{{.*}} i32* %B, i64 %polly.indvar
+; SCOPES:      load i32* %[[BIdx]], align 4, !alias.scope ![[AliasScopeB:[0-9]*]], !noalias ![[NoAliasB:[0-9]*]]
+; SCOPES:      %[[CIdx:[._a-zA-Z0-9]*]] = getelementptr{{.*}} float* %C, i64 %polly.indvar
+; SCOPES:      load float* %[[CIdx]], align 4, !alias.scope ![[AliasScopeC:[0-9]*]], !noalias ![[NoAliasC:[0-9]*]]
+; SCOPES:      %[[AIdx:[._a-zA-Z0-9]*]] = getelementptr{{.*}} i32* %A, i64 %polly.indvar
+; SCOPES:      store i32 %{{[._a-zA-Z0-9]*}}, i32* %[[AIdx]], align 4, !alias.scope ![[AliasScopeA:[0-9]*]], !noalias ![[NoAliasA:[0-9]*]]
+;
+; SCOPES:      ![[AliasScopeB]] = distinct !{![[AliasScopeB]], !{{[0-9]*}}, !"polly.alias.scope.B"}
+; SCOPES:      ![[NoAliasB]] = !{
+; SCOPES-DAG:     ![[AliasScopeA]]
+; SCOPES-DAG:     ![[AliasScopeC]]
+; SCOPES:       }
+; SCOPES-DAG:  ![[AliasScopeA]] = distinct !{![[AliasScopeA]], !{{[0-9]*}}, !"polly.alias.scope.A"}
+; SCOPES-DAG:  ![[AliasScopeC]] = distinct !{![[AliasScopeC]], !{{[0-9]*}}, !"polly.alias.scope.C"}
+; SCOPES:      ![[NoAliasC]] = !{
+; SCOPES-DAG:     ![[AliasScopeA]]
+; SCOPES-DAG:     ![[AliasScopeB]]
+; SCOPES:       }
+; SCOPES:      ![[NoAliasA]] = !{
+; SCOPES-DAG:     ![[AliasScopeB]]
+; SCOPES-DAG:     ![[AliasScopeC]]
+; SCOPES:       }
+;
+; NOSCOPES:    %[[BIdx:[._a-zA-Z0-9]*]] = getelementptr{{.*}} i32* %B, i64 %polly.indvar
+; NOSCOPES:    load i32* %[[BIdx]]
+; NOSCOPES-NOT: alias.scope
+; NOSCOPES-NOT: noalias
+; NOSCOPES:    %[[CIdx:[._a-zA-Z0-9]*]] = getelementptr{{.*}} float* %C, i64 %polly.indvar
+; NOSCOPES:    load float* %[[CIdx]]
+; NOSCOPES-NOT: alias.scope
+; NOSCOPES-NOT: noalias
+; NOSCOPES:    %[[AIdx:[._a-zA-Z0-9]*]] = getelementptr{{.*}} i32* %A, i64 %polly.indvar
+; NOSCOPES:    store i32 %{{[._a-zA-Z0-9]*}}, i32* %[[AIdx]]
+; NOSCOPES-NOT: alias.scope
+; NOSCOPES-NOT: noalias
+;
+; NOSCOPES-NOT: !
+;
+;    void jd(int *A, int *B, float *C) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[i] + C[i];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, float* %C) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %B, i64 %indvars.iv
+  %tmp = load i32* %arrayidx, align 4
+  %conv = sitofp i32 %tmp to float
+  %arrayidx2 = getelementptr inbounds float* %C, i64 %indvars.iv
+  %tmp1 = load float* %arrayidx2, align 4
+  %add = fadd fast float %conv, %tmp1
+  %conv3 = fptosi float %add to i32
+  %arrayidx5 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %conv3, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/blas_sscal_simplified.ll b/final/test/Isl/CodeGen/blas_sscal_simplified.ll
new file mode 100644
index 0000000..af847b6
--- /dev/null
+++ b/final/test/Isl/CodeGen/blas_sscal_simplified.ll
@@ -0,0 +1,44 @@
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+;
+; Regression test for a bug in the runtime check generation.
+
+; This was extracted from the blas testcase. It crashed in one
+; part of the runtime check generation at some point. To be
+; precise, we couldn't find a suitable block to put the RTC code in.
+;
+; int sscal(int n, float sa, float *sx) {
+;   for(int i=0; i<n; i++, sx++)
+;     *sx *= sa;
+;   return 0;
+; }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define i32 @sscal(i32 %n, float %sa, float* %sx) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  %cmp1 = icmp sgt i32 %n, 0
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:                                   ; preds = %entry.split
+  %0 = zext i32 %n to i64
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.body
+  %indvar = phi i64 [ 0, %for.body.lr.ph ], [ %indvar.next, %for.body ]
+  %sx.addr.02 = getelementptr float* %sx, i64 %indvar
+  %tmp = load float* %sx.addr.02, align 4
+  %mul = fmul float %tmp, %sa
+  store float %mul, float* %sx.addr.02, align 4
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp ne i64 %indvar.next, %0
+  br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry.split
+  ret i32 0
+}
diff --git a/final/test/Isl/CodeGen/constant_condition.ll b/final/test/Isl/CodeGen/constant_condition.ll
new file mode 100644
index 0000000..c62d59a
--- /dev/null
+++ b/final/test/Isl/CodeGen/constant_condition.ll
@@ -0,0 +1,56 @@
+;RUN: opt %loadPolly -polly-prepare -polly-detect-scops-in-regions-without-loops -polly-detect-scops-in-functions-without-loops -polly-ast -analyze < %s | FileCheck %s
+
+;#include <string.h>
+;int A[1];
+;
+;void constant_condition () {
+;  int a = 0;
+;  int b = 0;
+;
+;  if (a == b)
+;    A[0] = 0;
+;  else
+;    A[0] = 1;
+;}
+;
+;int main () {
+;  int i;
+;
+;  A[0] = 2;
+;
+;  constant_condition();
+;
+;  return A[0];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+@A = common global [1 x i32] zeroinitializer, align 4 ; <[1 x i32]*> [#uses=1]
+
+define void @constant_condition() nounwind {
+bb:
+  %tmp = icmp eq i32 0, 0                         ; <i1> [#uses=0]
+  br i1 true, label %bb1, label %bb2
+
+bb1:                                              ; preds = %bb
+  store i32 0, i32* getelementptr inbounds ([1 x i32]* @A, i32 0, i32 0)
+  br label %bb3
+
+bb2:                                              ; preds = %bb
+  store i32 1, i32* getelementptr inbounds ([1 x i32]* @A, i32 0, i32 0)
+  br label %bb3
+
+bb3:                                              ; preds = %bb2, %bb1
+  ret void
+}
+
+define i32 @main() nounwind {
+bb:
+  store i32 2, i32* getelementptr inbounds ([1 x i32]* @A, i32 0, i32 0)
+  call void @constant_condition()
+  %tmp = load i32* getelementptr inbounds ([1 x i32]* @A, i32 0, i32 0) ; <i32> [#uses=1]
+  ret i32 %tmp
+}
+
+
+; CHECK: Stmt_bb1();
diff --git a/final/test/Isl/CodeGen/create-conditional-scop.ll b/final/test/Isl/CodeGen/create-conditional-scop.ll
new file mode 100644
index 0000000..d0e6e94
--- /dev/null
+++ b/final/test/Isl/CodeGen/create-conditional-scop.ll
@@ -0,0 +1,29 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl -verify-loop-info < %s -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32"
+target triple = "hexagon-unknown-linux-gnu"
+
+; This test case used to fail, because we did not add the newly generated basic
+; block %polly.start as a basic block to the surrounding loop.
+define void @foo() nounwind {
+entry:
+  br i1 undef, label %while.cond14.preheader, label %for.body7.single_entry.single_entry
+
+while.cond14.preheader:                           ; preds = %for.inc02, %for.body7.single_entry.single_entry, %entry
+  ret void
+
+for.body7.single_entry.single_entry:              ; preds = %for.inc02, %entry
+  br i1 undef, label %while.cond14.preheader, label %while.body
+
+while.body:                                       ; preds = %while.body, %for.body7.single_entry.single_entry
+  %indvar35 = phi i32 [ %0, %while.body ], [ 0, %for.body7.single_entry.single_entry ]
+  %0 = add i32 %indvar35, 1
+  %exitcond2 = icmp eq i32 %0, 0
+  br i1 %exitcond2, label %for.inc02, label %while.body
+
+for.inc02:                                        ; preds = %while.body
+  br i1 undef, label %while.cond14.preheader, label %for.body7.single_entry.single_entry
+}
+
+; CHECK: polly.split_new_and_old
+; CHECK: br i1 true, label %polly.start, label %while.body
diff --git a/final/test/Isl/CodeGen/debug-intrinsics.ll b/final/test/Isl/CodeGen/debug-intrinsics.ll
new file mode 100644
index 0000000..53c48ef
--- /dev/null
+++ b/final/test/Isl/CodeGen/debug-intrinsics.ll
@@ -0,0 +1,80 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @foo(float* %A, i64 %N) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  tail call void @llvm.dbg.value(metadata float* %A, i64 0, metadata !14, metadata !{!"0x102"}), !dbg !15
+  tail call void @llvm.dbg.value(metadata i64 %N, i64 0, metadata !16, metadata !{!"0x102"}), !dbg !15
+  tail call void @llvm.dbg.value(metadata i64 0, i64 0, metadata !18, metadata !{!"0x102"}), !dbg !20
+  %cmp1 = icmp sgt i64 %N, 0, !dbg !20
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end, !dbg !20
+
+for.body.lr.ph:                                   ; preds = %entry.split
+  br label %for.body, !dbg !20
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.body
+  %0 = phi i64 [ 0, %for.body.lr.ph ], [ %1, %for.body ], !dbg !21
+  %arrayidx = getelementptr float* %A, i64 %0, !dbg !21
+  %conv = sitofp i64 %0 to float, !dbg !21
+  store float %conv, float* %arrayidx, align 4, !dbg !21
+  %1 = add nsw i64 %0, 1, !dbg !20
+  tail call void @llvm.dbg.value(metadata i64 %1, i64 0, metadata !18, metadata !{!"0x102"}), !dbg !20
+  %exitcond = icmp ne i64 %1, %N, !dbg !20
+  br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge, !dbg !20
+
+for.cond.for.end_crit_edge:                       ; preds = %for.body
+  br label %for.end, !dbg !20
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry.split
+  ret void, !dbg !22
+}
+
+; CHECK: polly.split_new_and_old:
+
+; CHECK: tail call void @llvm.dbg.value
+; CHECK: tail call void @llvm.dbg.value
+; CHECK: tail call void @llvm.dbg.value
+; CHECK: tail call void @llvm.dbg.value
+; CHECK-NOT: tail call void @llvm.dbg.value
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12}
+!llvm.ident = !{!13}
+
+!0 = !{!"0x11\0012\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/grosser/Projects/polly/git/tools/polly/loop.c] [DW_LANG_C99]
+!1 = !{!"loop.c", !"/home/grosser/Projects/polly/git/tools/polly"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (float*, i64)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [/home/grosser/Projects/polly/git/tools/polly/loop.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{null, !8, !10}
+!8 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from float]
+!9 = !{!"0x24\00float\000\0032\0032\000\000\004", null, null} ; [ DW_TAG_base_type ] [float] [line 0, size 32, align 32, offset 0, enc DW_ATE_float]
+!10 = !{!"0x24\00long int\000\0064\0064\000\000\005", null, null} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed]
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 1, !"Debug Info Version", i32 2}
+!13 = !{!"clang version 3.5 "}
+!14 = !{!"0x101\00A\0016777217\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [A] [line 1]
+!15 = !MDLocation(line: 1, scope: !4)
+!16 = !{!"0x101\00N\0033554433\000", !4, !5, !10} ; [ DW_TAG_arg_variable ] [N] [line 1]
+!17 = !{i64 0}
+!18 = !{!"0x100\00i\002\000", !19, !5, !10} ; [ DW_TAG_auto_variable ] [i] [line 2]
+!19 = !{!"0xb\002\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/loop.c]
+!20 = !MDLocation(line: 2, scope: !19)
+!21 = !MDLocation(line: 3, scope: !19)
+!22 = !MDLocation(line: 4, scope: !4)
diff --git a/final/test/Isl/CodeGen/loop_with_condition.ll b/final/test/Isl/CodeGen/loop_with_condition.ll
new file mode 100644
index 0000000..d8e0ab9
--- /dev/null
+++ b/final/test/Isl/CodeGen/loop_with_condition.ll
@@ -0,0 +1,175 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -analyze < %s | FileCheck %s
+
+;#include <string.h>
+;#define N 1024
+;int A[N];
+;int B[N];
+;
+;void loop_with_condition() {
+;  int i;
+;
+;  __sync_synchronize();
+;  for (i = 0; i < N; i++) {
+;    if (i <= N / 2)
+;      A[i] = 1;
+;    else
+;      A[i] = 2;
+;    B[i] = 3;
+;  }
+;  __sync_synchronize();
+;}
+;
+;int main () {
+;  int i;
+;
+;  memset(A, 0, sizeof(int) * N);
+;  memset(B, 0, sizeof(int) * N);
+;
+;  loop_with_condition();
+;
+;  for (i = 0; i < N; i++)
+;    if (B[i] != 3)
+;      return 1;
+;
+;  for (i = 0; i < N; i++)
+;    if (i <= N / 2 && A[i] != 1)
+;      return 1;
+;    else if (i > N / 2 && A[i] != 2)
+;      return 1;
+;  return 0;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=4]
+@B = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=4]
+
+define void @loop_with_condition() nounwind {
+; <label>:0
+  fence seq_cst
+  br label %1
+
+; <label>:1                                       ; preds = %7, %0
+  %indvar = phi i64 [ %indvar.next, %7 ], [ 0, %0 ] ; <i64> [#uses=5]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %scevgep1 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar to i32                 ; <i32> [#uses=1]
+  %exitcond = icmp ne i64 %indvar, 1024           ; <i1> [#uses=1]
+  br i1 %exitcond, label %2, label %8
+
+; <label>:2                                       ; preds = %1
+  %3 = icmp sle i32 %i.0, 512                     ; <i1> [#uses=1]
+  br i1 %3, label %4, label %5
+
+; <label>:4                                       ; preds = %2
+  store i32 1, i32* %scevgep
+  br label %6
+
+; <label>:5                                       ; preds = %2
+  store i32 2, i32* %scevgep
+  br label %6
+
+; <label>:6                                       ; preds = %5, %4
+  store i32 3, i32* %scevgep1
+  br label %7
+
+; <label>:7                                       ; preds = %6
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %1
+
+; <label>:8                                       ; preds = %1
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+; <label>:0
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @A to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @B to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @loop_with_condition()
+  br label %1
+
+; <label>:1                                       ; preds = %8, %0
+  %indvar1 = phi i64 [ %indvar.next2, %8 ], [ 0, %0 ] ; <i64> [#uses=3]
+  %scevgep3 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar1 ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar1 to i32                ; <i32> [#uses=1]
+  %2 = icmp slt i32 %i.0, 1024                    ; <i1> [#uses=1]
+  br i1 %2, label %3, label %9
+
+; <label>:3                                       ; preds = %1
+  %4 = load i32* %scevgep3                        ; <i32> [#uses=1]
+  %5 = icmp ne i32 %4, 3                          ; <i1> [#uses=1]
+  br i1 %5, label %6, label %7
+
+; <label>:6                                       ; preds = %3
+  br label %28
+
+; <label>:7                                       ; preds = %3
+  br label %8
+
+; <label>:8                                       ; preds = %7
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=1]
+  br label %1
+
+; <label>:9                                       ; preds = %1
+  br label %10
+
+; <label>:10                                      ; preds = %26, %9
+  %indvar = phi i64 [ %indvar.next, %26 ], [ 0, %9 ] ; <i64> [#uses=3]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %i.1 = trunc i64 %indvar to i32                 ; <i32> [#uses=3]
+  %11 = icmp slt i32 %i.1, 1024                   ; <i1> [#uses=1]
+  br i1 %11, label %12, label %27
+
+; <label>:12                                      ; preds = %10
+  %13 = icmp sle i32 %i.1, 512                    ; <i1> [#uses=1]
+  br i1 %13, label %14, label %18
+
+; <label>:14                                      ; preds = %12
+  %15 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %16 = icmp ne i32 %15, 1                        ; <i1> [#uses=1]
+  br i1 %16, label %17, label %18
+
+; <label>:17                                      ; preds = %14
+  br label %28
+
+; <label>:18                                      ; preds = %14, %12
+  %19 = icmp sgt i32 %i.1, 512                    ; <i1> [#uses=1]
+  br i1 %19, label %20, label %24
+
+; <label>:20                                      ; preds = %18
+  %21 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %22 = icmp ne i32 %21, 2                        ; <i1> [#uses=1]
+  br i1 %22, label %23, label %24
+
+; <label>:23                                      ; preds = %20
+  br label %28
+
+; <label>:24                                      ; preds = %20, %18
+  br label %25
+
+; <label>:25                                      ; preds = %24
+  br label %26
+
+; <label>:26                                      ; preds = %25
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %10
+
+; <label>:27                                      ; preds = %10
+  br label %28
+
+; <label>:28                                      ; preds = %27, %23, %17, %6
+  %.0 = phi i32 [ 1, %6 ], [ 1, %17 ], [ 1, %23 ], [ 0, %27 ] ; <i32> [#uses=1]
+  ret i32 %.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) {
+; CHECK:   if (c0 >= 513) {
+; CHECK:     Stmt_5(c0);
+; CHECK:   } else
+; CHECK:     Stmt_4(c0);
+; CHECK:   Stmt_6(c0);
+; CHECK: }
diff --git a/final/test/Isl/CodeGen/loop_with_condition_2.ll b/final/test/Isl/CodeGen/loop_with_condition_2.ll
new file mode 100644
index 0000000..fc75121
--- /dev/null
+++ b/final/test/Isl/CodeGen/loop_with_condition_2.ll
@@ -0,0 +1,141 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+
+; Verify that we actually detect this loop as the innermost loop even though
+; there is a conditional inside.
+
+; CHECK: #pragma simd
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) {
+; CHECK:   if (c0 >= m + 1025) {
+; CHECK:     Stmt_if_else(c0);
+; CHECK:   } else
+; CHECK:     Stmt_if_then(c0);
+; CHECK:   Stmt_if_end(c0);
+; CHECK: }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer, align 16
+@B = common global [1024 x i32] zeroinitializer, align 16
+
+define void @loop_with_condition(i32 %m) nounwind {
+entry:
+  fence seq_cst
+  %tmp = sub i32 0, %m
+  %tmp1 = zext i32 %tmp to i64
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %arrayidx = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar
+  %arrayidx10 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar
+  %tmp2 = add i64 %tmp1, %indvar
+  %sub = trunc i64 %tmp2 to i32
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %cmp3 = icmp sle i32 %sub, 1024
+  br i1 %cmp3, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.body
+  store i32 1, i32* %arrayidx
+  br label %if.end
+
+if.else:                                          ; preds = %for.body
+  store i32 2, i32* %arrayidx
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  store i32 3, i32* %arrayidx10
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+entry:
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @A to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @B to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @loop_with_condition(i32 5)
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.inc ], [ 0, %entry ]
+  %arrayidx = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar1
+  %i.0 = trunc i64 %indvar1 to i32
+  %cmp = icmp slt i32 %i.0, 1024
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp3 = load i32* %arrayidx
+  %cmp4 = icmp ne i32 %tmp3, 3
+  br i1 %cmp4, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body
+  br label %return
+
+if.end:                                           ; preds = %for.body
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvar.next2 = add i64 %indvar1, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc12, %for.end
+  %indvar = phi i64 [ %indvar.next, %for.inc12 ], [ 0, %for.end ]
+  %arrayidx15 = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar
+  %i.1 = trunc i64 %indvar to i32
+  %cmp8 = icmp slt i32 %i.1, 1024
+  br i1 %cmp8, label %for.body9, label %for.end35
+
+for.body9:                                        ; preds = %for.cond6
+  br i1 true, label %land.lhs.true, label %if.else
+
+land.lhs.true:                                    ; preds = %for.body9
+  %tmp16 = load i32* %arrayidx15
+  %cmp17 = icmp ne i32 %tmp16, 1
+  br i1 %cmp17, label %if.then18, label %if.else
+
+if.then18:                                        ; preds = %land.lhs.true
+  br label %return
+
+if.else:                                          ; preds = %land.lhs.true, %for.body9
+  br i1 false, label %land.lhs.true23, label %if.end30
+
+land.lhs.true23:                                  ; preds = %if.else
+  %tmp27 = load i32* %arrayidx15
+  %cmp28 = icmp ne i32 %tmp27, 2
+  br i1 %cmp28, label %if.then29, label %if.end30
+
+if.then29:                                        ; preds = %land.lhs.true23
+  br label %return
+
+if.end30:                                         ; preds = %land.lhs.true23, %if.else
+  br label %if.end31
+
+if.end31:                                         ; preds = %if.end30
+  br label %for.inc12
+
+for.inc12:                                        ; preds = %if.end31
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond6
+
+for.end35:                                        ; preds = %for.cond6
+  br label %return
+
+return:                                           ; preds = %for.end35, %if.then29, %if.then18, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ 1, %if.then18 ], [ 1, %if.then29 ], [ 0, %for.end35 ]
+  ret i32 %retval.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
diff --git a/final/test/Isl/CodeGen/loop_with_condition_ineq.ll b/final/test/Isl/CodeGen/loop_with_condition_ineq.ll
new file mode 100644
index 0000000..df923bc
--- /dev/null
+++ b/final/test/Isl/CodeGen/loop_with_condition_ineq.ll
@@ -0,0 +1,177 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -analyze < %s | FileCheck %s
+
+;#include <string.h>
+;#define N 1024
+;int A[N];
+;int B[N];
+;
+;void loop_with_condition_ineq() {
+;  int i;
+;
+;  __sync_synchronize();
+;  for (i = 0; i < N; i++) {
+;    if (i != N / 2)
+;      A[i] = 1;
+;    else
+;      A[i] = 2;
+;    B[i] = 3;
+;  }
+;  __sync_synchronize();
+;}
+;
+;int main () {
+;  int i;
+;
+;  memset(A, 0, sizeof(int) * N);
+;  memset(B, 0, sizeof(int) * N);
+;
+;  loop_with_condition_ineq();
+;
+;  for (i = 0; i < N; i++)
+;    if (B[i] != 3)
+;      return 1;
+;
+;  for (i = 0; i < N; i++)
+;    if (i != N / 2 && A[i] != 1)
+;      return 1;
+;    else if (i == N && A[i] != 2)
+;      return 1;
+;  return 0;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=4]
+@B = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=4]
+
+define void @loop_with_condition_ineq() nounwind {
+; <label>:0
+  fence seq_cst
+  br label %1
+
+; <label>:1                                       ; preds = %7, %0
+  %indvar = phi i64 [ %indvar.next, %7 ], [ 0, %0 ] ; <i64> [#uses=5]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %scevgep1 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar to i32                 ; <i32> [#uses=1]
+  %exitcond = icmp ne i64 %indvar, 1024           ; <i1> [#uses=1]
+  br i1 %exitcond, label %2, label %8
+
+; <label>:2                                       ; preds = %1
+  %3 = icmp ne i32 %i.0, 512                      ; <i1> [#uses=1]
+  br i1 %3, label %4, label %5
+
+; <label>:4                                       ; preds = %2
+  store i32 1, i32* %scevgep
+  br label %6
+
+; <label>:5                                       ; preds = %2
+  store i32 2, i32* %scevgep
+  br label %6
+
+; <label>:6                                       ; preds = %5, %4
+  store i32 3, i32* %scevgep1
+  br label %7
+
+; <label>:7                                       ; preds = %6
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %1
+
+; <label>:8                                       ; preds = %1
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+; <label>:0
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @A to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @B to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @loop_with_condition_ineq()
+  br label %1
+
+; <label>:1                                       ; preds = %8, %0
+  %indvar1 = phi i64 [ %indvar.next2, %8 ], [ 0, %0 ] ; <i64> [#uses=3]
+  %scevgep3 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar1 ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar1 to i32                ; <i32> [#uses=1]
+  %2 = icmp slt i32 %i.0, 1024                    ; <i1> [#uses=1]
+  br i1 %2, label %3, label %9
+
+; <label>:3                                       ; preds = %1
+  %4 = load i32* %scevgep3                        ; <i32> [#uses=1]
+  %5 = icmp ne i32 %4, 3                          ; <i1> [#uses=1]
+  br i1 %5, label %6, label %7
+
+; <label>:6                                       ; preds = %3
+  br label %28
+
+; <label>:7                                       ; preds = %3
+  br label %8
+
+; <label>:8                                       ; preds = %7
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=1]
+  br label %1
+
+; <label>:9                                       ; preds = %1
+  br label %10
+
+; <label>:10                                      ; preds = %26, %9
+  %indvar = phi i64 [ %indvar.next, %26 ], [ 0, %9 ] ; <i64> [#uses=3]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %i.1 = trunc i64 %indvar to i32                 ; <i32> [#uses=3]
+  %11 = icmp slt i32 %i.1, 1024                   ; <i1> [#uses=1]
+  br i1 %11, label %12, label %27
+
+; <label>:12                                      ; preds = %10
+  %13 = icmp ne i32 %i.1, 512                     ; <i1> [#uses=1]
+  br i1 %13, label %14, label %18
+
+; <label>:14                                      ; preds = %12
+  %15 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %16 = icmp ne i32 %15, 1                        ; <i1> [#uses=1]
+  br i1 %16, label %17, label %18
+
+; <label>:17                                      ; preds = %14
+  br label %28
+
+; <label>:18                                      ; preds = %14, %12
+  %19 = icmp eq i32 %i.1, 1024                    ; <i1> [#uses=1]
+  br i1 %19, label %20, label %24
+
+; <label>:20                                      ; preds = %18
+  %21 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %22 = icmp ne i32 %21, 2                        ; <i1> [#uses=1]
+  br i1 %22, label %23, label %24
+
+; <label>:23                                      ; preds = %20
+  br label %28
+
+; <label>:24                                      ; preds = %20, %18
+  br label %25
+
+; <label>:25                                      ; preds = %24
+  br label %26
+
+; <label>:26                                      ; preds = %25
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %10
+
+; <label>:27                                      ; preds = %10
+  br label %28
+
+; <label>:28                                      ; preds = %27, %23, %17, %6
+  %.0 = phi i32 [ 1, %6 ], [ 1, %17 ], [ 1, %23 ], [ 0, %27 ] ; <i32> [#uses=1]
+  ret i32 %.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) {
+; CHECK:   if (c0 >= 513) {
+; CHECK:     Stmt_4(c0);
+; CHECK:   } else if (c0 <= 511) {
+; CHECK:     Stmt_4(c0);
+; CHECK:   } else
+; CHECK:     Stmt_5(512);
+; CHECK:   Stmt_6(c0);
+; CHECK: }
diff --git a/final/test/Isl/CodeGen/loop_with_condition_nested.ll b/final/test/Isl/CodeGen/loop_with_condition_nested.ll
new file mode 100644
index 0000000..5d4a61c
--- /dev/null
+++ b/final/test/Isl/CodeGen/loop_with_condition_nested.ll
@@ -0,0 +1,218 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl -loops -analyze < %s | FileCheck %s -check-prefix=LOOPS
+
+
+;#include <string.h>
+;#define N 1024
+;int A[N];
+;int B[N];
+;
+;void loop_with_condition() {
+;  int i;
+;
+;  __sync_synchronize();
+;  for (i = 0; i < N; i++) {
+;    if (i <= N / 2) {
+;      if (i > 20)
+;        A[i] = 1;
+;      else
+;        A[i] = 2;
+;    }
+;    B[i] = 3;
+;  }
+;  __sync_synchronize();
+;}
+;
+;int main () {
+;  int i;
+;
+;  memset(A, 0, sizeof(int) * N);
+;  memset(B, 0, sizeof(int) * N);
+;
+;  loop_with_condition();
+;
+;  for (i = 0; i < N; i++)
+;    if (B[i] != 3)
+;      return 1;
+;
+;  for (i = 0; i < N; i++)
+;    if (i <= N / 2  && i > 20 && A[i] != 1)
+;      return 1;
+;    else if (i > N / 2) {
+;      if (i <= 20 && A[i] != 2)
+;        return 1;
+;      if (i > 20 && A[i] != 0)
+;        return 1;
+;    }
+;  return 0;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=4]
+@B = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=4]
+
+define void @loop_with_condition() nounwind {
+; <label>:0
+  fence seq_cst
+  br label %1
+
+; <label>:1                                       ; preds = %10, %0
+  %indvar = phi i64 [ %indvar.next, %10 ], [ 0, %0 ] ; <i64> [#uses=5]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %scevgep1 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar to i32                 ; <i32> [#uses=2]
+  %exitcond = icmp ne i64 %indvar, 1024           ; <i1> [#uses=1]
+  br i1 %exitcond, label %2, label %11
+
+; <label>:2                                       ; preds = %1
+  %3 = icmp sle i32 %i.0, 512                     ; <i1> [#uses=1]
+  br i1 %3, label %4, label %9
+
+; <label>:4                                       ; preds = %2
+  %5 = icmp sgt i32 %i.0, 20                      ; <i1> [#uses=1]
+  br i1 %5, label %6, label %7
+
+; <label>:6                                       ; preds = %4
+  store i32 1, i32* %scevgep
+  br label %8
+
+; <label>:7                                       ; preds = %4
+  store i32 2, i32* %scevgep
+  br label %8
+
+; <label>:8                                       ; preds = %7, %6
+  br label %9
+
+; <label>:9                                       ; preds = %8, %2
+  store i32 3, i32* %scevgep1
+  br label %10
+
+; <label>:10                                      ; preds = %9
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %1
+
+; <label>:11                                      ; preds = %1
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+; <label>:0
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @A to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @B to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @loop_with_condition()
+  br label %1
+
+; <label>:1                                       ; preds = %8, %0
+  %indvar1 = phi i64 [ %indvar.next2, %8 ], [ 0, %0 ] ; <i64> [#uses=3]
+  %scevgep3 = getelementptr [1024 x i32]* @B, i64 0, i64 %indvar1 ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar1 to i32                ; <i32> [#uses=1]
+  %2 = icmp slt i32 %i.0, 1024                    ; <i1> [#uses=1]
+  br i1 %2, label %3, label %9
+
+; <label>:3                                       ; preds = %1
+  %4 = load i32* %scevgep3                        ; <i32> [#uses=1]
+  %5 = icmp ne i32 %4, 3                          ; <i1> [#uses=1]
+  br i1 %5, label %6, label %7
+
+; <label>:6                                       ; preds = %3
+  br label %39
+
+; <label>:7                                       ; preds = %3
+  br label %8
+
+; <label>:8                                       ; preds = %7
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=1]
+  br label %1
+
+; <label>:9                                       ; preds = %1
+  br label %10
+
+; <label>:10                                      ; preds = %37, %9
+  %indvar = phi i64 [ %indvar.next, %37 ], [ 0, %9 ] ; <i64> [#uses=3]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=3]
+  %i.1 = trunc i64 %indvar to i32                 ; <i32> [#uses=6]
+  %11 = icmp slt i32 %i.1, 1024                   ; <i1> [#uses=1]
+  br i1 %11, label %12, label %38
+
+; <label>:12                                      ; preds = %10
+  %13 = icmp sle i32 %i.1, 512                    ; <i1> [#uses=1]
+  br i1 %13, label %14, label %20
+
+; <label>:14                                      ; preds = %12
+  %15 = icmp sgt i32 %i.1, 20                     ; <i1> [#uses=1]
+  br i1 %15, label %16, label %20
+
+; <label>:16                                      ; preds = %14
+  %17 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %18 = icmp ne i32 %17, 1                        ; <i1> [#uses=1]
+  br i1 %18, label %19, label %20
+
+; <label>:19                                      ; preds = %16
+  br label %39
+
+; <label>:20                                      ; preds = %16, %14, %12
+  %21 = icmp sgt i32 %i.1, 512                    ; <i1> [#uses=1]
+  br i1 %21, label %22, label %35
+
+; <label>:22                                      ; preds = %20
+  %23 = icmp sle i32 %i.1, 20                     ; <i1> [#uses=1]
+  br i1 %23, label %24, label %28
+
+; <label>:24                                      ; preds = %22
+  %25 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %26 = icmp ne i32 %25, 2                        ; <i1> [#uses=1]
+  br i1 %26, label %27, label %28
+
+; <label>:27                                      ; preds = %24
+  br label %39
+
+; <label>:28                                      ; preds = %24, %22
+  %29 = icmp sgt i32 %i.1, 20                     ; <i1> [#uses=1]
+  br i1 %29, label %30, label %34
+
+; <label>:30                                      ; preds = %28
+  %31 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %32 = icmp ne i32 %31, 0                        ; <i1> [#uses=1]
+  br i1 %32, label %33, label %34
+
+; <label>:33                                      ; preds = %30
+  br label %39
+
+; <label>:34                                      ; preds = %30, %28
+  br label %35
+
+; <label>:35                                      ; preds = %34, %20
+  br label %36
+
+; <label>:36                                      ; preds = %35
+  br label %37
+
+; <label>:37                                      ; preds = %36
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %10
+
+; <label>:38                                      ; preds = %10
+  br label %39
+
+; <label>:39                                      ; preds = %38, %33, %27, %19, %6
+  %.0 = phi i32 [ 1, %6 ], [ 1, %19 ], [ 1, %27 ], [ 1, %33 ], [ 0, %38 ] ; <i32> [#uses=1]
+  ret i32 %.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1) {
+; CHECK:   if (c0 <= 20) {
+; CHECK:     Stmt_7(c0);
+; CHECK:   } else if (c0 <= 512)
+; CHECK:     Stmt_6(c0);
+; CHECK:   Stmt_9(c0);
+; CHECK: }
+
+; LOOPS: Printing analysis 'Natural Loop Information' for function 'loop_with_condition':
+; LOOPS: Loop at depth 1 containing: %1<header><exiting>,%2,%4,%7,%6,%8,%9,%10<latch>
+; LOOPS: Loop at depth 1 containing:
+; LOOPS: %polly.loop_header<header>,%polly.cond,%polly.merge,%polly.then,%polly.else,%polly.stmt.,%polly.cond3,%polly.merge4,%polly.then5,%polly.else6,%polly.stmt.7,%polly.stmt{{.*}}<latch><exiting>
diff --git a/final/test/Isl/CodeGen/loop_with_conditional_entry_edge_splited_hard_case.ll b/final/test/Isl/CodeGen/loop_with_conditional_entry_edge_splited_hard_case.ll
new file mode 100644
index 0000000..997a24c
--- /dev/null
+++ b/final/test/Isl/CodeGen/loop_with_conditional_entry_edge_splited_hard_case.ll
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s
+;
+; Test case to trigger the hard way of creating a unique entering
+; edge for the SCoP. It is triggered because the entering edge
+; here: %while.begin --> %if is __not__ critical.
+;
+;    int f(void);
+;    void jd(int b, int *A) {
+;      while (f()) {
+;        if (b)
+;          for (int i = 0; i < 1024; i++)
+;            A[i] = i;
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32 %b, i32* %A) {
+entry:
+  br label %while.begin
+
+; CHECK: while.begin:
+while.begin:
+; CHECK:  %call = call i32 @f()
+  %call = call i32 @f()
+; CHECK:  %tobool = icmp eq i32 %call, 0
+  %tobool = icmp eq i32 %call, 0
+; CHECK:  br i1 %tobool, label %while.end, label %polly.entering.block
+  br i1 %tobool, label %while.end, label %if
+
+; CHECK: polly.entering.block:
+; CHECK:   br label %polly.split_new_and_old
+
+; CHECK: polly.split_new_and_old:
+; CHECK:   br i1 true, label %polly.start, label %if.split
+
+; CHECK: if.split:
+if:                                               ; preds = %while.begin
+; CHECK: %tobool2 = icmp eq i32 %b, 0
+  %tobool2 = icmp eq i32 %b, 0
+; CHECK: br i1 %tobool2, label %while.begin{{[a-zA-Z._]*}}, label %for.cond
+  br i1 %tobool2, label %while.begin, label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %if
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %if ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %while.begin
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
+  %tmp = trunc i64 %indvars.iv to i32
+  store i32 %tmp, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+while.end:                                        ; preds = %entry, %for.cond
+  ret void
+}
+
+declare i32 @f()
diff --git a/final/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll b/final/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll
new file mode 100644
index 0000000..a49151c
--- /dev/null
+++ b/final/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll
@@ -0,0 +1,45 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Derived from the following code:
+;
+; void foo(long n, long m, double A[n][m]) {
+;   for (long i = 0; i < 100; i++)
+;     for (long j = 0; j < 150; j++)
+;       A[i][j] = 1.0;
+; }
+;
+; CHECK: entry:
+; CHECK: %0 = icmp sge i64 %m, 150
+; CHECK: %1 = select i1 %0, i64 1, i64 0
+; CHECK: %2 = icmp ne i64 %1, 0
+; CHECK: polly.split_new_and_old:
+; CHECK: br i1 %2, label %polly.start, label %for.i
+
+define void @foo(i64 %n, i64 %m, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  %tmp = mul nsw i64 %i, %m
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j ]
+  %vlaarrayidx.sum = add i64 %j, %tmp
+  %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum
+  store double 1.0, double* %arrayidx
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, 150
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, 100
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/multidim_alias_check.ll b/final/test/Isl/CodeGen/multidim_alias_check.ll
new file mode 100644
index 0000000..e692f27
--- /dev/null
+++ b/final/test/Isl/CodeGen/multidim_alias_check.ll
@@ -0,0 +1,42 @@
+; RUN: opt %loadPolly -polly-codegen-isl -polly-delinearize < %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: %polly.access.sext.A = sext i32 %n to i64
+; CHECK: %polly.access.mul.A = mul i64 %polly.access.sext.A, %0
+; CHECK: %polly.access.add.A = add i64 %polly.access.mul.A, 1
+; CHECK: %polly.access.A = getelementptr double* %A, i64 %polly.access.add.A
+; CHECK: %polly.access.y = getelementptr double* %y, i64 0
+; CHECK: icmp ule double* %polly.access.A, %polly.access.y
+
+
+define void @init_array(i32 %n, double* %A, double* %y) {
+entry:
+  %add3 = add nsw i32 %n, 1
+  %tmp = zext i32 %add3 to i64
+  br label %for.body
+
+for.body:
+  %i.04 = phi i32 [ %inc39, %for.cond.loopexit ], [ 0, %entry ]
+  %arrayidx16 = getelementptr inbounds double* %y, i64 0
+  store double 1.0, double* %arrayidx16
+  %cmp251 = icmp slt i32 %n, 0
+  %inc39 = add nsw i32 %i.04, 1
+  br i1 %cmp251, label %for.cond.loopexit, label %for.body27
+
+for.body27:
+  %idxprom35 = sext i32 %i.04 to i64
+  %tmp1 = mul nsw i64 %idxprom35, %tmp
+  %arrayidx36.sum = add i64 0, %tmp1
+  %arrayidx37 = getelementptr inbounds double* %A, i64 %arrayidx36.sum
+  store double 1.0, double* %arrayidx37
+  br label %for.cond.loopexit
+
+for.cond.loopexit:
+  %cmp = icmp slt i32 %i.04, %n
+  br i1 %cmp, label %for.body, label %for.end40
+
+
+for.end40:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/no_guard_bb.ll b/final/test/Isl/CodeGen/no_guard_bb.ll
new file mode 100644
index 0000000..b5bf88b
--- /dev/null
+++ b/final/test/Isl/CodeGen/no_guard_bb.ll
@@ -0,0 +1,33 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S -verify-dom-info < %s | FileCheck %s
+;
+; CHECK-NOT: br i1 true, label %polly.{{.*}}, label %polly.{{.*}}
+;
+;    void jd(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = i;
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i64 %indvars.iv
+  %tmp = trunc i64 %indvars.iv to i32
+  store i32 %tmp, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/openmp_limit_threads.ll b/final/test/Isl/CodeGen/openmp_limit_threads.ll
new file mode 100644
index 0000000..fff0155
--- /dev/null
+++ b/final/test/Isl/CodeGen/openmp_limit_threads.ll
@@ -0,0 +1,54 @@
+; RUN: opt %loadPolly -polly-codegen-isl -polly-parallel -S < %s | FileCheck %s --check-prefix=AUTO
+; RUN: opt %loadPolly -polly-codegen-isl -polly-parallel -polly-num-threads=1 -S < %s | FileCheck %s --check-prefix=ONE
+; RUN: opt %loadPolly -polly-codegen-isl -polly-parallel -polly-num-threads=4 -S < %s | FileCheck %s --check-prefix=FOUR
+;
+; AUTO: call void @GOMP_parallel_loop_runtime_start(void (i8*)* @jd.polly.subfn, i8* %polly.par.userContext{{[0-9]*}}, i32 0, i64 0, i64 1024, i64 1)
+; ONE: call void @GOMP_parallel_loop_runtime_start(void (i8*)* @jd.polly.subfn, i8* %polly.par.userContext{{[0-9]*}}, i32 1, i64 0, i64 1024, i64 1)
+; FOUR: call void @GOMP_parallel_loop_runtime_start(void (i8*)* @jd.polly.subfn, i8* %polly.par.userContext{{[0-9]*}}, i32 4, i64 0, i64 1024, i64 1)
+;
+;    void jd(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        for (int j = 0; j < 1024; j++)
+;          A[i + j * 1024] = 0;
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc4 ], [ 0, %entry ]
+  %exitcond5 = icmp ne i64 %indvars.iv3, 1024
+  br i1 %exitcond5, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %tmp = shl nsw i64 %indvars.iv, 10
+  %tmp6 = add nsw i64 %indvars.iv3, %tmp
+  %arrayidx = getelementptr inbounds i32* %A, i64 %tmp6
+  store i32 0, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %indvars.iv.next4 = add nuw nsw i64 %indvars.iv3, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/reduction.ll b/final/test/Isl/CodeGen/reduction.ll
new file mode 100644
index 0000000..d40e3bc
--- /dev/null
+++ b/final/test/Isl/CodeGen/reduction.ll
@@ -0,0 +1,89 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s 2>&1 | not FileCheck %s
+
+;#include <string.h>
+;#include <stdio.h>
+;#define N 1021
+;
+;int main () {
+;  int i;
+;  int A[N];
+;  int red;
+;
+;  memset(A, 0, sizeof(int) * N);
+;
+;  A[0] = 1;
+;  A[1] = 1;
+;  red = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 2; i < N; i++) {
+;    A[i] = A[i-1] + A[i-2];
+;    red += A[i-2];
+;  }
+;
+;  __sync_synchronize();
+;
+;  if (red != 382399368)
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define i32 @main() nounwind {
+; <label>:0
+  %A = alloca [1021 x i32], align 16              ; <[1021 x i32]*> [#uses=6]
+  %1 = getelementptr inbounds [1021 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %2 = bitcast i32* %1 to i8*                     ; <i8*> [#uses=1]
+  call void @llvm.memset.p0i8.i64(i8* %2, i8 0, i64 4084, i32 1, i1 false)
+  %3 = getelementptr inbounds [1021 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %4 = getelementptr inbounds i32* %3, i64 0      ; <i32*> [#uses=1]
+  store i32 1, i32* %4
+  %5 = getelementptr inbounds [1021 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %6 = getelementptr inbounds i32* %5, i64 1      ; <i32*> [#uses=1]
+  store i32 1, i32* %6
+  fence seq_cst
+  br label %7
+
+; <label>:7                                       ; preds = %14, %0
+  %indvar = phi i64 [ %indvar.next, %14 ], [ 0, %0 ] ; <i64> [#uses=5]
+  %red.0 = phi i32 [ 0, %0 ], [ %13, %14 ]        ; <i32> [#uses=2]
+  %scevgep = getelementptr [1021 x i32]* %A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %tmp = add i64 %indvar, 2                       ; <i64> [#uses=1]
+  %scevgep1 = getelementptr [1021 x i32]* %A, i64 0, i64 %tmp ; <i32*> [#uses=1]
+  %tmp2 = add i64 %indvar, 1                      ; <i64> [#uses=1]
+  %scevgep3 = getelementptr [1021 x i32]* %A, i64 0, i64 %tmp2 ; <i32*> [#uses=1]
+  %exitcond = icmp ne i64 %indvar, 1019           ; <i1> [#uses=1]
+  br i1 %exitcond, label %8, label %15
+
+; <label>:8                                       ; preds = %7
+  %9 = load i32* %scevgep3                        ; <i32> [#uses=1]
+  %10 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %11 = add nsw i32 %9, %10                       ; <i32> [#uses=1]
+  store i32 %11, i32* %scevgep1
+  %12 = load i32* %scevgep                        ; <i32> [#uses=1]
+  %13 = add nsw i32 %red.0, %12                   ; <i32> [#uses=1]
+  br label %14
+
+; <label>:14                                      ; preds = %8
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %7
+
+; <label>:15                                      ; preds = %7
+  %red.0.lcssa = phi i32 [ %red.0, %7 ]           ; <i32> [#uses=1]
+  fence seq_cst
+  %16 = icmp ne i32 %red.0.lcssa, 382399368       ; <i1> [#uses=1]
+  br i1 %16, label %17, label %18
+
+; <label>:17                                      ; preds = %15
+  br label %18
+
+; <label>:18                                      ; preds = %17, %15
+  %.0 = phi i32 [ 1, %17 ], [ 0, %15 ]            ; <i32> [#uses=1]
+  ret i32 %.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK:  Could not generate independent blocks
diff --git a/final/test/Isl/CodeGen/reduction_2.ll b/final/test/Isl/CodeGen/reduction_2.ll
new file mode 100644
index 0000000..1bcff98
--- /dev/null
+++ b/final/test/Isl/CodeGen/reduction_2.ll
@@ -0,0 +1,93 @@
+; RUN: opt %loadPolly -basicaa -polly-ast -analyze < %s | FileCheck %s
+
+;#include <string.h>
+;#include <stdio.h>
+;#define N 1021
+;
+;int main () {
+;  int i;
+;  int A[N];
+;  int RED[1];
+;
+;  memset(A, 0, sizeof(int) * N);
+;
+;  A[0] = 1;
+;  A[1] = 1;
+;  RED[0] = 0;
+;
+;  for (i = 2; i < N; i++) {
+;    A[i] = A[i-1] + A[i-2];
+;    RED[0] += A[i-2];
+;  }
+;
+;  if (RED[0] != 382399368)
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [1021 x i32], align 4               ; <[1021 x i32]*> [#uses=6]
+  %RED = alloca [1 x i32], align 4                ; <[1 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [1021 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %conv = bitcast i32* %arraydecay to i8*         ; <i8*> [#uses=1]
+  call void @llvm.memset.p0i8.i64(i8* %conv, i8 0, i64 4084, i32 1, i1 false)
+  %arraydecay1 = getelementptr inbounds [1021 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx = getelementptr inbounds i32* %arraydecay1, i64 0 ; <i32*> [#uses=1]
+  store i32 1, i32* %arrayidx
+  %arraydecay2 = getelementptr inbounds [1021 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx3 = getelementptr inbounds i32* %arraydecay2, i64 1 ; <i32*> [#uses=1]
+  store i32 1, i32* %arrayidx3
+  %arraydecay4 = getelementptr inbounds [1 x i32]* %RED, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx5 = getelementptr inbounds i32* %arraydecay4, i64 0 ; <i32*> [#uses=1]
+  store i32 0, i32* %arrayidx5
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ] ; <i64> [#uses=5]
+  %arrayidx15 = getelementptr [1021 x i32]* %A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %tmp = add i64 %indvar, 2                       ; <i64> [#uses=1]
+  %arrayidx20 = getelementptr [1021 x i32]* %A, i64 0, i64 %tmp ; <i32*> [#uses=1]
+  %tmp1 = add i64 %indvar, 1                      ; <i64> [#uses=1]
+  %arrayidx9 = getelementptr [1021 x i32]* %A, i64 0, i64 %tmp1 ; <i32*> [#uses=1]
+  %exitcond = icmp ne i64 %indvar, 1019           ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp10 = load i32* %arrayidx9                   ; <i32> [#uses=1]
+  %tmp16 = load i32* %arrayidx15                  ; <i32> [#uses=1]
+  %add = add nsw i32 %tmp10, %tmp16               ; <i32> [#uses=1]
+  store i32 %add, i32* %arrayidx20
+  %tmp26 = load i32* %arrayidx15                  ; <i32> [#uses=1]
+  %arraydecay27 = getelementptr inbounds [1 x i32]* %RED, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx28 = getelementptr inbounds i32* %arraydecay27, i64 0 ; <i32*> [#uses=2]
+  %tmp29 = load i32* %arrayidx28                  ; <i32> [#uses=1]
+  %add30 = add nsw i32 %tmp29, %tmp26             ; <i32> [#uses=1]
+  store i32 %add30, i32* %arrayidx28
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  %arraydecay32 = getelementptr inbounds [1 x i32]* %RED, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx33 = getelementptr inbounds i32* %arraydecay32, i64 0 ; <i32*> [#uses=1]
+  %tmp34 = load i32* %arrayidx33                  ; <i32> [#uses=1]
+  %cmp35 = icmp ne i32 %tmp34, 382399368          ; <i1> [#uses=1]
+  br i1 %cmp35, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.end
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.end
+  %retval.0 = phi i32 [ 1, %if.then ], [ 0, %for.end ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: for (int c0 = 0; c0 <= 1018; c0 += 1)
+; CHECK:   Stmt_for_body(c0);
diff --git a/final/test/Isl/CodeGen/reduction_simple_binary.ll b/final/test/Isl/CodeGen/reduction_simple_binary.ll
new file mode 100644
index 0000000..2d2812b
--- /dev/null
+++ b/final/test/Isl/CodeGen/reduction_simple_binary.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
+;
+; CHECK: pragma simd reduction
+;
+; int prod;
+; void f() {
+;   for (int i = 0; i < 100; i++)
+;     prod *= i;
+; }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+@prod = common global i32 0, align 4
+
+define void @f() {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i1.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i1.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %add2 = add nsw i32 %i1.0, 3
+  %tmp1 = load i32* @prod, align 4
+  %mul3 = mul nsw i32 %tmp1, %add2
+  store i32 %mul3, i32* @prod, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i1.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll b/final/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll
new file mode 100644
index 0000000..a4dbbcd
--- /dev/null
+++ b/final/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll
@@ -0,0 +1,28 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize < %s | FileCheck %s
+
+; CHECK: %1 = zext i32 %n to i64
+; CHECK: %2 = icmp sge i64 %1, 1
+; CHECK: %3 = select i1 %2, i64 1, i64 0
+; CHECK: %4 = icmp ne i64 %3, 0
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @init_array(i32 %n, double* %data) {
+entry:
+  %0 = zext i32 %n to i64
+  br label %for.body4
+
+for.body4:                                        ; preds = %for.body4, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.body4 ], [ 0, %entry ]
+  %.moved.to.for.body4 = mul i64 %0, %indvar1
+  %1 = add i64 %.moved.to.for.body4, 0
+  %arrayidx7 = getelementptr double* %data, i64 %1
+  store double undef, double* %arrayidx7, align 8
+  %indvar.next2 = add i64 %indvar1, 1
+  br i1 false, label %for.body4, label %for.end10
+
+for.end10:                                        ; preds = %for.body4
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/run-time-condition.ll b/final/test/Isl/CodeGen/run-time-condition.ll
new file mode 100644
index 0000000..77af3a4
--- /dev/null
+++ b/final/test/Isl/CodeGen/run-time-condition.ll
@@ -0,0 +1,31 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @run-time-condition(i16* noalias %A, i16* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %indvar = phi i64 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i64 %indvar, 1024
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i16* %B, i64 0
+  %load = load i16* %arrayidx
+  %add10 = add nsw i16 %load, 1
+  %arrayidx13 = getelementptr inbounds i16* %A, i64 %indvar
+  store i16 %add10, i16* %arrayidx13, align 2
+  %inc = add nsw i64 %indvar, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+; The trivial case, no run-time checks required.
+;
+; CHECK: polly.split_new_and_old:
+; CHECK:  br i1 true, label %polly.start, label %for.cond
diff --git a/final/test/Isl/CodeGen/scalar-references-used-in-scop-compute.ll b/final/test/Isl/CodeGen/scalar-references-used-in-scop-compute.ll
new file mode 100644
index 0000000..fdf9139
--- /dev/null
+++ b/final/test/Isl/CodeGen/scalar-references-used-in-scop-compute.ll
@@ -0,0 +1,51 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s
+
+; Test the code generation in the presence of a scalar out-of-scop value being
+; used from within the SCoP.
+
+; CHECH-LABEL: @scalar-function-argument
+; CHECK: polly.split_new_and_old
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @scalar-function-argument(float* %A, float %sqrinv) {
+entry:
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ %indvar.next, %for.body ], [ 0, %entry ]
+  %mul104 = fmul float 1.0, %sqrinv
+  %rp107 = getelementptr float* %A, i64 %indvar
+  store float %mul104, float* %rp107, align 4
+  %indvar.next = add nsw i64 %indvar, 1
+  %cmp = icmp slt i64 1024, %indvar.next
+  br i1 %cmp, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+; CHECH-LABEL: @scalar-outside-of-scop
+; CHECK: polly.split_new_and_old
+
+define void @scalar-outside-of-scop(float* %A) {
+entry:
+  %sqrinv = call float @getFloat()
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ %indvar.next, %for.body ], [ 0, %entry ]
+  %mul104 = fmul float 1.0, %sqrinv
+  %rp107 = getelementptr float* %A, i64 %indvar
+  store float %mul104, float* %rp107, align 4
+  %indvar.next = add nsw i64 %indvar, 1
+  %cmp = icmp slt i64 1024, %indvar.next
+  br i1 %cmp, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+declare float @getFloat()
diff --git a/final/test/Isl/CodeGen/scev.ll b/final/test/Isl/CodeGen/scev.ll
new file mode 100644
index 0000000..7bfe862
--- /dev/null
+++ b/final/test/Isl/CodeGen/scev.ll
@@ -0,0 +1,22 @@
+; RUN: opt %loadPolly -polly-detect < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define fastcc void @f () inlinehint align 2 {
+entry:
+  %0 = fmul double undef, 1.250000e+00            ; <double> [#uses=1]
+  %1 = fptoui double %0 to i32                    ; <i32> [#uses=0]
+  br i1 false, label %bb5.i, label %bb.nph.i
+
+bb.nph.i:                                         ; preds = %bb.i1
+  br label %bb3.i2
+
+bb3.i2:                                           ; preds = %bb3.i2, %bb.nph.i
+  br i1 undef, label %bb3.i2, label %bb5.i
+
+bb5.i:                                            ; preds = %bb3.i2, %bb.i1
+  br label %exit
+
+exit:
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/scop_never_executed_runtime_check_location.ll b/final/test/Isl/CodeGen/scop_never_executed_runtime_check_location.ll
new file mode 100644
index 0000000..5a31940
--- /dev/null
+++ b/final/test/Isl/CodeGen/scop_never_executed_runtime_check_location.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize < %s | FileCheck %s
+
+; Verify that we generate the runtime check code after the conditional branch
+; in the SCoP region entering block (here %entry).
+;
+; CHECK: entry:
+; CHECK: zext i32 %n to i64
+; CHECK: br i1 false
+;
+; CHECK: %[[T0:[._a-zA-Z0-9]]] = zext i32 %n to i64
+; CHECK: %[[T1:[._a-zA-Z0-9]]] = icmp sge i64 %[[T0]], 1
+; CHECK: %[[T2:[._a-zA-Z0-9]]] = select i1 %[[T1]], i64 1, i64 0
+; CHECK: %[[T3:[._a-zA-Z0-9]]] = icmp ne i64 %[[T2]], 0
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @init_array(i32 %n, double* %data) {
+entry:
+  %0 = zext i32 %n to i64
+  br i1 false, label %for.end10, label %for.body4
+
+for.body4:                                        ; preds = %for.body4, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.body4 ], [ 0, %entry ]
+  %.moved.to.for.body4 = mul i64 %0, %indvar1
+  %1 = add i64 %.moved.to.for.body4, 0
+  %arrayidx7 = getelementptr double* %data, i64 %1
+  store double undef, double* %arrayidx7, align 8
+  %indvar.next2 = add i64 %indvar1, 1
+  br i1 false, label %for.body4, label %for.end10
+
+for.end10:                                        ; preds = %for.body4
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/sequential_loops.ll b/final/test/Isl/CodeGen/sequential_loops.ll
new file mode 100644
index 0000000..51d7613
--- /dev/null
+++ b/final/test/Isl/CodeGen/sequential_loops.ll
@@ -0,0 +1,138 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+
+;#include <string.h>
+;#define N 1024
+;
+;int A[N];
+;
+;void sequential_loops() {
+;  int i;
+;  for (i = 0; i < N/2; i++) {
+;    A[i] = 1;
+;  }
+;  for (i = N/2 ; i < N; i++) {
+;    A[i] = 2;
+;  }
+;}
+;
+;int main () {
+;  int i;
+;  memset(A, 0, sizeof(int) * N);
+;
+;  sequential_loops();
+;
+;  for (i = 0; i < N; i++) {
+;    if (A[i] != 1 && i < N/2)
+;      return 1;
+;    if (A[i] !=  2 && i >= N/2)
+;      return 1;
+;  }
+;
+;  return 0;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer, align 4 ; <[1024 x i32]*> [#uses=5]
+
+define void @sequential_loops() nounwind {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb3, %bb
+  %indvar1 = phi i64 [ %indvar.next2, %bb3 ], [ 0, %bb ]
+  %scevgep4 = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar1
+  %exitcond3 = icmp ne i64 %indvar1, 512
+  br i1 %exitcond3, label %bb2, label %bb4
+
+bb2:                                              ; preds = %bb1
+  store i32 1, i32* %scevgep4
+  br label %bb3
+
+bb3:                                              ; preds = %bb2
+  %indvar.next2 = add i64 %indvar1, 1
+  br label %bb1
+
+bb4:                                              ; preds = %bb1
+  br label %bb5
+
+bb5:                                              ; preds = %bb7, %bb4
+  %indvar = phi i64 [ %indvar.next, %bb7 ], [ 0, %bb4 ]
+  %tmp = add i64 %indvar, 512
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %tmp
+  %exitcond = icmp ne i64 %indvar, 512
+  br i1 %exitcond, label %bb6, label %bb8
+
+bb6:                                              ; preds = %bb5
+  store i32 2, i32* %scevgep
+  br label %bb7
+
+bb7:                                              ; preds = %bb6
+  %indvar.next = add i64 %indvar, 1
+  br label %bb5
+
+bb8:                                              ; preds = %bb5
+  ret void
+}
+
+define i32 @main() nounwind {
+bb:
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @A to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @sequential_loops()
+  br label %bb1
+
+bb1:                                              ; preds = %bb15, %bb
+  %indvar = phi i64 [ %indvar.next, %bb15 ], [ 0, %bb ]
+  %i.0 = trunc i64 %indvar to i32
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar
+  %tmp = icmp slt i32 %i.0, 1024
+  br i1 %tmp, label %bb2, label %bb16
+
+bb2:                                              ; preds = %bb1
+  %tmp3 = load i32* %scevgep
+  %tmp4 = icmp ne i32 %tmp3, 1
+  br i1 %tmp4, label %bb5, label %bb8
+
+bb5:                                              ; preds = %bb2
+  %tmp6 = icmp slt i32 %i.0, 512
+  br i1 %tmp6, label %bb7, label %bb8
+
+bb7:                                              ; preds = %bb5
+  br label %bb17
+
+bb8:                                              ; preds = %bb5, %bb2
+  %tmp9 = load i32* %scevgep
+  %tmp10 = icmp ne i32 %tmp9, 2
+  br i1 %tmp10, label %bb11, label %bb14
+
+bb11:                                             ; preds = %bb8
+  %tmp12 = icmp sge i32 %i.0, 512
+  br i1 %tmp12, label %bb13, label %bb14
+
+bb13:                                             ; preds = %bb11
+  br label %bb17
+
+bb14:                                             ; preds = %bb11, %bb8
+  br label %bb15
+
+bb15:                                             ; preds = %bb14
+  %indvar.next = add i64 %indvar, 1
+  br label %bb1
+
+bb16:                                             ; preds = %bb1
+  br label %bb17
+
+bb17:                                             ; preds = %bb16, %bb13, %bb7
+  %.0 = phi i32 [ 1, %bb7 ], [ 1, %bb13 ], [ 0, %bb16 ]
+  ret i32 %.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: {
+; CHECK:   for (int c1 = 0; c1 <= 511; c1 += 1)
+; CHECK:     Stmt_bb2(c1);
+; CHECK:   for (int c1 = 0; c1 <= 511; c1 += 1)
+; CHECK:     Stmt_bb6(c1);
+; CHECK: }
diff --git a/final/test/Isl/CodeGen/simple_loop_non_single_exit.ll b/final/test/Isl/CodeGen/simple_loop_non_single_exit.ll
new file mode 100644
index 0000000..ab4c2b9
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_loop_non_single_exit.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-codegen-isl -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=CHECK-CODE
+
+; void f(long A[], long N) {
+;   long i;
+;   if (true)
+;     for (i = 0; i < N; ++i)
+;       A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br label %next
+
+next:
+  br i1 true, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %next], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Create LLVM-IR from SCoPs' for region: 'next => polly.merge_new_and_old'
+; CHECK-CODE: polly.split_new_and_old
+; CHECK-CODE: polly.merge_new_and_old
diff --git a/final/test/Isl/CodeGen/simple_loop_non_single_exit_2.ll b/final/test/Isl/CodeGen/simple_loop_non_single_exit_2.ll
new file mode 100644
index 0000000..4f09802
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_loop_non_single_exit_2.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-codegen-isl -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=CHECK-CODE
+
+; void f(long A[], long N) {
+;   long i;
+;   if (true)
+;     if (true)
+;       for (i = 0; i < N; ++i)
+;         A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %next, label %return
+
+next:
+  br i1 true, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %next], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Create LLVM-IR from SCoPs' for region: 'for.i => return'
+; CHECK-CODE: polly.split_new_and_old
+; CHECK-CODE: polly.merge_new_and_old
diff --git a/final/test/Isl/CodeGen/simple_non_single_entry.ll b/final/test/Isl/CodeGen/simple_non_single_entry.ll
new file mode 100644
index 0000000..c0c90ec
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_non_single_entry.ll
@@ -0,0 +1,71 @@
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-codegen-isl -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=CHECK-CODE
+
+; void f(long A[], long N) {
+;   long i;
+;
+;  if (true){
+;    i = 0;
+;    goto next;
+;  }else{
+;    i = 1;
+;    goto next;
+; }
+;
+; next:
+;  if (true)
+;    goto for.i;
+;  else
+;    goto for.i;
+;
+; for.i:
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %then1, label %else1
+
+then1:
+  br label %next
+
+else1:
+  br label %next
+
+next:
+  br i1 true, label %then, label %else
+
+then:
+  br label %for.i.head
+
+else:
+  br label %for.i.head
+
+for.i.head:
+  br label %for.i.head1
+
+for.i.head1:
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %for.i.head1], [ %indvar.next, %for.i ]
+  fence seq_cst
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Create LLVM-IR from SCoPs' for region: 'next.split => polly.merge_new_and_old'
+; CHECK-CODE: polly.split_new_and_old
+; CHECK-CODE: polly.merge_new_and_old
diff --git a/final/test/Isl/CodeGen/simple_nonaffine_loop.ll b/final/test/Isl/CodeGen/simple_nonaffine_loop.ll
new file mode 100644
index 0000000..bfed04b
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_nonaffine_loop.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -polly-ast -polly-allow-nonaffine -analyze < %s | FileCheck %s
+
+;#include <stdio.h>
+;#include <stdlib.h>
+;#include <math.h>
+;
+;int main()
+;{
+;	int A[1024*1024];
+;	int i;
+;	for (i = 0; i < 1024; i++)
+;		A[i*i] = 2*i;
+;
+;	printf("Random Value: %d", A[rand() % 1024*1024]);
+;
+;	return 0;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.7.2"
+
+@.str = private unnamed_addr constant [17 x i8] c"Random Value: %d\00", align 1
+
+define i32 @main() nounwind uwtable ssp {
+entry:
+  %A = alloca [1048576 x i32], align 16
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %0 = phi i32 [ 0, %entry.split ], [ %1, %for.body ]
+  %mul = mul i32 %0, 2
+  %mul1 = mul nsw i32 %0, %0
+  %idxprom1 = zext i32 %mul1 to i64
+  %arrayidx = getelementptr inbounds [1048576 x i32]* %A, i64 0, i64 %idxprom1
+  store i32 %mul, i32* %arrayidx, align 4
+  %1 = add nsw i32 %0, 1
+  %exitcond = icmp ne i32 %1, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  %call = call i32 @rand() nounwind
+  %rem = srem i32 %call, 1024
+  %mul2 = shl nsw i32 %rem, 10
+  %idxprom3 = sext i32 %mul2 to i64
+  %arrayidx4 = getelementptr inbounds [1048576 x i32]* %A, i64 0, i64 %idxprom3
+  %2 = load i32* %arrayidx4, align 16
+  %call5 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str, i64 0, i64 0), i32 %2) nounwind
+  ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+
+declare i32 @rand()
+
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK:   Stmt_for_body(c0);
diff --git a/final/test/Isl/CodeGen/simple_vec_assign_scalar.ll b/final/test/Isl/CodeGen/simple_vec_assign_scalar.ll
new file mode 100644
index 0000000..df91b6c
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_assign_scalar.ll
@@ -0,0 +1,60 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -dce -S < %s | FileCheck %s
+
+;#define N 1024
+;float A[N];
+;float B[N];
+;
+;void simple_vec_const(void) {
+;  int i;
+;
+;  for (i = 0; i < 4; i++)
+;    B[i] = A[i] + 1;
+;}
+;int main()
+;{
+;  simple_vec_const();
+;  return A[42];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+define void @simple_vec_const() nounwind {
+bb:
+  br label %bb2
+
+bb2:                                              ; preds = %bb5, %bb
+  %indvar = phi i64 [ %indvar.next, %bb5 ], [ 0, %bb ]
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %indvar
+  %scevgep1 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %bb3, label %bb6
+
+bb3:                                              ; preds = %bb2
+  %tmp = load float* %scevgep1, align 4
+  %tmp4 = fadd float %tmp, 1.000000e+00
+  store float %tmp4, float* %scevgep, align 4
+  br label %bb5
+
+bb5:                                              ; preds = %bb3
+  %indvar.next = add i64 %indvar, 1
+  br label %bb2
+
+bb6:                                              ; preds = %bb2
+  ret void
+}
+
+define i32 @main() nounwind {
+bb:
+  call void @simple_vec_const()
+  %tmp = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 42), align 8
+  %tmp1 = fptosi float %tmp to i32
+  ret i32 %tmp1
+}
+
+; CHECK: %tmp_p_vec_full = load <4 x float>* bitcast ([1024 x float]* @A to <4 x float>*), align 8, !alias.scope !0, !noalias !2
+; CHECK: %tmp4p_vec = fadd <4 x float> %tmp_p_vec_full, <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK: store <4 x float> %tmp4p_vec, <4 x float>* bitcast ([1024 x float]* @B to <4 x float>*), align 8, !alias.scope !3, !noalias !4
diff --git a/final/test/Isl/CodeGen/simple_vec_assign_scalar_2.ll b/final/test/Isl/CodeGen/simple_vec_assign_scalar_2.ll
new file mode 100644
index 0000000..7aa9d61
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_assign_scalar_2.ll
@@ -0,0 +1,66 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -dce -S < %s | FileCheck %s
+
+;#define N 1024
+;float A[N];
+;float B[N];
+;
+;void simple_vec_const(void) {
+;  int i;
+;
+;  for (i = 0; i < 4; i++)
+;    B[i] = A[i] + i;
+;}
+;int main()
+;{
+;  simple_vec_const();
+;  return A[42];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+define void @simple_vec_const() nounwind {
+bb:
+  br label %bb2
+
+bb2:                                              ; preds = %bb6, %bb
+  %indvar = phi i64 [ %indvar.next, %bb6 ], [ 0, %bb ]
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %indvar
+  %i.0 = trunc i64 %indvar to i32
+  %scevgep1 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %bb3, label %bb7
+
+bb3:                                              ; preds = %bb2
+  %tmp = load float* %scevgep1, align 4
+  %tmp4 = sitofp i32 %i.0 to float
+  %tmp5 = fadd float %tmp, %tmp4
+  store float %tmp5, float* %scevgep, align 4
+  br label %bb6
+
+bb6:                                              ; preds = %bb3
+  %indvar.next = add i64 %indvar, 1
+  br label %bb2
+
+bb7:                                              ; preds = %bb2
+  ret void
+}
+
+define i32 @main() nounwind {
+bb:
+  call void @simple_vec_const()
+  %tmp = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 42), align 8
+  %tmp1 = fptosi float %tmp to i32
+  ret i32 %tmp1
+}
+
+
+; CHECK: insertelement <4 x float> undef, float %{{[^,]+}}, i32 0
+; CHECK: insertelement <4 x float> %0, float %{{[^,]+}}, i32 1
+; CHECK: insertelement <4 x float> %1, float %{{[^,]+}}, i32 2
+; CHECK: insertelement <4 x float> %2, float %{{[^,]+}}, i32 3
+; CHECK: fadd <4 x float> %tmp_p_vec_full, %3
+
diff --git a/final/test/Isl/CodeGen/simple_vec_call.ll b/final/test/Isl/CodeGen/simple_vec_call.ll
new file mode 100644
index 0000000..6a77824
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_call.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+declare float @foo(float) readnone
+
+define void @simple_vec_call() nounwind {
+entry:
+  br label %body
+
+body:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar_next, %body ]
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %indvar
+  %value = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 0), align 16
+  %result = tail call float @foo(float %value) nounwind
+  store float %result, float* %scevgep, align 4
+  %indvar_next = add i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar_next, 4
+  br i1 %exitcond, label %return, label %body
+
+return:
+  ret void
+}
+
+; CHECK: %value_p_splat_one = load <1 x float>* bitcast ([1024 x float]* @A to <1 x float>*), align 8
+; CHECK: %value_p_splat = shufflevector <1 x float> %value_p_splat_one, <1 x float> %value_p_splat_one, <4 x i32> zeroinitializer
+; CHECK: %0 = extractelement <4 x float> %value_p_splat, i32 0
+; CHECK: %1 = extractelement <4 x float> %value_p_splat, i32 1
+; CHECK: %2 = extractelement <4 x float> %value_p_splat, i32 2
+; CHECK: %3 = extractelement <4 x float> %value_p_splat, i32 3
+; CHECK: [[RES1:%[a-zA-Z0-9_]+]] = tail call float @foo(float %0) [[NUW:#[0-9]+]]
+; CHECK: [[RES2:%[a-zA-Z0-9_]+]] = tail call float @foo(float %1) [[NUW]]
+; CHECK: [[RES3:%[a-zA-Z0-9_]+]] = tail call float @foo(float %2) [[NUW]]
+; CHECK: [[RES4:%[a-zA-Z0-9_]+]] = tail call float @foo(float %3) [[NUW]]
+; CHECK: %4 = insertelement <4 x float> undef, float [[RES1]], i32 0
+; CHECK: %5 = insertelement <4 x float> %4, float [[RES2]], i32 1
+; CHECK: %6 = insertelement <4 x float> %5, float [[RES3]], i32 2
+; CHECK: %7 = insertelement <4 x float> %6, float [[RES4]], i32 3
+; CHECK:  store <4 x float> %7
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/final/test/Isl/CodeGen/simple_vec_call_2.ll b/final/test/Isl/CodeGen/simple_vec_call_2.ll
new file mode 100644
index 0000000..ee7f50e
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_call_2.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -dce -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float**] zeroinitializer, align 16
+
+declare float** @foo(float) readnone
+
+define void @simple_vec_call() nounwind {
+entry:
+  br label %body
+
+body:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar_next, %body ]
+  %scevgep = getelementptr [1024 x float**]* @B, i64 0, i64 %indvar
+  %value = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 0), align 16
+  %result = tail call float** @foo(float %value) nounwind
+  store float** %result, float*** %scevgep, align 4
+  %indvar_next = add i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar_next, 4
+  br i1 %exitcond, label %return, label %body
+
+return:
+  ret void
+}
+
+; CHECK: %value_p_splat_one = load <1 x float>* bitcast ([1024 x float]* @A to <1 x float>*), align 8
+; CHECK: %value_p_splat = shufflevector <1 x float> %value_p_splat_one, <1 x float> %value_p_splat_one, <4 x i32> zeroinitializer
+; CHECK: %0 = extractelement <4 x float> %value_p_splat, i32 0
+; CHECK: %1 = extractelement <4 x float> %value_p_splat, i32 1
+; CHECK: %2 = extractelement <4 x float> %value_p_splat, i32 2
+; CHECK: %3 = extractelement <4 x float> %value_p_splat, i32 3
+; CHECK: [[RES1:%[a-zA-Z0-9_]+]] = tail call float** @foo(float %0) [[NUW:#[0-9]+]]
+; CHECK: [[RES2:%[a-zA-Z0-9_]+]] = tail call float** @foo(float %1) [[NUW]]
+; CHECK: [[RES3:%[a-zA-Z0-9_]+]] = tail call float** @foo(float %2) [[NUW]]
+; CHECK: [[RES4:%[a-zA-Z0-9_]+]] = tail call float** @foo(float %3) [[NUW]]
+; CHECK: %4 = insertelement <4 x float**> undef, float** %p_result, i32 0
+; CHECK: %5 = insertelement <4 x float**> %4, float** %p_result1, i32 1
+; CHECK: %6 = insertelement <4 x float**> %5, float** %p_result2, i32 2
+; CHECK: %7 = insertelement <4 x float**> %6, float** %p_result3, i32 3
+; CHECK: store <4 x float**> %7, <4 x float**>* bitcast ([1024 x float**]* @B to <4 x float**>*), align
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/final/test/Isl/CodeGen/simple_vec_cast.ll b/final/test/Isl/CodeGen/simple_vec_cast.ll
new file mode 100644
index 0000000..f13d06b
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_cast.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -dce -S < %s | FileCheck %s -check-prefix=CHECK
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x double] zeroinitializer, align 16
+
+define void @simple_vec_const() nounwind {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb3, %bb
+  %indvar = phi i64 [ %indvar.next, %bb3 ], [ 0, %bb ]
+  %scevgep = getelementptr [1024 x double]* @B, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %bb2, label %bb4
+
+bb2:                                              ; preds = %bb1
+  %tmp = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 0), align 16
+  %tmp2 = fpext float %tmp to double
+  store double %tmp2, double* %scevgep, align 4
+  br label %bb3
+
+bb3:                                              ; preds = %bb2
+  %indvar.next = add i64 %indvar, 1
+  br label %bb1
+
+bb4:                                              ; preds = %bb1
+  ret void
+}
+
+; CHECK: %tmp_p_splat_one = load <1 x float>* bitcast ([1024 x float]* @A to <1 x float>*), align 8, !alias.scope !0, !noalias !2
+; CHECK: %tmp_p_splat = shufflevector <1 x float> %tmp_p_splat_one, <1 x float> %tmp_p_splat_one, <4 x i32> zeroinitializer
+; CHECK: %0 = fpext <4 x float> %tmp_p_splat to <4 x double>
+; CHECK: store <4 x double> %0, <4 x double>* bitcast ([1024 x double]* @B to <4 x double>*), align 8, !alias.scope !3, !noalias !4
+
diff --git a/final/test/Isl/CodeGen/simple_vec_const.ll b/final/test/Isl/CodeGen/simple_vec_const.ll
new file mode 100644
index 0000000..df40ccc
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_const.ll
@@ -0,0 +1,57 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -S < %s | FileCheck %s
+
+;#define N 1024
+;float A[N];
+;float B[N];
+;
+;void simple_vec_const(void) {
+;  int i;
+;
+;  for (i = 0; i < 4; i++)
+;    B[i] = A[0];
+;}
+;int main()
+;{
+;  simple_vec_const();
+;  return A[42];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+define void @simple_vec_const() nounwind {
+; <label>:0
+  br label %1
+
+; <label>:1                                       ; preds = %4, %0
+  %indvar = phi i64 [ %indvar.next, %4 ], [ 0, %0 ]
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %2, label %5
+
+; <label>:2                                       ; preds = %1
+  %3 = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 0), align 16
+  store float %3, float* %scevgep, align 4
+  br label %4
+
+; <label>:4                                       ; preds = %2
+  %indvar.next = add i64 %indvar, 1
+  br label %1
+
+; <label>:5                                       ; preds = %1
+  ret void
+}
+
+define i32 @main() nounwind {
+  call void @simple_vec_const()
+  %1 = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 42), align 8
+  %2 = fptosi float %1 to i32
+  ret i32 %2
+}
+
+
+; CHECK: load <1 x float>* bitcast ([1024 x float]* @A to <1 x float>*)
+; CHECK: shufflevector <1 x float> {{.*}}, <1 x float> {{.*}} <4 x i32> zeroinitializer
diff --git a/final/test/Isl/CodeGen/simple_vec_large_width.ll b/final/test/Isl/CodeGen/simple_vec_large_width.ll
new file mode 100644
index 0000000..0ec8650
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_large_width.ll
@@ -0,0 +1,40 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -dce -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+define void @simple_vec_large_width() nounwind {
+; <label>:0
+  br label %1
+
+; <label>:1                                       ; preds = %4, %0
+  %indvar = phi i64 [ %indvar.next, %4 ], [ 0, %0 ]
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %indvar
+  %scevgep1 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 15
+  br i1 %exitcond, label %2, label %5
+
+; <label>:2                                       ; preds = %1
+  %3 = load float* %scevgep1, align 4
+  store float %3, float* %scevgep, align 4
+  br label %4
+
+; <label>:4                                       ; preds = %2
+  %indvar.next = add i64 %indvar, 1
+  br label %1
+
+; <label>:5                                       ; preds = %1
+  ret void
+}
+
+define i32 @main() nounwind {
+  call void @simple_vec_large_width()
+  %1 = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 42), align 8
+  %2 = fptosi float %1 to i32
+  ret i32 %2
+}
+
+; CHECK: [[VEC1:%[a-zA-Z0-9_]+_full]] = load <15 x float>*
+; CHECK: store <15 x float> [[VEC1]]
diff --git a/final/test/Isl/CodeGen/simple_vec_ptr_ptr_ty.ll b/final/test/Isl/CodeGen/simple_vec_ptr_ptr_ty.ll
new file mode 100644
index 0000000..cca14df
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_ptr_ptr_ty.ll
@@ -0,0 +1,28 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float**] zeroinitializer, align 16
+@B = common global [1024 x float**] zeroinitializer, align 16
+
+declare float @foo(float) readnone
+
+define void @simple_vec_call() nounwind {
+entry:
+  br label %body
+
+body:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar_next, %body ]
+  %scevgep = getelementptr [1024 x float**]* @B, i64 0, i64 %indvar
+  %value = load float*** getelementptr inbounds ([1024 x float**]* @A, i64 0, i64 0), align 16
+  store float** %value, float*** %scevgep, align 4
+  %indvar_next = add i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar_next, 4
+  br i1 %exitcond, label %return, label %body
+
+return:
+  ret void
+}
+; CHECK: %value_p_splat_one = load <1 x float**>* bitcast ([1024 x float**]* @A to <1 x float**>*), align 8
+; CHECK: %value_p_splat = shufflevector <1 x float**> %value_p_splat_one, <1 x float**> %value_p_splat_one, <4 x i32> zeroinitializer
+; CHECK: store <4 x float**> %value_p_splat, <4 x float**>* bitcast ([1024 x float**]* @B to <4 x float**>*), align 8
diff --git a/final/test/Isl/CodeGen/simple_vec_stride_negative_one.ll b/final/test/Isl/CodeGen/simple_vec_stride_negative_one.ll
new file mode 100644
index 0000000..30398e8
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_stride_negative_one.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-codegen-isl %vector-opt -S < %s | FileCheck %s
+
+; ModuleID = 'reverse.c'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+;int A[100];
+;void foo() {
+;  for (int i=3; i >= 0; i--)
+;    A[i]+=1;
+;}
+
+
+@A = common global [100 x i32] zeroinitializer, align 16
+
+; Function Attrs: nounwind uwtable
+define void @foo() #0 {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %indvars.iv = phi i64 [ 3, %entry ], [ %indvars.iv.next, %for.body ]
+  %arrayidx = getelementptr inbounds [100 x i32]* @A, i64 0, i64 %indvars.iv
+  %0 = load i32* %arrayidx, align 4
+  %add = add nsw i32 %0, 1
+  store i32 %add, i32* %arrayidx, align 4
+  %indvars.iv.next = add nsw i64 %indvars.iv, -1
+  %1 = trunc i64 %indvars.iv to i32
+  %cmp = icmp sgt i32 %1, 0
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+; CHECK: @foo
+; CHECK: [[LOAD:%[a-zA-Z0-9_]+]] = load <4 x i32>*
+; CHECK: [[REVERSE_LOAD:%[a-zA-Z0-9_]+reverse]] = shufflevector <4 x i32> [[LOAD]], <4 x i32> [[LOAD]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
diff --git a/final/test/Isl/CodeGen/simple_vec_stride_x.ll b/final/test/Isl/CodeGen/simple_vec_stride_x.ll
new file mode 100644
index 0000000..7f56abe
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_stride_x.ll
@@ -0,0 +1,73 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt  -dce -S < %s | FileCheck %s
+
+;#define N 1024
+;float A[N];
+;float B[N];
+;
+;void simple_vec_stride_x(void) {
+;  int i;
+;
+;  for (i = 0; i < 4; i++)
+;    B[2 * i] = A[2 * i];
+;}
+;int main()
+;{
+;  simple_vec_stride_x();
+;  return A[42];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+
+define void @simple_vec_stride_x() nounwind {
+bb:
+  br label %bb2
+
+bb2:                                              ; preds = %bb5, %bb
+  %indvar = phi i64 [ %indvar.next, %bb5 ], [ 0, %bb ]
+  %tmp = mul i64 %indvar, 2
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %tmp
+  %scevgep1 = getelementptr [1024 x float]* @A, i64 0, i64 %tmp
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %bb3, label %bb6
+
+bb3:                                              ; preds = %bb2
+  %tmp4 = load float* %scevgep1, align 8
+  store float %tmp4, float* %scevgep, align 8
+  br label %bb5
+
+bb5:                                              ; preds = %bb3
+  %indvar.next = add i64 %indvar, 1
+  br label %bb2
+
+bb6:                                              ; preds = %bb2
+  ret void
+}
+
+define i32 @main() nounwind {
+bb:
+  call void @simple_vec_stride_x()
+  %tmp = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 42), align 8
+  %tmp1 = fptosi float %tmp to i32
+  ret i32 %tmp1
+}
+
+; CHECK: [[LOAD1:%[a-zA-Z0-9_]+_scalar_]] = load float*
+; CHECK: [[VEC1:%[a-zA-Z0-9_]+]] = insertelement <4 x float> undef, float [[LOAD1]], i32 0
+; CHECK: [[LOAD2:%[a-zA-Z0-9_]+]] = load float*
+; CHECK: [[VEC2:%[a-zA-Z0-9_]+]] = insertelement <4 x float> [[VEC1]], float [[LOAD2]], i32 1
+; CHECK: [[LOAD3:%[a-zA-Z0-9_]+]] = load float*
+; CHECK: [[VEC3:%[a-zA-Z0-9_]+]] = insertelement <4 x float> [[VEC2]], float [[LOAD3]], i32 2
+; CHECK: [[LOAD4:%[a-zA-Z0-9_]+]] = load float*
+; CHECK: [[VEC4:%[a-zA-Z0-9_]+]] = insertelement <4 x float> [[VEC3]], float [[LOAD4]], i32 3
+; CHECK: [[EL1:%[a-zA-Z0-9_]+]] = extractelement <4 x float> [[VEC4]], i32 0
+; CHECK: store float [[EL1]]
+; CHECK: [[EL2:%[a-zA-Z0-9_]+]] = extractelement <4 x float> [[VEC4]], i32 1
+; CHECK: store float [[EL2]]
+; CHECK: [[EL3:%[a-zA-Z0-9_]+]] = extractelement <4 x float> [[VEC4]], i32 2
+; CHECK: store float [[EL3]]
+; CHECK: [[EL4:%[a-zA-Z0-9_]+]] = extractelement <4 x float> [[VEC4]], i32 3
+; CHECK: store float [[EL4]]
diff --git a/final/test/Isl/CodeGen/simple_vec_two_stmts.ll b/final/test/Isl/CodeGen/simple_vec_two_stmts.ll
new file mode 100644
index 0000000..b77ab23
--- /dev/null
+++ b/final/test/Isl/CodeGen/simple_vec_two_stmts.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -basicaa -polly-codegen-isl %vector-opt -dce -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 16
+@B = common global [1024 x float] zeroinitializer, align 16
+@C = common global [1024 x float] zeroinitializer, align 16
+
+define void @simple_vec_stride_one() nounwind {
+bb0:
+  br label %bb1
+
+bb1:
+  %indvar = phi i64 [ %indvar.next, %bb4 ], [ 0, %bb0 ]
+  %scevgep = getelementptr [1024 x float]* @B, i64 0, i64 %indvar
+  %scevgep2 = getelementptr [1024 x float]* @C, i64 0, i64 %indvar
+  %scevgep1 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %bb2a, label %bb5
+
+bb2a:
+  %tmp1 = load float* %scevgep1, align 4
+  store float %tmp1, float* %scevgep, align 4
+  br label %bb2b
+
+bb2b:
+  %tmp2 = load float* %scevgep1, align 4
+  store float %tmp2, float* %scevgep2, align 4
+  br label %bb4
+
+bb4:
+  %indvar.next = add i64 %indvar, 1
+  br label %bb1
+
+bb5:
+  ret void
+}
+
+define i32 @main() nounwind {
+  call void @simple_vec_stride_one()
+  %1 = load float* getelementptr inbounds ([1024 x float]* @A, i64 0, i64 42), align 8
+  %2 = fptosi float %1 to i32
+  ret i32 %2
+}
+
+; CHECK: [[LOAD1:%[a-zA-Z0-9_]+_full]] = load <4 x float>*
+; CHECK: store <4 x float> [[LOAD1]]
+; CHECK: [[LOAD2:%[a-zA-Z0-9_]+_full]] = load <4 x float>*
+; CHECK: store <4 x float> [[LOAD2]]
+
diff --git a/final/test/Isl/CodeGen/single_do_loop_int_max_iterations.ll b/final/test/Isl/CodeGen/single_do_loop_int_max_iterations.ll
new file mode 100644
index 0000000..081d323
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_do_loop_int_max_iterations.ll
@@ -0,0 +1,93 @@
+; RUN: opt %loadPolly -polly-ast -analyze  -S < %s | FileCheck %s
+
+;#define N 20
+;#include "limits.h"
+;#include <stdio.h>
+;int A[N];
+;
+;void single_do_loop_int_max_iterations() {
+;  int i;
+;
+;  __sync_synchronize();
+;
+;  i = 0;
+;
+;  do {
+;    A[0] = i;
+;    ++i;
+;  } while (i < INT_MAX);
+;
+;  __sync_synchronize();
+;}
+;
+;int main () {
+;  int i;
+;
+;  A[0] = 0;
+;
+;  single_do_loop_int_max_iterations();
+;
+;  fprintf(stdout, "Output %d\n", A[0]);
+;
+;  if (A[0] == INT_MAX - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+
+@A = common global [20 x i32] zeroinitializer, align 4 ; <[20 x i32]*> [#uses=1]
+@stdout = external global %struct._IO_FILE*       ; <%struct._IO_FILE**> [#uses=1]
+@.str = private constant [11 x i8] c"Output %d\0A\00" ; <[11 x i8]*> [#uses=1]
+
+define void @single_do_loop_int_max_iterations() nounwind {
+entry:
+  fence seq_cst
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond, %entry
+  %0 = phi i32 [ 0, %entry ], [ %inc, %do.cond ]  ; <i32> [#uses=2]
+  store i32 %0, i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0)
+  %inc = add nsw i32 %0, 1                        ; <i32> [#uses=2]
+  br label %do.cond
+
+do.cond:                                          ; preds = %do.body
+  %exitcond = icmp ne i32 %inc, 2147483647        ; <i1> [#uses=1]
+  br i1 %exitcond, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.cond
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+entry:
+  store i32 0, i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0)
+  call void @single_do_loop_int_max_iterations()
+  %tmp = load %struct._IO_FILE** @stdout          ; <%struct._IO_FILE*> [#uses=1]
+  %tmp1 = load i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0) ; <i32> [#uses=1]
+  %call = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %tmp, i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), i32 %tmp1) ; <i32> [#uses=0]
+  %tmp2 = load i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0) ; <i32> [#uses=1]
+  %cmp = icmp eq i32 %tmp2, 2147483646            ; <i1> [#uses=1]
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.else:                                          ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+declare i32 @fprintf(%struct._IO_FILE*, i8*, ...)
+
+; CHECK: for (int c0 = 0; c0 <= 2147483646; c0 += 1)
+; CHECK:   Stmt_do_body(c0);
diff --git a/final/test/Isl/CodeGen/single_do_loop_int_max_iterations___%do.body---%do.end.jscop b/final/test/Isl/CodeGen/single_do_loop_int_max_iterations___%do.body---%do.end.jscop
new file mode 100644
index 0000000..fcd78fc
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_do_loop_int_max_iterations___%do.body---%do.end.jscop
@@ -0,0 +1,13 @@
+{
+	"name": "do.body => do.end",
+	"context": "{ [] }",
+	"statements": [{
+		"name": "Stmt_do_body",
+		"domain": "{ Stmt_do_body[i0] : i0 >= 0 and i0 <= 2147483646 }",
+		"schedule": "{ Stmt_do_body[i0] -> scattering[0, o1, i0, o3, 0] : 64o3 = o1 and o1 <= i0 and o1 >= -63 + i0 }",
+		"accesses": [{
+			"kind": "write",
+			"relation": "{ Stmt_do_body[i0] -> MemRef_A[0] }"
+		}]
+	}]
+}
\ No newline at end of file
diff --git a/final/test/Isl/CodeGen/single_do_loop_int_param_iterations.ll b/final/test/Isl/CodeGen/single_do_loop_int_param_iterations.ll
new file mode 100644
index 0000000..7a8d4cf
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_do_loop_int_param_iterations.ll
@@ -0,0 +1,77 @@
+; RUN: opt %loadPolly -polly-ast -S -analyze  < %s | FileCheck %s
+; XFAIL: *
+
+;define N 20
+;#include "limits.h"
+;int A[N];
+;
+;void bar (int n) {
+;  int i;
+;  __sync_synchronize();
+;  i = 0;
+;
+;  do {
+;    A[0] = i;
+;    ++i;
+;  } while (i < 2 * n);
+;  __sync_synchronize();
+;}
+;
+;int main () {
+;  A[0] = 0;
+;  bar (N/2);
+;
+;  if (A[0] == N - 1 )
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [20 x i32] zeroinitializer, align 4 ; <[20 x i32]*> [#uses=1]
+
+define void @bar(i32 %n) nounwind {
+entry:
+  fence seq_cst
+  %tmp = mul i32 %n, 2                            ; <i32> [#uses=2]
+  %tmp1 = icmp sgt i32 %tmp, 1                    ; <i1> [#uses=1]
+  %smax = select i1 %tmp1, i32 %tmp, i32 1        ; <i32> [#uses=1]
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond, %entry
+  %0 = phi i32 [ 0, %entry ], [ %inc, %do.cond ]  ; <i32> [#uses=2]
+  store i32 %0, i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0)
+  %inc = add nsw i32 %0, 1                        ; <i32> [#uses=2]
+  br label %do.cond
+
+do.cond:                                          ; preds = %do.body
+  %exitcond = icmp ne i32 %inc, %smax             ; <i1> [#uses=1]
+  br i1 %exitcond, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.cond
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+entry:
+  store i32 0, i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0)
+  call void @bar(i32 10)
+  %tmp = load i32* getelementptr inbounds ([20 x i32]* @A, i32 0, i32 0) ; <i32> [#uses=1]
+  %cmp = icmp eq i32 %tmp, 19                     ; <i1> [#uses=1]
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.else:                                          ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+; CHECK: Scop: do.body => do.end
+
diff --git a/final/test/Isl/CodeGen/single_do_loop_ll_max_iterations.ll b/final/test/Isl/CodeGen/single_do_loop_ll_max_iterations.ll
new file mode 100644
index 0000000..365ac07
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_do_loop_ll_max_iterations.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-ast -analyze  -S < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl < %s
+
+;#define N 20
+;#include "limits.h"
+;long long A[N];
+;
+;int main () {
+;  long long i;
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  i = 0;
+;
+;  do {
+;    A[0] = i;
+;    ++i;
+;  } while (i < LLONG_MAX);
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == LLONG_MAX - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [20 x i64] zeroinitializer, align 8 ; <[20 x i64]*> [#uses=1]
+
+define i32 @main() nounwind {
+entry:
+  store i64 0, i64* getelementptr inbounds ([20 x i64]* @A, i32 0, i32 0)
+  fence seq_cst
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond, %entry
+  %0 = phi i64 [ 0, %entry ], [ %inc, %do.cond ]  ; <i64> [#uses=2]
+  store i64 %0, i64* getelementptr inbounds ([20 x i64]* @A, i32 0, i32 0)
+  %inc = add nsw i64 %0, 1                        ; <i64> [#uses=2]
+  br label %do.cond
+
+do.cond:                                          ; preds = %do.body
+  %exitcond = icmp ne i64 %inc, 9223372036854775807 ; <i1> [#uses=1]
+  br i1 %exitcond, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.cond
+  fence seq_cst
+  %tmp3 = load i64* getelementptr inbounds ([20 x i64]* @A, i32 0, i32 0) ; <i64> [#uses=1]
+  %cmp4 = icmp eq i64 %tmp3, 9223372036854775806  ; <i1> [#uses=1]
+  br i1 %cmp4, label %if.then, label %if.else
+
+if.then:                                          ; preds = %do.end
+  br label %return
+
+if.else:                                          ; preds = %do.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK: for (int c0 = 0; c0 <= 9223372036854775806; c0 += 1)
+; CHECK:   Stmt_do_body(c0);
diff --git a/final/test/Isl/CodeGen/single_do_loop_one_iteration.ll b/final/test/Isl/CodeGen/single_do_loop_one_iteration.ll
new file mode 100644
index 0000000..f8afce7
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_do_loop_one_iteration.ll
@@ -0,0 +1,70 @@
+; RUN: opt %loadPolly -polly-ast -S -analyze  < %s | FileCheck %s
+; XFAIL: *
+
+;#define N 20
+;#include "limits.h"
+;
+;int main () {
+;  int i;
+;  int A[N];
+;
+;  A[0] = 1;
+;
+;  __sync_synchronize();
+;
+;  i = 0;
+;
+;  do {
+;    A[0] = 0;
+;    ++i;
+;  } while (i < 1);
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == 0)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i32], align 4                 ; <[20 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx = getelementptr inbounds i32* %arraydecay, i64 0 ; <i32*> [#uses=1]
+  store i32 1, i32* %arrayidx
+  fence seq_cst
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond, %entry
+  %arraydecay1 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx2 = getelementptr inbounds i32* %arraydecay1, i64 0 ; <i32*> [#uses=1]
+  store i32 0, i32* %arrayidx2
+  br label %do.cond
+
+do.cond:                                          ; preds = %do.body
+  br i1 false, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.cond
+  fence seq_cst
+  %arraydecay4 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx5 = getelementptr inbounds i32* %arraydecay4, i64 0 ; <i32*> [#uses=1]
+  %tmp6 = load i32* %arrayidx5                    ; <i32> [#uses=1]
+  %cmp7 = icmp eq i32 %tmp6, 0                    ; <i1> [#uses=1]
+  br i1 %cmp7, label %if.then, label %if.else
+
+if.then:                                          ; preds = %do.end
+  br label %return
+
+if.else:                                          ; preds = %do.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK: S0(0)
diff --git a/final/test/Isl/CodeGen/single_do_loop_scev_replace.ll b/final/test/Isl/CodeGen/single_do_loop_scev_replace.ll
new file mode 100644
index 0000000..a5b8ed8
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_do_loop_scev_replace.ll
@@ -0,0 +1,95 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+
+;#define N 20
+;#include "limits.h"
+;#include <stdio.h>
+;int A[2 * N];
+;
+;void single_do_loop_scev_replace() {
+;  int i;
+;
+;  __sync_synchronize();
+;
+;  i = 0;
+;
+;  do {
+;    A[2 * i] = i;
+;    ++i;
+;  } while (i < N);
+;
+;  __sync_synchronize();
+;}
+;
+;int main () {
+;  int i;
+;
+;  single_do_loop_scev_replace();
+;
+;  fprintf(stdout, "Output %d\n", A[0]);
+;
+;  if (A[2 * N - 2] == N - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+
+@A = common global [40 x i32] zeroinitializer, align 4 ; <[40 x i32]*> [#uses=3]
+@stdout = external global %struct._IO_FILE*       ; <%struct._IO_FILE**> [#uses=1]
+@.str = private constant [11 x i8] c"Output %d\0A\00" ; <[11 x i8]*> [#uses=1]
+
+define void @single_do_loop_scev_replace() nounwind {
+entry:
+  fence seq_cst
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond, %entry
+  %indvar = phi i64 [ %indvar.next, %do.cond ], [ 0, %entry ] ; <i64> [#uses=3]
+  %tmp = mul i64 %indvar, 2                       ; <i64> [#uses=1]
+  %arrayidx = getelementptr [40 x i32]* @A, i64 0, i64 %tmp ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar to i32                 ; <i32> [#uses=1]
+  br label %do.cond
+
+do.cond:                                          ; preds = %do.body
+  store i32 %i.0, i32* %arrayidx
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=2]
+  %exitcond = icmp ne i64 %indvar.next, 20        ; <i1> [#uses=1]
+  br i1 %exitcond, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.cond
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+entry:
+  call void @single_do_loop_scev_replace()
+  %tmp = load %struct._IO_FILE** @stdout          ; <%struct._IO_FILE*> [#uses=1]
+  %tmp1 = load i32* getelementptr inbounds ([40 x i32]* @A, i32 0, i32 0) ; <i32> [#uses=1]
+  %call = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %tmp, i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), i32 %tmp1) ; <i32> [#uses=0]
+  %tmp2 = load i32* getelementptr inbounds ([40 x i32]* @A, i32 0, i64 38) ; <i32> [#uses=1]
+  %cmp = icmp eq i32 %tmp2, 19                    ; <i1> [#uses=1]
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.else:                                          ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+declare i32 @fprintf(%struct._IO_FILE*, i8*, ...)
+
+; CHECK: for (int c0 = 0; c0 <= 19; c0 += 1)
+; CHECK:   Stmt_do_cond(c0);
+
+
diff --git a/final/test/Isl/CodeGen/single_loop.ll b/final/test/Isl/CodeGen/single_loop.ll
new file mode 100644
index 0000000..c80e225
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_loop.ll
@@ -0,0 +1,85 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+
+;#include <string.h>
+;#define N 1024
+;
+;int main () {
+;  int i;
+;  int A[N];
+;
+;  memset(A, 0, sizeof(int) * N);
+;
+;  for (i = 0; i < N; i++) {
+;    A[i] = 1;
+;  }
+;
+;  for (i = 0; i < N; i++)
+;    if (A[i] != 1)
+;      return 1;
+;
+;  return 0;
+;}
+;
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [1024 x i32], align 4               ; <[1024 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [1024 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %conv = bitcast i32* %arraydecay to i8*         ; <i8*> [#uses=1]
+  call void @llvm.memset.p0i8.i64(i8* %conv, i8 0, i64 4096, i32 1, i1 false)
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.inc ], [ 0, %entry ] ; <i64> [#uses=3]
+  %arrayidx = getelementptr [1024 x i32]* %A, i64 0, i64 %indvar1 ; <i32*> [#uses=1]
+  %exitcond = icmp ne i64 %indvar1, 1024          ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  store i32 1, i32* %arrayidx
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next2 = add i64 %indvar1, 1             ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc07, %for.end
+  %indvar = phi i64 [ %indvar.next, %for.inc07 ], [ 0, %for.end ] ; <i64> [#uses=3]
+  %arrayidx13 = getelementptr [1024 x i32]* %A, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  %i.1 = trunc i64 %indvar to i32                 ; <i32> [#uses=1]
+  %cmp7 = icmp slt i32 %i.1, 1024                 ; <i1> [#uses=1]
+  br i1 %cmp7, label %for.body9, label %for.end20
+
+for.body9:                                        ; preds = %for.cond5
+  %tmp14 = load i32* %arrayidx13                  ; <i32> [#uses=1]
+  %cmp15 = icmp ne i32 %tmp14, 1                  ; <i1> [#uses=1]
+  br i1 %cmp15, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body9
+  br label %return
+
+if.end:                                           ; preds = %for.body9
+  br label %for.inc07
+
+for.inc07:                                        ; preds = %if.end
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %for.cond5
+
+for.end20:                                        ; preds = %for.cond5
+  br label %return
+
+return:                                           ; preds = %for.end20, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ 0, %for.end20 ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: for (int c0 = 0; c0 <= 1023; c0 += 1)
+; CHECK:   Stmt_for_body(c0);
diff --git a/final/test/Isl/CodeGen/single_loop_int_max_iterations.ll b/final/test/Isl/CodeGen/single_loop_int_max_iterations.ll
new file mode 100644
index 0000000..c76c18a
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_loop_int_max_iterations.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -analyze  -S < %s | FileCheck %s
+
+;#define N 20
+;#include "limits.h"
+;
+;int main () {
+;  int i;
+;  int A[N];
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 0; i < INT_MAX; i++)
+;    A[0] = i;
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == INT_MAX - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i32], align 4                 ; <[20 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx = getelementptr inbounds i32* %arraydecay, i64 0 ; <i32*> [#uses=1]
+  store i32 0, i32* %arrayidx
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]  ; <i32> [#uses=3]
+  %exitcond = icmp ne i32 %0, 2147483647          ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arraydecay2 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx3 = getelementptr inbounds i32* %arraydecay2, i64 0 ; <i32*> [#uses=1]
+  store i32 %0, i32* %arrayidx3
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %0, 1                        ; <i32> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  %arraydecay5 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx6 = getelementptr inbounds i32* %arraydecay5, i64 0 ; <i32*> [#uses=1]
+  %tmp7 = load i32* %arrayidx6                    ; <i32> [#uses=1]
+  %cmp8 = icmp eq i32 %tmp7, 2147483646           ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.end
+  br label %return
+
+if.else:                                          ; preds = %for.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK: for (int c0 = 0; c0 <= 2147483646; c0 += 1)
+; CHECK:   Stmt_for_body(c0);
diff --git a/final/test/Isl/CodeGen/single_loop_ll_max_iterations.ll b/final/test/Isl/CodeGen/single_loop_ll_max_iterations.ll
new file mode 100644
index 0000000..7d34b2f
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_loop_ll_max_iterations.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -analyze  -S < %s | FileCheck %s
+
+;#include "limits.h"
+;#define N 20
+;
+;int main () {
+;  long long i;
+;  long long A[N];
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 0; i < LLONG_MAX; i++)
+;    A[0] = i;
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == LLONG_MAX - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i64], align 8                 ; <[20 x i64]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i64]* %A, i32 0, i32 0 ; <i64*> [#uses=1]
+  %arrayidx = getelementptr inbounds i64* %arraydecay, i64 0 ; <i64*> [#uses=1]
+  store i64 0, i64* %arrayidx
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]  ; <i64> [#uses=3]
+  %exitcond = icmp ne i64 %0, 9223372036854775807 ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arraydecay2 = getelementptr inbounds [20 x i64]* %A, i32 0, i32 0 ; <i64*> [#uses=1]
+  %arrayidx3 = getelementptr inbounds i64* %arraydecay2, i64 0 ; <i64*> [#uses=1]
+  store i64 %0, i64* %arrayidx3
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i64 %0, 1                        ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  %arraydecay5 = getelementptr inbounds [20 x i64]* %A, i32 0, i32 0 ; <i64*> [#uses=1]
+  %arrayidx6 = getelementptr inbounds i64* %arraydecay5, i64 0 ; <i64*> [#uses=1]
+  %tmp7 = load i64* %arrayidx6                    ; <i64> [#uses=1]
+  %cmp8 = icmp eq i64 %tmp7, 9223372036854775806  ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.end
+  br label %return
+
+if.else:                                          ; preds = %for.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK: for (int c0 = 0; c0 <= 9223372036854775806; c0 += 1)
+; CHECK:   Stmt_for_body(c0);
diff --git a/final/test/Isl/CodeGen/single_loop_one_iteration.ll b/final/test/Isl/CodeGen/single_loop_one_iteration.ll
new file mode 100644
index 0000000..9e973a9
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_loop_one_iteration.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+
+;#define N 20
+;
+;int main () {
+;  int i;
+;  int A[N];
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 0; i < 1; i++)
+;    A[i] = 1;
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i32], align 4                 ; <[20 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx = getelementptr inbounds i32* %arraydecay, i64 0 ; <i32*> [#uses=1]
+  store i32 0, i32* %arrayidx
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ] ; <i64> [#uses=3]
+  %arrayidx3 = getelementptr [20 x i32]* %A, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  %exitcond = icmp ne i64 %indvar, 1              ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  store i32 1, i32* %arrayidx3
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  %arraydecay5 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx6 = getelementptr inbounds i32* %arraydecay5, i64 0 ; <i32*> [#uses=1]
+  %tmp7 = load i32* %arrayidx6                    ; <i32> [#uses=1]
+  %cmp8 = icmp eq i32 %tmp7, 1                    ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.end
+  br label %return
+
+if.else:                                          ; preds = %for.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK: Stmt_for_body(0);
diff --git a/final/test/Isl/CodeGen/single_loop_param.ll b/final/test/Isl/CodeGen/single_loop_param.ll
new file mode 100644
index 0000000..402b683
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_loop_param.ll
@@ -0,0 +1,71 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer, align 16 ; <[1024 x i32]*> [#uses=3]
+
+define void @bar(i64 %n) nounwind {
+bb:
+  fence seq_cst
+  br label %bb1
+
+bb1:                                              ; preds = %bb3, %bb
+  %i.0 = phi i64 [ 0, %bb ], [ %tmp, %bb3 ]       ; <i64> [#uses=3]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i.0 ; <i32*> [#uses=1]
+  %exitcond = icmp ne i64 %i.0, %n                ; <i1> [#uses=1]
+  br i1 %exitcond, label %bb2, label %bb4
+
+bb2:                                              ; preds = %bb1
+  store i32 1, i32* %scevgep
+  br label %bb3
+
+bb3:                                              ; preds = %bb2
+  %tmp = add nsw i64 %i.0, 1                      ; <i64> [#uses=1]
+  br label %bb1
+
+bb4:                                              ; preds = %bb1
+  fence seq_cst
+  ret void
+}
+
+define i32 @main() nounwind {
+bb:
+  call void @llvm.memset.p0i8.i64(i8* bitcast ([1024 x i32]* @A to i8*), i8 0, i64 4096, i32 1, i1 false)
+  call void @bar(i64 1024)
+  br label %bb1
+
+bb1:                                              ; preds = %bb7, %bb
+  %indvar = phi i64 [ %indvar.next, %bb7 ], [ 0, %bb ] ; <i64> [#uses=3]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  %i.0 = trunc i64 %indvar to i32                 ; <i32> [#uses=1]
+  %tmp = icmp slt i32 %i.0, 1024                  ; <i1> [#uses=1]
+  br i1 %tmp, label %bb2, label %bb8
+
+bb2:                                              ; preds = %bb1
+  %tmp3 = load i32* %scevgep                      ; <i32> [#uses=1]
+  %tmp4 = icmp ne i32 %tmp3, 1                    ; <i1> [#uses=1]
+  br i1 %tmp4, label %bb5, label %bb6
+
+bb5:                                              ; preds = %bb2
+  br label %bb9
+
+bb6:                                              ; preds = %bb2
+  br label %bb7
+
+bb7:                                              ; preds = %bb6
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %bb1
+
+bb8:                                              ; preds = %bb1
+  br label %bb9
+
+bb9:                                              ; preds = %bb8, %bb5
+  %.0 = phi i32 [ 1, %bb5 ], [ 0, %bb8 ]          ; <i32> [#uses=1]
+  ret i32 %.0
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   Stmt_bb2(c0);
+
diff --git a/final/test/Isl/CodeGen/single_loop_zero_iterations.ll b/final/test/Isl/CodeGen/single_loop_zero_iterations.ll
new file mode 100644
index 0000000..e4c336c
--- /dev/null
+++ b/final/test/Isl/CodeGen/single_loop_zero_iterations.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-ast -analyze  -S < %s | FileCheck %s
+
+;#define N 20
+;
+;int main () {
+;  int i;
+;  int A[N];
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 0; i < 0; i++)
+;    A[i] = 1;
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == 0)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i32], align 4                 ; <[20 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx = getelementptr inbounds i32* %arraydecay, i64 0 ; <i32*> [#uses=1]
+  store i32 0, i32* %arrayidx
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ] ; <i64> [#uses=2]
+  %arrayidx3 = getelementptr [20 x i32]* %A, i64 0, i64 %indvar ; <i32*> [#uses=1]
+  br i1 false, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  store i32 1, i32* %arrayidx3
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  %arraydecay5 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx6 = getelementptr inbounds i32* %arraydecay5, i64 0 ; <i32*> [#uses=1]
+  %tmp7 = load i32* %arrayidx6                    ; <i32> [#uses=1]
+  %cmp8 = icmp eq i32 %tmp7, 0                    ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.end
+  br label %return
+
+if.else:                                          ; preds = %for.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK: for region: 'for.cond => for.end.region' in function 'main':
+; CHECK-NOT:   Stmt_for_body(0);
diff --git a/final/test/Isl/CodeGen/split_edges.ll b/final/test/Isl/CodeGen/split_edges.ll
new file mode 100644
index 0000000..93ffa9b
--- /dev/null
+++ b/final/test/Isl/CodeGen/split_edges.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-codegen-isl -verify-region-info -verify-dom-info -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define void @loop_with_condition() nounwind {
+bb0:
+  fence seq_cst
+  br label %bb1
+
+bb1:
+  br i1 true, label %bb2, label %bb3
+
+bb2:
+  %ind1 = phi i32 [0, %bb1], [ %inc0, %bb2]
+  %inc0 = add i32 %ind1, 1
+  %cond1 = icmp eq i32 %ind1, 32
+  br i1 %cond1, label %bb4, label %bb2
+
+bb3:
+  %ind2 = phi i32 [0, %bb1], [ %inc2, %bb3]
+  %inc2 = add i32 %ind2, 1
+  br i1 true, label %bb4, label %bb3
+
+bb4:
+  br label %bb5
+
+bb5:
+  fence seq_cst
+  ret void
+
+}
+
+; CHECK: polly.split_new_and_old
+; CHECK: polly.merge_new_and_old
diff --git a/final/test/Isl/CodeGen/split_edges_2.ll b/final/test/Isl/CodeGen/split_edges_2.ll
new file mode 100644
index 0000000..386845f
--- /dev/null
+++ b/final/test/Isl/CodeGen/split_edges_2.ll
@@ -0,0 +1,33 @@
+; RUN: opt %loadPolly -polly-codegen-isl -verify-region-info -verify-dom-info -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define void @loop_with_condition() nounwind {
+bb0:
+  fence seq_cst
+  br label %bb1
+
+bb1:
+  br label %bb2
+
+bb2:
+  %ind1 = phi i32 [0, %bb1], [ %inc0, %bb2]
+  %inc0 = add i32 %ind1, 1
+  %cond1 = icmp eq i32 %ind1, 32
+  br i1 %cond1, label %bb4, label %bb2
+
+bb4:
+  br label %bb5
+
+bb5:
+  fence seq_cst
+  ret void
+
+}
+
+; CHECK: polly.split_new_and_old
+; CHECK: polly.merge_new_and_old
+
+
+
diff --git a/final/test/Isl/CodeGen/test-invalid-operands-for-select-2.ll b/final/test/Isl/CodeGen/test-invalid-operands-for-select-2.ll
new file mode 100644
index 0000000..fd8589d
--- /dev/null
+++ b/final/test/Isl/CodeGen/test-invalid-operands-for-select-2.ll
@@ -0,0 +1,56 @@
+; RUN: opt %loadPolly -S -polly-code-generator=isl -polly-codegen-isl -verify-loop-info < %s | FileCheck %s
+;
+; Check that we do not crash as described here: http://llvm.org/bugs/show_bug.cgi?id=21167
+;
+; CHECK: polly.split_new_and_old
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind uwtable
+define void @kernel_fdtd_apml(i32 %cxm, i32 %cym, [65 x [65 x double]]* %Bza, [65 x [65 x double]]* %Hz, double* %czp) #0 {
+entry:
+  br i1 false, label %for.cond4.preheader, label %for.end451
+
+for.cond4.preheader:                              ; preds = %for.inc449, %entry
+  %iz.08 = phi i32 [ undef, %for.inc449 ], [ 0, %entry ]
+  %cmp55 = icmp sgt i32 %cym, 0
+  br i1 %cmp55, label %for.cond7.preheader, label %for.inc449
+
+for.cond7.preheader:                              ; preds = %for.end, %for.cond4.preheader
+  %iy.06 = phi i32 [ %inc447, %for.end ], [ 0, %for.cond4.preheader ]
+  %cmp81 = icmp sgt i32 %cxm, 0
+  br i1 %cmp81, label %for.body9, label %for.end
+
+for.body9:                                        ; preds = %for.body9, %for.cond7.preheader
+  %ix.02 = phi i32 [ %inc, %for.body9 ], [ 0, %for.cond7.preheader ]
+  %idxprom74 = sext i32 %iz.08 to i64
+  %arrayidx75 = getelementptr inbounds double* %czp, i64 %idxprom74
+  %0 = load double* %arrayidx75, align 8
+  %idxprom102 = sext i32 %iz.08 to i64
+  %arrayidx105 = getelementptr inbounds [65 x [65 x double]]* %Hz, i64 %idxprom102, i64 0, i64 0
+  store double undef, double* %arrayidx105, align 8
+  %inc = add nsw i32 %ix.02, 1
+  br i1 false, label %for.body9, label %for.end
+
+for.end:                                          ; preds = %for.body9, %for.cond7.preheader
+  %idxprom209 = sext i32 %cxm to i64
+  %idxprom211 = sext i32 %iz.08 to i64
+  %arrayidx214 = getelementptr inbounds [65 x [65 x double]]* %Hz, i64 %idxprom211, i64 0, i64 %idxprom209
+  store double undef, double* %arrayidx214, align 8
+  %idxprom430 = sext i32 %cxm to i64
+  %idxprom431 = sext i32 %cym to i64
+  %idxprom432 = sext i32 %iz.08 to i64
+  %arrayidx435 = getelementptr inbounds [65 x [65 x double]]* %Hz, i64 %idxprom432, i64 %idxprom431, i64 %idxprom430
+  store double undef, double* %arrayidx435, align 8
+  %arrayidx445 = getelementptr inbounds [65 x [65 x double]]* %Bza, i64 0, i64 0, i64 0
+  store double undef, double* %arrayidx445, align 8
+  %inc447 = add nsw i32 %iy.06, 1
+  %cmp5 = icmp slt i32 %inc447, %cym
+  br i1 %cmp5, label %for.cond7.preheader, label %for.inc449
+
+for.inc449:                                       ; preds = %for.end, %for.cond4.preheader
+  br i1 undef, label %for.cond4.preheader, label %for.end451
+
+for.end451:                                       ; preds = %for.inc449, %entry
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/test-invalid-operands-for-select.ll b/final/test/Isl/CodeGen/test-invalid-operands-for-select.ll
new file mode 100644
index 0000000..b838b5c
--- /dev/null
+++ b/final/test/Isl/CodeGen/test-invalid-operands-for-select.ll
@@ -0,0 +1,81 @@
+; RUN: opt %loadPolly -S -polly-code-generator=isl -polly-codegen-isl < %s | FileCheck %s
+;
+; Check that we do not crash as described here: http://llvm.org/PR21167
+;
+; In case the pieceweise affine function used to create an isl_ast_expr
+; had empty cases (e.g., with contradicting constraints on the
+; parameters), it was possible that the condition of the isl_ast_expr
+; select was not a comparison but a constant (thus of type i64).
+; However, we shouldn't crash in such a case :)
+;
+; CHECK: polly.split_new_and_old
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind uwtable
+define void @dradb4(i32 %ido, i32 %l1, float* %cc, float* %ch, float* %wa1, float* %wa3) #0 {
+entry:
+  %mul = mul nsw i32 %l1, %ido
+  br i1 undef, label %for.end256, label %if.end
+
+if.end:                                           ; preds = %entry
+  br i1 undef, label %L105, label %for.cond45.preheader
+
+for.cond45.preheader:                             ; preds = %if.end
+  br i1 undef, label %for.body47, label %for.end198
+
+for.body47:                                       ; preds = %for.inc096, %for.cond45.preheader
+  br i1 undef, label %for.body53.lr.ph, label %for.inc096
+
+for.body53.lr.ph:                                 ; preds = %for.body47
+  br label %for.body53
+
+for.body53:                                       ; preds = %for.body53, %for.body53.lr.ph
+  %t7.014 = phi i32 [ 0, %for.body53.lr.ph ], [ %add58, %for.body53 ]
+  %i.013 = phi i32 [ 2, %for.body53.lr.ph ], [ %add193, %for.body53 ]
+  %add58 = add nsw i32 %t7.014, 2
+  %arrayidx70 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx72 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx77 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx81 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx84 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx95 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx105 = getelementptr inbounds float* %cc, i64 0
+  %arrayidx110 = getelementptr inbounds float* %ch, i64 0
+  store float undef, float* %arrayidx110, align 4
+  %arrayidx122 = getelementptr inbounds float* %wa1, i64 0
+  %add129 = add nsw i32 %add58, %mul
+  %idxprom142 = sext i32 %add129 to i64
+  %arrayidx143 = getelementptr inbounds float* %ch, i64 %idxprom142
+  store float undef, float* %arrayidx143, align 4
+  %add153 = add nsw i32 %add129, %mul
+  %arrayidx170 = getelementptr inbounds float* %wa3, i64 0
+  %arrayidx174 = getelementptr inbounds float* %wa3, i64 0
+  %add177 = add nsw i32 %add153, %mul
+  %sub178 = add nsw i32 %add177, -1
+  %idxprom179 = sext i32 %sub178 to i64
+  %arrayidx180 = getelementptr inbounds float* %ch, i64 %idxprom179
+  store float undef, float* %arrayidx180, align 4
+  %arrayidx183 = getelementptr inbounds float* %wa3, i64 0
+  %0 = load float* %arrayidx183, align 4
+  %mul184 = fmul float undef, %0
+  %add189 = fadd float %mul184, 0.000000e+00
+  %idxprom190 = sext i32 %add177 to i64
+  %arrayidx191 = getelementptr inbounds float* %ch, i64 %idxprom190
+  store float %add189, float* %arrayidx191, align 4
+  %add193 = add nsw i32 %i.013, 2
+  %cmp52 = icmp slt i32 %add193, %ido
+  br i1 %cmp52, label %for.body53, label %for.inc096
+
+for.inc096:                                       ; preds = %for.body53, %for.body47
+  br i1 undef, label %for.body47, label %for.end198
+
+for.end198:                                       ; preds = %for.inc096, %for.cond45.preheader
+  br i1 false, label %for.end256, label %L105
+
+L105:                                             ; preds = %for.end198, %if.end
+  br label %for.end256
+
+for.end256:                                       ; preds = %L105, %for.end198, %entry
+  ret void
+}
diff --git a/final/test/Isl/CodeGen/test.ll b/final/test/Isl/CodeGen/test.ll
new file mode 100644
index 0000000..6b76682
--- /dev/null
+++ b/final/test/Isl/CodeGen/test.ll
@@ -0,0 +1,68 @@
+; RUN: opt %loadPolly -polly-ast -analyze  -S < %s | FileCheck %s
+; XFAIL: *
+
+;int bar1();
+;int bar2();
+;int bar3();
+;int k;
+;#define N 100
+;int A[N];
+;
+;int foo (int z) {
+;  int i, j;
+;
+;  for (i = 0; i < N; i++) {
+;    A[i] = i;
+;
+;      for (j = 0; j < N * 2; j++)
+;        A[i] = j * A[i];
+;  }
+;
+;  return A[z];
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [100 x i32] zeroinitializer, align 4 ; <[100 x i32]*> [#uses=2]
+@k = common global i32 0, align 4                 ; <i32*> [#uses=0]
+
+define i32 @foo(i32 %z) nounwind {
+bb.nph31.split.us:
+  br label %bb.nph.us
+
+for.inc06.us:                                     ; preds = %for.body6.us
+  store i32 %mul.us, i32* %arrayidx.us
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=2]
+  %exitcond32 = icmp eq i64 %indvar.next, 100     ; <i1> [#uses=1]
+  br i1 %exitcond32, label %for.end19, label %bb.nph.us
+
+for.body6.us:                                     ; preds = %for.body6.us, %bb.nph.us
+  %arrayidx10.tmp.0.us = phi i32 [ %i.027.us, %bb.nph.us ], [ %mul.us, %for.body6.us ] ; <i32> [#uses=1]
+  %0 = phi i32 [ 0, %bb.nph.us ], [ %inc.us, %for.body6.us ] ; <i32> [#uses=2]
+  %mul.us = mul i32 %arrayidx10.tmp.0.us, %0      ; <i32> [#uses=2]
+  %inc.us = add nsw i32 %0, 1                     ; <i32> [#uses=2]
+  %exitcond = icmp eq i32 %inc.us, 200            ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.inc06.us, label %for.body6.us
+
+bb.nph.us:                                        ; preds = %bb.nph31.split.us, %for.inc06.us
+  %indvar = phi i64 [ %indvar.next, %for.inc06.us ], [ 0, %bb.nph31.split.us ] ; <i64> [#uses=3]
+  %arrayidx.us = getelementptr [100 x i32]* @A, i64 0, i64 %indvar ; <i32*> [#uses=2]
+  %i.027.us = trunc i64 %indvar to i32            ; <i32> [#uses=2]
+  store i32 %i.027.us, i32* %arrayidx.us
+  br label %for.body6.us
+
+for.end19:                                        ; preds = %for.inc06.us
+  %idxprom21 = sext i32 %z to i64                 ; <i64> [#uses=1]
+  %arrayidx22 = getelementptr inbounds [100 x i32]* @A, i64 0, i64 %idxprom21 ; <i32*> [#uses=1]
+  %tmp23 = load i32* %arrayidx22                  ; <i32> [#uses=1]
+  ret i32 %tmp23
+}
+; CHECK: for (c2=0;c2<=99;c2++) {
+; CHECK:   S{{[0-4]}}(c2);
+; CHECK:   for (c4=0;c4<=199;c4++) {
+; CHECK:     S{{[[0-4]}}(c2,c4);
+; CHECK:   }
+; CHECK:   S{{[0-4]}}(c2);
+; CHECK: }
+
diff --git a/final/test/Isl/CodeGen/two-scops-in-row.ll b/final/test/Isl/CodeGen/two-scops-in-row.ll
new file mode 100644
index 0000000..e4e4270
--- /dev/null
+++ b/final/test/Isl/CodeGen/two-scops-in-row.ll
@@ -0,0 +1,41 @@
+; RUN: opt %loadPolly -polly-ast -analyze -polly-ignore-aliasing < %s | FileCheck %s 
+; RUN: opt %loadPolly -polly-codegen-isl -polly-ignore-aliasing < %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: if (1)
+; CHECK:     {
+; CHECK:       for (int c0 = 0; c0 <= -Scalar0.val.loadoutside + 99; c0 += 1)
+; CHECK:         Stmt_for_1(c0);
+; CHECK:       if (Scalar0.val.loadoutside >= 100)
+; CHECK:         Stmt_for_1(0);
+; CHECK:     }
+
+; CHECK: if (1)
+; CHECK:     Stmt_for_0(0);
+
+
+define void @foo(i32* %A) {
+entry:
+  %Scalar0 = alloca i32
+  br label %for.0
+
+for.0:
+  %Scalar0.val = load i32* %Scalar0
+  br i1 false, label %for.0, label %for.1.preheader
+
+for.1.preheader:
+  fence seq_cst
+  br label %for.1
+
+for.1:
+  %indvar.1 = phi i32 [ %Scalar0.val, %for.1.preheader ], [ %indvar.1.next, %for.1]
+  %arrayidx.1 = getelementptr inbounds i32* %A, i32 %indvar.1
+  store i32 1, i32* %arrayidx.1
+  %indvar.1.next = add nsw i32 %indvar.1, 1
+  %cmp.1 = icmp slt i32 %indvar.1.next, 100
+  br i1 %cmp.1, label %for.1, label %end
+
+end:
+  ret void
+}
diff --git a/final/test/Isl/single_loop_param_less_equal.ll b/final/test/Isl/single_loop_param_less_equal.ll
new file mode 100644
index 0000000..5d6f733
--- /dev/null
+++ b/final/test/Isl/single_loop_param_less_equal.ll
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl  -S < %s | FileCheck %s -check-prefix=CODEGEN
+; RUN: opt %loadPolly -polly-codegen-isl -loops -analyze < %s | FileCheck %s -check-prefix=LOOPS
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer
+
+define void @bar(i64 %n) {
+start:
+  %n_plus_one = add i64 %n, 1
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i
+  %exitcond = icmp ne i64 %i, %n_plus_one
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  store i32 1, i32* %scevgep
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: for (int c0 = 0; c0 <= n; c0 += 1)
+; CHECK:   Stmt_loop_body(c0)
+
+; CODEGEN: polly.start:
+; CODEGEN:   br label %polly.loop_if
+
+; CODEGEN: polly.loop_exit:
+; CODEGEN:   br label %polly.merge_new_and_old
+
+; CODEGEN: polly.loop_if:
+; CODEGEN:   %polly.loop_guard = icmp sle i64 0, %n
+; CODEGEN:   br i1 %polly.loop_guard, label %polly.loop_preheader, label %polly.loop_exit
+
+; CODEGEN: polly.loop_header:
+; CODEGEN:   %polly.indvar = phi i64 [ 0, %polly.loop_preheader ], [ %polly.indvar_next, %polly.stmt.loop.body ]
+; CODEGEN:   br label %polly.stmt.loop.body
+
+; CODEGEN: polly.stmt.loop.body:
+; CODEGEN:   [[PTR:%[a-zA-Z0-9_\.]+]] = getelementptr [1024 x i32]* @A, i64 0, i64 %polly.indvar
+; CODEGEN:   store i32 1, i32* [[PTR]]
+; CODEGEN:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; CODEGEN:   %polly.adjust_ub = sub i64 %n, 1
+; CODEGEN:   %polly.loop_cond = icmp sle i64 %polly.indvar, %polly.adjust_ub
+; CODEGEN:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
+
+; CODEGEN: polly.loop_preheader:
+; CODEGEN:   br label %polly.loop_header
+
+; LOOPS: Loop at depth 1 containing: %loop.header<header><exiting>,%loop.body,%loop.backedge<latch>
+; LOOPS: Loop at depth 1 containing: %polly.loop_header<header>,%polly.stmt.loop.body<latch><exiting>
diff --git a/final/test/Isl/single_loop_param_less_than.ll b/final/test/Isl/single_loop_param_less_than.ll
new file mode 100644
index 0000000..b8a673d
--- /dev/null
+++ b/final/test/Isl/single_loop_param_less_than.ll
@@ -0,0 +1,58 @@
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl  -S < %s | FileCheck %s -check-prefix=CODEGEN
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@A = common global [1024 x i32] zeroinitializer
+
+define void @bar(i64 %n) {
+start:
+  fence seq_cst
+  br label %loop.header
+
+loop.header:
+  %i = phi i64 [ 0, %start ], [ %i.next, %loop.backedge ]
+  %scevgep = getelementptr [1024 x i32]* @A, i64 0, i64 %i
+  %exitcond = icmp ne i64 %i, %n
+  br i1 %exitcond, label %loop.body, label %ret
+
+loop.body:
+  store i32 1, i32* %scevgep
+  br label %loop.backedge
+
+loop.backedge:
+  %i.next = add nsw i64 %i, 1
+  br label %loop.header
+
+ret:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
+; CHECK:   Stmt_loop_body(c0)
+
+; CODEGEN: polly.start:
+; CODEGEN:   br label %polly.loop_if
+
+; CODEGEN: polly.loop_exit:
+; CODEGEN:   br label %polly.merge_new_and_old
+
+; CODEGEN: polly.loop_if:
+; CODEGEN:   %polly.loop_guard = icmp slt i64 0, %n
+; CODEGEN:   br i1 %polly.loop_guard, label %polly.loop_preheader, label %polly.loop_exit
+
+; CODEGEN: polly.loop_header:
+; CODEGEN:   %polly.indvar = phi i64 [ 0, %polly.loop_preheader ], [ %polly.indvar_next, %polly.stmt.loop.body ]
+; CODEGEN:   br label %polly.stmt.loop.body
+
+; CODEGEN: polly.stmt.loop.body:
+; CODEGEN:   [[PTR:%[a-zA-Z0-9_\.]+]] =  getelementptr [1024 x i32]* @A, i64 0, i64 %polly.indvar
+; CODEGEN:   store i32 1, i32* [[PTR]]
+; CODEGEN:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; CODEGEN:   %polly.adjust_ub = sub i64 %n, 1
+; CODEGEN:   %polly.loop_cond = icmp slt i64 %polly.indvar, %polly.adjust_ub
+; CODEGEN:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
+
+; CODEGEN: polly.loop_preheader:
+; CODEGEN:   br label %polly.loop_header
diff --git a/final/test/Isl/single_loop_uint_max_iterations.ll b/final/test/Isl/single_loop_uint_max_iterations.ll
new file mode 100644
index 0000000..de1982f
--- /dev/null
+++ b/final/test/Isl/single_loop_uint_max_iterations.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -S -analyze  < %s | FileCheck %s
+; XFAIL: *
+
+;#include "limits.h"
+;#define N 20
+;
+;int main () {
+;  unsigned int i;
+;  unsigned int A[N];
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 0; i < UINT_MAX; i++)
+;    A[0] = i;
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == UINT_MAX - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i32], align 4                 ; <[20 x i32]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx = getelementptr inbounds i32* %arraydecay, i64 0 ; <i32*> [#uses=1]
+  store i32 0, i32* %arrayidx
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]  ; <i32> [#uses=3]
+  %exitcond = icmp ne i32 %0, -1                  ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arraydecay2 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx3 = getelementptr inbounds i32* %arraydecay2, i64 0 ; <i32*> [#uses=1]
+  store i32 %0, i32* %arrayidx3
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add i32 %0, 1                            ; <i32> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  %arraydecay5 = getelementptr inbounds [20 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1]
+  %arrayidx6 = getelementptr inbounds i32* %arraydecay5, i64 0 ; <i32*> [#uses=1]
+  %tmp7 = load i32* %arrayidx6                    ; <i32> [#uses=1]
+  %cmp8 = icmp eq i32 %tmp7, -2                   ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.end
+  br label %return
+
+if.else:                                          ; preds = %for.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK:for (c2=0;
diff --git a/final/test/Isl/single_loop_ull_max_iterations.ll b/final/test/Isl/single_loop_ull_max_iterations.ll
new file mode 100644
index 0000000..78e1b86
--- /dev/null
+++ b/final/test/Isl/single_loop_ull_max_iterations.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-ast -S -analyze  < %s | FileCheck %s
+; XFAIL: *
+
+;#include "limits.h"
+;#define N 20
+;
+;int main () {
+;  unsigned long long i;
+;  unsigned long long A[N];
+;
+;  A[0] = 0;
+;
+;  __sync_synchronize();
+;
+;  for (i = 0; i < ULLONG_MAX; i++)
+;    A[0] = i;
+;
+;  __sync_synchronize();
+;
+;  if (A[0] == ULLONG_MAX - 1)
+;    return 0;
+;  else
+;    return 1;
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %A = alloca [20 x i64], align 8                 ; <[20 x i64]*> [#uses=3]
+  %arraydecay = getelementptr inbounds [20 x i64]* %A, i32 0, i32 0 ; <i64*> [#uses=1]
+  %arrayidx = getelementptr inbounds i64* %arraydecay, i64 0 ; <i64*> [#uses=1]
+  store i64 0, i64* %arrayidx
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]  ; <i64> [#uses=3]
+  %exitcond = icmp ne i64 %0, -1                  ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arraydecay2 = getelementptr inbounds [20 x i64]* %A, i32 0, i32 0 ; <i64*> [#uses=1]
+  %arrayidx3 = getelementptr inbounds i64* %arraydecay2, i64 0 ; <i64*> [#uses=1]
+  store i64 %0, i64* %arrayidx3
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add i64 %0, 1                            ; <i64> [#uses=1]
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  fence seq_cst
+  %arraydecay5 = getelementptr inbounds [20 x i64]* %A, i32 0, i32 0 ; <i64*> [#uses=1]
+  %arrayidx6 = getelementptr inbounds i64* %arraydecay5, i64 0 ; <i64*> [#uses=1]
+  %tmp7 = load i64* %arrayidx6                    ; <i64> [#uses=1]
+  %cmp8 = icmp eq i64 %tmp7, -2                   ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then, label %if.else
+
+if.then:                                          ; preds = %for.end
+  br label %return
+
+if.else:                                          ; preds = %for.end
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.else ] ; <i32> [#uses=1]
+  ret i32 %retval.0
+}
+
+; CHECK:for (c2=0;
diff --git a/final/test/Makefile b/final/test/Makefile
new file mode 100644
index 0000000..bab51fe
--- /dev/null
+++ b/final/test/Makefile
@@ -0,0 +1,63 @@
+LEVEL := ..
+include $(LEVEL)/Makefile.common
+
+# Test in all immediate subdirectories if unset.
+ifdef TESTSUITE
+TESTDIRS := $(TESTSUITE:%=$(PROJ_SRC_DIR)/%)
+else
+TESTDIRS ?= $(PROJ_SRC_DIR)
+endif
+
+# 'lit' wants objdir paths, so it will pick up the lit.site.cfg.
+TESTDIRS := $(TESTDIRS:$(PROJ_SRC_DIR)%=$(PROJ_OBJ_DIR)%)
+
+# Allow EXTRA_TESTDIRS to provide additional test directories.
+TESTDIRS += $(EXTRA_TESTDIRS)
+
+ifndef TESTARGS
+ifdef VERBOSE
+TESTARGS = -v
+else
+TESTARGS = -s -v
+endif
+endif
+
+# Make sure any extra test suites can find the main site config.
+LIT_ARGS := --param polly_site_config=${PROJ_OBJ_DIR}/lit.site.cfg \
+            --param build_config=$(PROJ_OBJ_DIR)
+
+
+ifdef VG
+  LIT_ARGS += "--vg"
+endif
+
+
+check-polly:: lit.site.cfg polly-lib
+	@ echo '--- Running polly tests for $(TARGET_TRIPLE) ---'
+	@ $(PYTHON) $(LLVM_SRC_ROOT)/utils/lit/lit.py \
+	  $(LIT_ARGS) $(TESTARGS) $(TESTDIRS)
+
+FORCE:
+
+polly-lib: FORCE
+	$(MAKE) -C ../lib || exit 1;
+
+lit.site.cfg: FORCE
+	@echo "Making Polly 'lit.site.cfg' file..."
+	@sed -e "s#@LLVM_SOURCE_DIR@#$(LLVM_SRC_ROOT)#g" \
+	     -e "s#@LLVM_BINARY_DIR@#$(LLVM_OBJ_ROOT)#g" \
+	     -e "s#@LLVM_TOOLS_DIR@#$(LLVM_OBJ_ROOT)/$(BuildMode)/bin#g" \
+	     -e "s#@LLVM_LIBS_DIR@#$(LibDir)#g" \
+	     -e "s#@POLLY_SOURCE_DIR@#$(PROJ_SRC_DIR)/..#g" \
+	     -e "s#@POLLY_BINARY_DIR@#$(PROJ_OBJ_DIR)/..#g" \
+	     -e "s#@TARGET_TRIPLE@#$(TARGET_TRIPLE)#g" \
+	     -e "s#@LLVM_SHLIBEXT@#$(SHLIBEXT)#g" \
+             -e "s#@POLLY_LIB_DIR@#$(LibDir)#g" \
+             -e "s#@LINK_POLLY_INTO_TOOLS@#OFF#g" \
+             -e "s#@CUDALIB_FOUND@#$(CUDALIB_FOUND)#g" \
+	     $(PROJ_SRC_DIR)/lit.site.cfg.in > $@
+
+clean::
+	@ find . -name Output | xargs rm -fr
+
+.PHONY: check-polly clean
diff --git a/final/test/README b/final/test/README
new file mode 100644
index 0000000..e8470c6
--- /dev/null
+++ b/final/test/README
@@ -0,0 +1 @@
+place tests here
\ No newline at end of file
diff --git a/final/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll b/final/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll
new file mode 100644
index 0000000..1df2d84
--- /dev/null
+++ b/final/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll
@@ -0,0 +1,17 @@
+; RUN: opt %loadPolly -polly-opt-isl -S < %s
+target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32"
+target triple = "hexagon-unknown-linux-gnu"
+
+define void @sdbout_label() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entry
+  %0 = phi i32 [ 0, %entry ], [ %1, %for.cond ]
+  %1 = add nsw i32 %0, 1
+  %exitcond72 = icmp eq i32 %1, 7
+  br i1 %exitcond72, label %sw.epilog66, label %for.cond
+
+sw.epilog66:                                      ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScheduleOptimizer/2012-04-16-Trivially-vectorizable-loops.ll b/final/test/ScheduleOptimizer/2012-04-16-Trivially-vectorizable-loops.ll
new file mode 100644
index 0000000..71b82f7
--- /dev/null
+++ b/final/test/ScheduleOptimizer/2012-04-16-Trivially-vectorizable-loops.ll
@@ -0,0 +1,205 @@
+; RUN: opt %loadPolly -basicaa -polly-opt-isl %vector-opt < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+
+@A = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@B = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@stdout = external global %struct._IO_FILE*
+@.str = private unnamed_addr constant [5 x i8] c"%lf \00", align 1
+@C = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@.str1 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
+
+define void @init_array() nounwind uwtable {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc17, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc18, %for.inc17 ]
+  %cmp = icmp slt i32 %i.0, 1536
+  br i1 %cmp, label %for.body, label %for.end19
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %cmp2 = icmp slt i32 %j.0, 1536
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %mul = mul nsw i32 %i.0, %j.0
+  %rem = srem i32 %mul, 1024
+  %add = add nsw i32 1, %rem
+  %conv = sitofp i32 %add to double
+  %div = fdiv double %conv, 2.000000e+00
+  %conv4 = fptrunc double %div to float
+  %idxprom = sext i32 %j.0 to i64
+  %idxprom5 = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds [1536 x [1536 x float]]* @A, i32 0, i64 %idxprom5
+  %arrayidx6 = getelementptr inbounds [1536 x float]* %arrayidx, i32 0, i64 %idxprom
+  store float %conv4, float* %arrayidx6, align 4
+  %mul7 = mul nsw i32 %i.0, %j.0
+  %rem8 = srem i32 %mul7, 1024
+  %add9 = add nsw i32 1, %rem8
+  %conv10 = sitofp i32 %add9 to double
+  %div11 = fdiv double %conv10, 2.000000e+00
+  %conv12 = fptrunc double %div11 to float
+  %idxprom13 = sext i32 %j.0 to i64
+  %idxprom14 = sext i32 %i.0 to i64
+  %arrayidx15 = getelementptr inbounds [1536 x [1536 x float]]* @B, i32 0, i64 %idxprom14
+  %arrayidx16 = getelementptr inbounds [1536 x float]* %arrayidx15, i32 0, i64 %idxprom13
+  store float %conv12, float* %arrayidx16, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc17
+
+for.inc17:                                        ; preds = %for.end
+  %inc18 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end19:                                        ; preds = %for.cond
+  ret void
+}
+
+define void @print_array() nounwind uwtable {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %cmp = icmp slt i32 %i.0, 1536
+  br i1 %cmp, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %cmp2 = icmp slt i32 %j.0, 1536
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %0 = load %struct._IO_FILE** @stdout, align 8
+  %idxprom = sext i32 %j.0 to i64
+  %idxprom4 = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom4
+  %arrayidx5 = getelementptr inbounds [1536 x float]* %arrayidx, i32 0, i64 %idxprom
+  %1 = load float* %arrayidx5, align 4
+  %conv = fpext float %1 to double
+  %call = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %0, i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0), double %conv)
+  %rem = srem i32 %j.0, 80
+  %cmp6 = icmp eq i32 %rem, 79
+  br i1 %cmp6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body3
+  %2 = load %struct._IO_FILE** @stdout, align 8
+  %call8 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %2, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body3
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  %3 = load %struct._IO_FILE** @stdout, align 8
+  %call9 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %3, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
+
+declare i32 @fprintf(%struct._IO_FILE*, i8*, ...)
+
+define i32 @main() nounwind uwtable {
+entry:
+  call void @init_array()
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc28, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc29, %for.inc28 ]
+  %cmp = icmp slt i32 %i.0, 1536
+  br i1 %cmp, label %for.body, label %for.end30
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc25, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc26, %for.inc25 ]
+  %cmp2 = icmp slt i32 %j.0, 1536
+  br i1 %cmp2, label %for.body3, label %for.end27
+
+for.body3:                                        ; preds = %for.cond1
+  %idxprom = sext i32 %j.0 to i64
+  %idxprom4 = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom4
+  %arrayidx5 = getelementptr inbounds [1536 x float]* %arrayidx, i32 0, i64 %idxprom
+  store float 0.000000e+00, float* %arrayidx5, align 4
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i32 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %cmp7 = icmp slt i32 %k.0, 1536
+  br i1 %cmp7, label %for.body8, label %for.end
+
+for.body8:                                        ; preds = %for.cond6
+  %idxprom9 = sext i32 %j.0 to i64
+  %idxprom10 = sext i32 %i.0 to i64
+  %arrayidx11 = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom10
+  %arrayidx12 = getelementptr inbounds [1536 x float]* %arrayidx11, i32 0, i64 %idxprom9
+  %0 = load float* %arrayidx12, align 4
+  %idxprom13 = sext i32 %k.0 to i64
+  %idxprom14 = sext i32 %i.0 to i64
+  %arrayidx15 = getelementptr inbounds [1536 x [1536 x float]]* @A, i32 0, i64 %idxprom14
+  %arrayidx16 = getelementptr inbounds [1536 x float]* %arrayidx15, i32 0, i64 %idxprom13
+  %1 = load float* %arrayidx16, align 4
+  %idxprom17 = sext i32 %j.0 to i64
+  %idxprom18 = sext i32 %k.0 to i64
+  %arrayidx19 = getelementptr inbounds [1536 x [1536 x float]]* @B, i32 0, i64 %idxprom18
+  %arrayidx20 = getelementptr inbounds [1536 x float]* %arrayidx19, i32 0, i64 %idxprom17
+  %2 = load float* %arrayidx20, align 4
+  %mul = fmul float %1, %2
+  %add = fadd float %0, %mul
+  %idxprom21 = sext i32 %j.0 to i64
+  %idxprom22 = sext i32 %i.0 to i64
+  %arrayidx23 = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom22
+  %arrayidx24 = getelementptr inbounds [1536 x float]* %arrayidx23, i32 0, i64 %idxprom21
+  store float %add, float* %arrayidx24, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body8
+  %inc = add nsw i32 %k.0, 1
+  br label %for.cond6
+
+for.end:                                          ; preds = %for.cond6
+  br label %for.inc25
+
+for.inc25:                                        ; preds = %for.end
+  %inc26 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end27:                                        ; preds = %for.cond1
+  br label %for.inc28
+
+for.inc28:                                        ; preds = %for.end27
+  %inc29 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end30:                                        ; preds = %for.cond
+  ret i32 0
+}
diff --git a/final/test/ScheduleOptimizer/2012-10-14-Zero-Bands.ll b/final/test/ScheduleOptimizer/2012-10-14-Zero-Bands.ll
new file mode 100644
index 0000000..894d57d
--- /dev/null
+++ b/final/test/ScheduleOptimizer/2012-10-14-Zero-Bands.ll
@@ -0,0 +1,27 @@
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-detect-scops-in-functions-without-loops -polly-opt-isl -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1536 x float] zeroinitializer
+
+define void @read_nres() {
+entry:
+  br label %if.cond
+
+if.cond:
+  br i1 false, label %if.then, label %if.end
+
+if.then:
+  %ptr = getelementptr [1536 x float]* @A, i64 0, i32 23
+  store float undef, float* %ptr
+  br label %if.end
+
+if.end:
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK: Calculated schedule:
+; CHECK-NOT: Stmt_if_then
diff --git a/final/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll b/final/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll
new file mode 100644
index 0000000..e81033a
--- /dev/null
+++ b/final/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll
@@ -0,0 +1,24 @@
+; RUN: opt %loadPolly -polly-opt-isl -S < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Check that we handle statements with an empty iteration domain correctly.
+
+define void @f() {
+entry:
+  %A = alloca double
+  br label %for
+
+for:
+  %indvar = phi i32 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i32 %indvar, -1
+  br i1 %exitcond, label %for.inc, label %return
+
+for.inc:
+  %indvar.next = add i32 %indvar, 1
+  store double 1.0, double* %A
+  br label %for
+
+return:
+  ret void
+}
diff --git a/final/test/ScheduleOptimizer/computeout.ll b/final/test/ScheduleOptimizer/computeout.ll
new file mode 100644
index 0000000..578478c
--- /dev/null
+++ b/final/test/ScheduleOptimizer/computeout.ll
@@ -0,0 +1,70 @@
+; RUN: opt -S %loadPolly -basicaa -polly-opt-isl -polly-opt-fusion=max -polly-ast -analyze < %s | FileCheck %s 
+; RUN: opt -S %loadPolly -basicaa -polly-opt-isl -polly-opt-fusion=max -polly-ast -analyze -polly-dependences-computeout=1 < %s | FileCheck %s -check-prefix=TIMEOUT
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+;     for(i = 0; i < 100; i++ )
+; S1:   A[i] = 2;
+;
+;     for (i = 0; i < 10; i++ )
+; S2:   A[i]  = 5;
+;
+;     for (i = 0; i < 200; i++ )
+; S3:   A[i] = 5;
+
+define void @sequential_writes() {
+entry:
+  %A = alloca [200 x i32]
+  br label %S1
+
+S1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
+  %arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
+  store i32 2, i32* %arrayidx.1
+  %indvar.next.1 = add i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, 100
+  br i1 %exitcond.1, label %S1, label %exit.1
+
+exit.1:
+  br label %S2
+
+S2:
+  %indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
+  %arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
+  store i32 5, i32* %arrayidx.2
+  %indvar.next.2 = add i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, 10
+  br i1 %exitcond.2, label %S2, label %exit.2
+
+exit.2:
+  br label %S3
+
+S3:
+  %indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
+  %arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
+  store i32 7, i32* %arrayidx.3
+  %indvar.next.3 = add i64 %indvar.3, 1
+  %exitcond.3 = icmp ne i64 %indvar.next.3, 200
+  br i1 %exitcond.3, label %S3 , label %exit.3
+
+exit.3:
+  ret void
+}
+
+
+; CHECK: for (int c0 = 0; c0 <= 199; c0 += 1) {
+; CHECK:   if (c0 <= 99) {
+; CHECK:     Stmt_S1(c0);
+; CHECK:     if (c0 <= 9)
+; CHECK:       Stmt_S2(c0);
+; CHECK:   }
+; CHECK:   Stmt_S3(c0);
+; CHECK: }
+
+; TIMEOUT: for (int c1 = 0; c1 <= 99; c1 += 1)
+; TIMEOUT: Stmt_S1(c1);
+; TIMEOUT: for (int c1 = 0; c1 <= 9; c1 += 1)
+; TIMEOUT: Stmt_S2(c1);
+; TIMEOUT: for (int c1 = 0; c1 <= 199; c1 += 1)
+; TIMEOUT: Stmt_S3(c1);
+
diff --git a/final/test/ScheduleOptimizer/line-tiling-2.ll b/final/test/ScheduleOptimizer/line-tiling-2.ll
new file mode 100644
index 0000000..7b4aa9c
--- /dev/null
+++ b/final/test/ScheduleOptimizer/line-tiling-2.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-opt-isl -analyze -polly-no-tiling=0 -polly-ast -polly-tile-sizes=1,64 < %s
+; CHECK: c0 += 1
+; CHECK: c1 += 64
+; CHECK: c1 <= c1 + 63
+; ModuleID = 'line-tiling-2.ll'
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+; Function Attrs: nounwind
+define void @line([512 x i32]* %A) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body3.lr.ph
+
+for.body3.lr.ph:                                  ; preds = %for.inc5, %entry.split
+  %i.0 = phi i32 [ 0, %entry.split ], [ %inc6, %for.inc5 ]
+  br label %for.body3
+
+for.body3:                                        ; preds = %for.body3.lr.ph, %for.body3
+  %j.0 = phi i32 [ 0, %for.body3.lr.ph ], [ %inc, %for.body3 ]
+  %mul = mul nsw i32 %j.0, %i.0
+  %rem = srem i32 %mul, 42
+  %arrayidx4 = getelementptr inbounds [512 x i32]* %A, i32 %i.0, i32 %j.0
+  store i32 %rem, i32* %arrayidx4, align 4
+  %inc = add nsw i32 %j.0, 1
+  %cmp2 = icmp slt i32 %inc, 512
+  br i1 %cmp2, label %for.body3, label %for.inc5
+
+for.inc5:                                         ; preds = %for.body3
+  %inc6 = add nsw i32 %i.0, 1
+  %cmp = icmp slt i32 %inc6, 1024
+  br i1 %cmp, label %for.body3.lr.ph, label %for.end7
+
+for.end7:                                         ; preds = %for.inc5
+  ret void
+}
diff --git a/final/test/ScheduleOptimizer/line-tiling.ll b/final/test/ScheduleOptimizer/line-tiling.ll
new file mode 100644
index 0000000..b9d1f8e
--- /dev/null
+++ b/final/test/ScheduleOptimizer/line-tiling.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-opt-isl -analyze -polly-no-tiling=0 -polly-ast -polly-tile-sizes=64,1 < %s
+; CHECK: c0 += 64
+; CHECK: c1 += 1
+; CHECK: c0 <= c0 + 63
+; ModuleID = 'line-tiling.ll'
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+; Function Attrs: nounwind
+define void @line([512 x i32]* %A) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body3.lr.ph
+
+for.body3.lr.ph:                                  ; preds = %for.inc5, %entry.split
+  %i.0 = phi i32 [ 0, %entry.split ], [ %inc6, %for.inc5 ]
+  br label %for.body3
+
+for.body3:                                        ; preds = %for.body3.lr.ph, %for.body3
+  %j.0 = phi i32 [ 0, %for.body3.lr.ph ], [ %inc, %for.body3 ]
+  %mul = mul nsw i32 %j.0, %i.0
+  %rem = srem i32 %mul, 42
+  %arrayidx4 = getelementptr inbounds [512 x i32]* %A, i32 %i.0, i32 %j.0
+  store i32 %rem, i32* %arrayidx4, align 4
+  %inc = add nsw i32 %j.0, 1
+  %cmp2 = icmp slt i32 %inc, 512
+  br i1 %cmp2, label %for.body3, label %for.inc5
+
+for.inc5:                                         ; preds = %for.body3
+  %inc6 = add nsw i32 %i.0, 1
+  %cmp = icmp slt i32 %inc6, 1024
+  br i1 %cmp, label %for.body3.lr.ph, label %for.end7
+
+for.end7:                                         ; preds = %for.inc5
+  ret void
+}
diff --git a/final/test/ScheduleOptimizer/prevectorization.ll b/final/test/ScheduleOptimizer/prevectorization.ll
new file mode 100644
index 0000000..8eb7511
--- /dev/null
+++ b/final/test/ScheduleOptimizer/prevectorization.ll
@@ -0,0 +1,78 @@
+; RUN: opt -S %loadPolly -basicaa -polly-opt-isl -polly-vectorizer=polly -polly-ast -analyze < %s | FileCheck %s 
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@C = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@A = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@B = common global [1536 x [1536 x float]] zeroinitializer, align 16
+
+; Function Attrs: nounwind uwtable
+define void @foo() #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.cond1.preheader
+
+for.cond1.preheader:                              ; preds = %entry.split, %for.inc28
+  %indvar4 = phi i64 [ 0, %entry.split ], [ %indvar.next5, %for.inc28 ]
+  br label %for.body3
+
+for.body3:                                        ; preds = %for.cond1.preheader, %for.inc25
+  %indvar6 = phi i64 [ 0, %for.cond1.preheader ], [ %indvar.next7, %for.inc25 ]
+  %arrayidx24 = getelementptr [1536 x [1536 x float]]* @C, i64 0, i64 %indvar4, i64 %indvar6
+  store float 0.000000e+00, float* %arrayidx24, align 4
+  br label %for.body8
+
+for.body8:                                        ; preds = %for.body3, %for.body8
+  %indvar = phi i64 [ 0, %for.body3 ], [ %indvar.next, %for.body8 ]
+  %arrayidx16 = getelementptr [1536 x [1536 x float]]* @A, i64 0, i64 %indvar4, i64 %indvar
+  %arrayidx20 = getelementptr [1536 x [1536 x float]]* @B, i64 0, i64 %indvar, i64 %indvar6
+  %0 = load float* %arrayidx24, align 4
+  %1 = load float* %arrayidx16, align 4
+  %2 = load float* %arrayidx20, align 4
+  %mul = fmul float %1, %2
+  %add = fadd float %0, %mul
+  store float %add, float* %arrayidx24, align 4
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp ne i64 %indvar.next, 1536
+  br i1 %exitcond, label %for.body8, label %for.inc25
+
+for.inc25:                                        ; preds = %for.body8
+  %indvar.next7 = add i64 %indvar6, 1
+  %exitcond8 = icmp ne i64 %indvar.next7, 1536
+  br i1 %exitcond8, label %for.body3, label %for.inc28
+
+for.inc28:                                        ; preds = %for.inc25
+  %indvar.next5 = add i64 %indvar4, 1
+  %exitcond9 = icmp ne i64 %indvar.next5, 1536
+  br i1 %exitcond9, label %for.cond1.preheader, label %for.end30
+
+for.end30:                                        ; preds = %for.inc28
+  ret void
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+; CHECK: #pragma known-parallel
+; CHECK: for (int c1 = 0; c1 <= 1535; c1 += 32)
+; CHECK:   for (int c2 = 0; c2 <= 1535; c2 += 32)
+; CHECK:     for (int c3 = c1; c3 <= c1 + 31; c3 += 1)
+; CHECK:       for (int c4 = c2; c4 <= c2 + 31; c4 += 4)
+; CHECK:         #pragma simd
+; CHECK:         for (int c5 = c4; c5 <= c4 + 3; c5 += 1)
+; CHECK:           Stmt_for_body3(c3, c5);
+; CHECK: #pragma known-parallel
+; CHECK: for (int c1 = 0; c1 <= 1535; c1 += 32)
+; CHECK:   for (int c2 = 0; c2 <= 1535; c2 += 32)
+; CHECK:     for (int c3 = 0; c3 <= 1535; c3 += 32)
+; CHECK:       for (int c4 = c1; c4 <= c1 + 31; c4 += 1)
+; CHECK:         for (int c5 = c2; c5 <= c2 + 31; c5 += 4)
+; CHECK:           for (int c6 = c3; c6 <= c3 + 31; c6 += 1)
+; CHECK:             #pragma simd
+; CHECK:             for (int c7 = c5; c7 <= c5 + 3; c7 += 1)
+; CHECK:               Stmt_for_body8(c4, c7, c6);
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.5.0 "}
diff --git a/final/test/ScheduleOptimizer/rectangular-tiling.ll b/final/test/ScheduleOptimizer/rectangular-tiling.ll
new file mode 100644
index 0000000..e2e21ba
--- /dev/null
+++ b/final/test/ScheduleOptimizer/rectangular-tiling.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-opt-isl -analyze -polly-no-tiling=0 -polly-ast -polly-tile-sizes=256,16 < %s
+; CHECK: c0 += 256
+; CHECK: c1 += 16
+; CHECK: c0 <= c0 + 255
+; CHECK: c1 <= c1 + 15
+; ModuleID = 'rectangular-tiling.ll'
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+; Function Attrs: nounwind
+define void @rect([512 x i32]* %A) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body3.lr.ph
+
+for.body3.lr.ph:                                  ; preds = %for.inc5, %entry.split
+  %i.0 = phi i32 [ 0, %entry.split ], [ %inc6, %for.inc5 ]
+  br label %for.body3
+
+for.body3:                                        ; preds = %for.body3.lr.ph, %for.body3
+  %j.0 = phi i32 [ 0, %for.body3.lr.ph ], [ %inc, %for.body3 ]
+  %mul = mul nsw i32 %j.0, %i.0
+  %rem = srem i32 %mul, 42
+  %arrayidx4 = getelementptr inbounds [512 x i32]* %A, i32 %i.0, i32 %j.0
+  store i32 %rem, i32* %arrayidx4, align 4
+  %inc = add nsw i32 %j.0, 1
+  %cmp2 = icmp slt i32 %inc, 512
+  br i1 %cmp2, label %for.body3, label %for.inc5
+
+for.inc5:                                         ; preds = %for.body3
+  %inc6 = add nsw i32 %i.0, 1
+  %cmp = icmp slt i32 %inc6, 1024
+  br i1 %cmp, label %for.body3.lr.ph, label %for.end7
+
+for.end7:                                         ; preds = %for.inc5
+  ret void
+}
diff --git a/final/test/ScopDetect/aliasing_parametric_simple_1.ll b/final/test/ScopDetect/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..dcd4241
--- /dev/null
+++ b/final/test/ScopDetect/aliasing_parametric_simple_1.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %idxprom = sext i32 %c to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopDetect/aliasing_parametric_simple_2.ll b/final/test/ScopDetect/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..8016f74
--- /dev/null
+++ b/final/test/ScopDetect/aliasing_parametric_simple_2.ll
@@ -0,0 +1,39 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c - 10] + B[5];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %sub = add nsw i32 %c, -10
+  %idxprom = sext i32 %sub to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 5
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx3 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopDetect/aliasing_simple_1.ll b/final/test/ScopDetect/aliasing_simple_1.ll
new file mode 100644
index 0000000..ec16930
--- /dev/null
+++ b/final/test/ScopDetect/aliasing_simple_1.ll
@@ -0,0 +1,33 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[0];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp = load i32* %B, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopDetect/aliasing_simple_2.ll b/final/test/ScopDetect/aliasing_simple_2.ll
new file mode 100644
index 0000000..79c1600
--- /dev/null
+++ b/final/test/ScopDetect/aliasing_simple_2.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[0] + B[1023];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp = load i32* %B, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 1023
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %add, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopDetect/base_pointer.ll b/final/test/ScopDetect/base_pointer.ll
new file mode 100644
index 0000000..92c76cd
--- /dev/null
+++ b/final/test/ScopDetect/base_pointer.ll
@@ -0,0 +1,297 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @base_pointer_in_condition(i64** noalias %A_ptr, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br label %pre
+
+pre:
+  %A = load i64** %A_ptr
+  br i1 true, label %for.i, label %then
+
+for.i:
+  %indvar = phi i64 [ 0, %pre ], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %then, label %for.i
+
+then:
+  br label %return
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_in_condition
+; CHECK: Valid Region for Scop: for.i => then
+
+define void @base_pointer_is_argument(float* %A, i64 %n) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %A, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_argument
+; CHECK: Valid Region for Scop: for.i => exit
+
+define void @base_pointer_is_const_expr(i64 %n) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* inttoptr (i64 100 to float*), i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_const_expr
+; CHECK-LABEL: Valid Region for Scop: for.i => exit
+
+@A = external global float
+
+define void @base_pointer_is_global(i64 %n) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* @A, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_global
+; CHECK: Valid Region for Scop: for.i => exit
+
+declare float *@foo()
+
+define void @base_pointer_is_inst_outside(i64 %n) {
+entry:
+  %A = call float *@foo()
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %A, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_inst_outside
+; CHECK: Valid Region for Scop: for.i => exit
+
+declare float* @getNextBasePtr(float*) readnone nounwind
+
+define void @base_pointer_is_phi_node(i64 %n, float* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  %ptr = phi float* [ %ptr.next, %for.i.inc ], [ %A, %entry ]
+; To get a PHI node inside a SCoP that can not be analyzed but
+; for which the surrounding SCoP is normally still valid we use a function
+; without any side effects.
+  %ptr.next = call float* @getNextBasePtr(float* %ptr)
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %ptr, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_phi_node
+; CHECK-NOT: Valid Region for Scop
+
+define void @base_pointer_is_inst_inside_invariant_1(i64 %n, float* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+; To get an instruction inside a region, we use a function without side
+; effects on which SCEV blocks, but for which it is still clear that the
+; return value remains invariant throughout the whole loop.
+  %ptr = call float* @getNextBasePtr(float* %A)
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %ptr, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_inst_inside_invariant_1
+; CHECK: Valid Region for Scop: for.i => exit
+
+declare float* @getNextBasePtr2(float*) readnone nounwind
+
+define void @base_pointer_is_inst_inside_invariant_2(i64 %n, float* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  %ptr = call float* @getNextBasePtr2(float* %A)
+  %ptr2 = call float* @getNextBasePtr(float* %ptr)
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %ptr2, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: base_pointer_is_inst_inside_invariant_2
+; CHECK: Valid Region for Scop: for.i => exit
+
+declare float* @getNextBasePtr3(float*, i64) readnone nounwind
+
+define void @base_pointer_is_inst_inside_variant(i64 %n, float* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  %ptr = call float* @getNextBasePtr3(float* %A, i64 %indvar.i)
+  %ptr2 = call float* @getNextBasePtr(float* %ptr)
+  br label %S1
+
+S1:
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %ptr2, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK: base_pointer_is_inst_inside_variant
+; CHECK-NOT: Valid Region for Scop
+
+define void @base_pointer_is_ptr2ptr(float** noalias %A, i64 %n) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  %arrayidx = getelementptr float** %A, i64 %indvar.i
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %for.i ], [ %indvar.j.next, %for.j ]
+  %conv = sitofp i64 %indvar.i to float
+  %basepointer = load float** %arrayidx, align 8
+  %arrayidx5 = getelementptr float* %basepointer, i64 %indvar.j
+  store float %conv, float* %arrayidx5, align 4
+  %indvar.j.next = add i64 %indvar.j, 1
+  %exitcond.j = icmp ne i64 %indvar.j.next, %n
+  br i1 %exitcond.j, label %for.j, label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK: base_pointer_is_ptr2ptr
+; CHECK-NOT: Valid Region for Scop
diff --git a/final/test/ScopDetect/cross_loop_non_single_exit.ll b/final/test/ScopDetect/cross_loop_non_single_exit.ll
new file mode 100644
index 0000000..cedee28
--- /dev/null
+++ b/final/test/ScopDetect/cross_loop_non_single_exit.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   if (true)
+;     for (i = 0; i < N; ++i)
+;       A[i] = i;
+;   else
+;     for (j = 0; j < N; ++j)
+;        A[j] = j;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %next, label %next2
+
+next2:
+  br i1 true, label %for.j, label %return
+
+for.j:
+  %indvar2 = phi i64 [ 0, %next2], [ %indvar2.next2, %for.j]
+  %scevgep2 = getelementptr i64* %A, i64 %indvar2
+  store i64 %indvar2, i64* %scevgep2
+  %indvar2.next2 = add nsw i64 %indvar2, 1
+  %exitcond2 = icmp eq i64 %indvar2.next2, %N
+  br i1 %exitcond2, label %return, label %for.j
+
+next:
+  br i1 true, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %next], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: next => return
+; CHECK: Valid Region for Scop: next2 => return
diff --git a/final/test/ScopDetect/cross_loop_non_single_exit_2.ll b/final/test/ScopDetect/cross_loop_non_single_exit_2.ll
new file mode 100644
index 0000000..f6c16d6
--- /dev/null
+++ b/final/test/ScopDetect/cross_loop_non_single_exit_2.ll
@@ -0,0 +1,62 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   if (true)
+;     for (i = 0; i < N; ++i)
+;       A[i] = i;
+;   else
+;     for (j = 0; j < N; ++j)
+;        A[j] = j;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i64 @foo()
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %next, label %next2
+
+next2:
+  br i1 true, label %for.j, label %return
+
+for.j:
+  %indvar2 = phi i64 [ 0, %next2], [ %indvar2.next2, %for.j]
+  %scevgep2 = getelementptr i64* %A, i64 %indvar2
+  store i64 %indvar2, i64* %scevgep2
+  %indvar2.next2 = add nsw i64 %indvar2, 1
+  %exitcond2 = icmp eq i64 %indvar2.next2, %N
+  br i1 %exitcond2, label %return, label %for.j
+
+next:
+  br i1 true, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %next], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %i = call i64 @foo()
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  br i1 true, label %return_a, label %return_b
+
+return_a:
+  br label %return_join
+
+return_b:
+  br label %return_join
+
+return_join:
+  fence seq_cst
+  ret void
+}
+
+; CHECK-NOT: Valid Region for Scop: next => return
+; CHECK: Valid Region for Scop: next2 => return
diff --git a/final/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll b/final/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll
new file mode 100644
index 0000000..2a67dd6
--- /dev/null
+++ b/final/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-detect < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N, i64 %M) nounwind {
+entry:
+  fence seq_cst
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %next, label %for.i
+
+next:
+  fence seq_cst
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ %indvar, %next ], [ %indvar.j.next, %for.j ]
+  %scevgep.j = getelementptr i64* %A, i64 %indvar.j
+  store i64 %indvar.j, i64* %scevgep.j
+  fence seq_cst
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %M
+  br i1 %exitcond.j, label %return, label %for.j
+
+return:
+  fence seq_cst
+  ret void
+}
diff --git a/final/test/ScopDetect/indvars.ll b/final/test/ScopDetect/indvars.ll
new file mode 100644
index 0000000..432ad10
--- /dev/null
+++ b/final/test/ScopDetect/indvars.ll
@@ -0,0 +1,41 @@
+; RUN: opt %loadPolly -analyze -polly-detect -polly-codegen-isl < %s | FileCheck %s
+;
+; When a region header is part of a loop, then all entering edges of this region
+; should not come from the loop but outside the region.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main(i64* %A) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.next.i, %for.i.backedge ]
+  %indvar.next.i = add i64 %indvar.i, 1
+  %scevgep = getelementptr i64* %A, i64 %indvar.i
+  store i64 %indvar.i, i64* %scevgep, align 4
+  br i1 true, label %for.j.preheader, label %for.j2
+
+for.j.preheader:
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ %indvar.next.j, %for.j ], [ 0, %for.j.preheader ]
+  %indvar.next.j = add i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.next.j, 10
+  br i1 %exitcond.j, label %for.j2, label %for.j
+
+for.j2:
+  fence seq_cst
+  br label %for.i.backedge
+
+for.i.backedge:
+  %exitcond.i = icmp eq i64 %indvar.next.i, 2048
+  br i1 %exitcond.i, label %for.i, label %.end
+
+.end:
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.j => for.j2
diff --git a/final/test/ScopDetect/invalidate_scalar_evolution.ll b/final/test/ScopDetect/invalidate_scalar_evolution.ll
new file mode 100644
index 0000000..314c79c
--- /dev/null
+++ b/final/test/ScopDetect/invalidate_scalar_evolution.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -polly-detect -analyze  < %s | FileCheck %s -check-prefix=CHECK
+
+; void f(long A[], long N) {
+;   long i;
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N, i64 %p) nounwind {
+entry:
+  fence seq_cst
+  br label %pre
+
+pre:
+  %p_tmp = srem i64 %p, 5
+  br i1 true, label %for.i, label %then
+
+for.i:
+  %indvar = phi i64 [ 0, %pre ], [ %indvar.next, %for.i ]
+  %indvar.p1 = phi i64 [ 0, %pre ], [ %indvar.p1.next, %for.i ]
+  %indvar.p2 = phi i64 [ 0, %pre ], [ %indvar.p2.next, %for.i ]
+  %sum = add i64 %indvar, %indvar.p1
+  %sum2 = sub i64 %sum, %indvar.p2
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %indvar.p1.next = add nsw i64 %indvar.p1, %p_tmp
+  %indvar.p2.next = add nsw i64 %indvar.p2, %p_tmp
+  %exitcond = icmp eq i64 %sum2, %N
+  br i1 %exitcond, label %then, label %for.i
+
+then:
+  br label %return
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.i => then
diff --git a/final/test/ScopDetect/keep_going_expansion.ll b/final/test/ScopDetect/keep_going_expansion.ll
new file mode 100644
index 0000000..9cdecfa
--- /dev/null
+++ b/final/test/ScopDetect/keep_going_expansion.ll
@@ -0,0 +1,46 @@
+; RUN: opt %loadPolly -basicaa -polly-detect-track-failures -polly-detect-keep-going -polly-detect -analyze < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @a(i32 %n, i32* noalias %A, i32* noalias %B) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body
+
+for.cond2.preheader:                              ; preds = %for.body
+  br label %for.body4
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %indvar = phi i64 [ 0, %entry.split ], [ %indvar.next, %for.body ]
+  %j.02 = trunc i64 %indvar to i32
+  %arrayidx = getelementptr i32* %B, i64 %indvar
+  store i32 %j.02, i32* %arrayidx, align 4
+  %indvar.next = add i64 %indvar, 1
+  %exitcond3 = icmp ne i64 %indvar.next, 32
+  br i1 %exitcond3, label %for.body, label %for.cond2.preheader
+
+for.body4:                                        ; preds = %for.cond2.preheader, %for.body4
+  %0 = phi i32 [ 0, %for.cond2.preheader ], [ %1, %for.body4 ]
+  %mul = mul i32 %n, %0
+  %idxprom5 = sext i32 %mul to i64
+  %arrayidx6 = getelementptr inbounds i32* %A, i64 %idxprom5
+  store i32 %0, i32* %arrayidx6, align 4
+  %1 = add nsw i32 %0, 1
+  %exitcond = icmp ne i32 %1, 32
+  br i1 %exitcond, label %for.body4, label %for.end9
+
+for.end9:                                         ; preds = %for.body4
+  %idxprom10 = sext i32 %n to i64
+  %arrayidx11 = getelementptr inbounds i32* %A, i64 %idxprom10
+  %2 = load i32* %arrayidx11, align 4
+  %idxprom12 = sext i32 %n to i64
+  %arrayidx13 = getelementptr inbounds i32* %B, i64 %idxprom12
+  %3 = load i32* %arrayidx13, align 4
+  %add = add nsw i32 %3, %2
+  ret i32 %add
+}
+
+; CHECK: Valid Region for Scop: for.body => for.cond2.preheader
diff --git a/final/test/ScopDetect/multidim_two_accesses_different_delinearization.ll b/final/test/ScopDetect/multidim_two_accesses_different_delinearization.ll
new file mode 100644
index 0000000..ebddf3f
--- /dev/null
+++ b/final/test/ScopDetect/multidim_two_accesses_different_delinearization.ll
@@ -0,0 +1,45 @@
+; RUN: opt %loadPolly -polly-detect -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Derived from the following code:
+;
+; void foo(long n, long m, double *A) {
+;   for (long i = 0; i < n; i++)
+;     for (long j = 0; j < m; j++)
+;       *(A + i * n + j) = 1.0;
+;       *(A + j * m + i) = 2.0;
+; }
+
+; CHECK-NOT: Valid Region for Scop
+
+define void @foo(i64 %n, i64 %m, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j ]
+  %tmp = mul nsw i64 %i, %m
+  %vlaarrayidx.sum = add i64 %j, %tmp
+  %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum
+  store double 1.0, double* %arrayidx
+  %tmp1 = mul nsw i64 %j, %n
+  %vlaarrayidx.sum1 = add i64 %i, %tmp1
+  %arrayidx1 = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum1
+  store double 1.0, double* %arrayidx1
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopDetect/nested_loop_single_exit.ll b/final/test/ScopDetect/nested_loop_single_exit.ll
new file mode 100644
index 0000000..5a616d7
--- /dev/null
+++ b/final/test/ScopDetect/nested_loop_single_exit.ll
@@ -0,0 +1,45 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -polly-codegen-isl -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i, j;
+;   if (true)
+;     for (j = 0; j < N; ++j)
+;       for (i = 0; i < N; ++i)
+;         A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br label %next
+
+next:
+  br i1 true, label %for.j, label %return
+
+for.j:
+  %j.015 = phi i64 [ %inc5, %for.inc8 ], [ 0, %next ]
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %for.j], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %for.inc8, label %for.i
+
+for.inc8:                                         ; preds = %for.body3
+  %inc5 = add nsw i64 %j.015, 1
+  %exitcond16 = icmp eq i64 %inc5, %N
+  br i1 %exitcond16, label %return, label %for.j
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: next => return
diff --git a/final/test/ScopDetect/parametric-multiply-in-scev.ll b/final/test/ScopDetect/parametric-multiply-in-scev.ll
new file mode 100644
index 0000000..3234822
--- /dev/null
+++ b/final/test/ScopDetect/parametric-multiply-in-scev.ll
@@ -0,0 +1,29 @@
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-detect-scops-in-functions-without-loops -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-detect-scops-in-functions-without-loops -polly-detect -analyze < %s | FileCheck %s
+
+
+;  foo(float *A, long n, long k) {
+;    if (true)
+;      A[n * k] = 0;
+;  }
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(float* %A, i64 %n, i64 %k) {
+entry:
+  br label %for.j
+
+for.j:
+  br i1 true, label %if.then, label %return
+
+if.then:
+  %mul = mul nsw i64 %n, %k
+  %arrayidx = getelementptr float* %A, i64 %mul
+  store float 0.000000e+00, float* %arrayidx
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.j => return
diff --git a/final/test/ScopDetect/remove_all_children.ll b/final/test/ScopDetect/remove_all_children.ll
new file mode 100644
index 0000000..2c01701
--- /dev/null
+++ b/final/test/ScopDetect/remove_all_children.ll
@@ -0,0 +1,46 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @remove_all_children(i32* %eclass) {
+entry:
+  br label %while.body
+
+while.cond.loopexit:                              ; preds = %while.body50, %while.end44
+  fence seq_cst
+  br label %while.cond.backedge
+
+while.body:                                       ; preds = %while.cond.backedge, %entry
+  br label %if.end33
+
+while.cond.backedge:                              ; preds = %while.end30, %while.cond.loopexit
+  br i1 false, label %while.body, label %while.end60
+
+if.end33:                                         ; preds = %while.end30
+  br i1 false, label %while.body36, label %while.end44
+
+while.body36:                                     ; preds = %while.body36, %while.body36.lr.ph
+  %indvar77 = phi i64 [ 0, %if.end33 ], [ %indvar.next78, %while.body36 ]
+  %arrayidx40 = getelementptr i32* %eclass, i64 0
+  %indvar.next78 = add i64 %indvar77, 1
+  br i1 false, label %while.body36, label %while.end44
+
+while.end44:                                      ; preds = %while.body36, %if.end33
+  br i1 false, label %while.body50, label %while.cond.loopexit
+
+while.body50:                                     ; preds = %while.body50, %while.body50.lr.ph
+  %indvar79 = phi i64 [ 0, %while.end44 ], [ %indvar.next80, %while.body50 ]
+  %arrayidx55 = getelementptr i32* %eclass, i64 0
+  store i32 0, i32* %arrayidx55, align 4
+  %indvar.next80 = add i64 %indvar79, 1
+  br i1 false, label %while.body50, label %while.cond.loopexit
+
+while.end60:                                      ; preds = %while.cond.backedge
+  ret void
+}
+; remove_all_children
+; CHECK-NOT: Valid Region
+; CHECK: Valid Region for Scop: if.end33 => while.cond.loopexit
+; CHECK-NOT: Valid Region
diff --git a/final/test/ScopDetect/report-scop-location.ll b/final/test/ScopDetect/report-scop-location.ll
new file mode 100644
index 0000000..5c5bfda
--- /dev/null
+++ b/final/test/ScopDetect/report-scop-location.ll
@@ -0,0 +1,82 @@
+; RUN: opt %loadPolly -polly-detect -polly-report -disable-output < %s  2>&1 | FileCheck %s
+target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @foo(float* %A) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body, !dbg !11
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %indvar = phi i64 [ 0, %entry.split ], [ %indvar.next, %for.body ]
+  %i.01 = trunc i64 %indvar to i32, !dbg !13
+  %arrayidx = getelementptr float* %A, i64 %indvar, !dbg !13
+  %conv = sitofp i32 %i.01 to float, !dbg !13
+  store float %conv, float* %arrayidx, align 4, !dbg !13
+  %indvar.next = add i64 %indvar, 1, !dbg !11
+  %exitcond = icmp ne i64 %indvar.next, 100, !dbg !11
+  br i1 %exitcond, label %for.body, label %for.end, !dbg !11
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !14
+}
+
+; CHECK: note: Polly detected an optimizable loop region (scop) in function 'foo'
+; CHECK: test.c:2: Start of scop
+; CHECK: test.c:3: End of scop
+
+; Function Attrs: nounwind uwtable
+define void @bar(float* %A) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body, !dbg !15
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %indvar = phi i64 [ 0, %entry.split ], [ %indvar.next, %for.body ]
+  %i.01 = trunc i64 %indvar to i32, !dbg !17
+  %arrayidx = getelementptr float* %A, i64 %indvar, !dbg !17
+  %conv = sitofp i32 %i.01 to float, !dbg !17
+  store float %conv, float* %arrayidx, align 4, !dbg !17
+  %indvar.next = add i64 %indvar, 1, !dbg !15
+  %exitcond = icmp ne i64 %indvar.next, 100, !dbg !15
+  br i1 %exitcond, label %for.body, label %for.end, !dbg !15
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !18
+}
+
+; CHECK: note: Polly detected an optimizable loop region (scop) in function 'bar'
+; CHECK: test.c:9: Start of scop
+; CHECK: test.c:13: End of scop
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8, !9}
+!llvm.ident = !{!10}
+
+!0 = !{!"0x11\0012\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/grosser/Projects/polly/git/tools/polly/test.c] [DW_LANG_C99]
+!1 = !{!"test.c", !"/home/grosser/Projects/polly/git/tools/polly"}
+!2 = !{i32 0}
+!3 = !{!4, !7}
+!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (float*)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [/home/grosser/Projects/polly/git/tools/polly/test.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{!"0x2e\00bar\00bar\00\006\000\001\000\006\00256\000\006", !1, !5, !6, null, void (float*)* @bar, null, null, !2} ; [ DW_TAG_subprogram ] [line 6] [def] [bar]
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 1, !"Debug Info Version", i32 2}
+!10 = !{!"clang version 3.5 "}
+!11 = !MDLocation(line: 2, scope: !12)
+!12 = !{!"0xb\002\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test.c]
+!13 = !MDLocation(line: 3, scope: !12)
+!14 = !MDLocation(line: 4, scope: !4)
+!15 = !MDLocation(line: 9, scope: !16)
+!16 = !{!"0xb\009\000\001", !1, !7} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test.c]
+!17 = !MDLocation(line: 13, scope: !16)
+!18 = !MDLocation(line: 14, scope: !7)
+
diff --git a/final/test/ScopDetect/run_time_alias_check.ll b/final/test/ScopDetect/run_time_alias_check.ll
new file mode 100644
index 0000000..15b1c9b
--- /dev/null
+++ b/final/test/ScopDetect/run_time_alias_check.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-detect -polly-code-generator=isl -analyze < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare float* @getNextBasePtr(float*) readnone nounwind
+
+define void @base_pointer_is_inst_inside_invariant_1(i64 %n, float* %A, float* %B) {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
+  br label %S1
+
+S1:
+; To get an instruction inside a region, we use a function without side
+; effects on which SCEV blocks, but for which it is still clear that the
+; return value remains invariant throughout the whole loop.
+  %ptr = call float* @getNextBasePtr(float* %A)
+  %conv = sitofp i64 %indvar.i to float
+  %arrayidx5 = getelementptr float* %ptr, i64 %indvar.i
+  store float %conv, float* %arrayidx5, align 4
+  store float 1.0, float* %B
+  br label %for.i.inc
+
+for.i.inc:
+  %indvar.i.next = add i64 %indvar.i, 1
+  %exitcond.i = icmp ne i64 %indvar.i.next, %n
+  br i1 %exitcond.i, label %for.i, label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-NOT: Valid Region for Scop
diff --git a/final/test/ScopDetect/sequential_loops.ll b/final/test/ScopDetect/sequential_loops.ll
new file mode 100644
index 0000000..b9526bf
--- /dev/null
+++ b/final/test/ScopDetect/sequential_loops.ll
@@ -0,0 +1,94 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Two sequential loops right after each other.
+;
+; void f(long A[], long N) {
+;   long i;
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+define void @f1(i64* %A, i64 %N) nounwind {
+; CHECK-LABEL: 'Polly - Detect static control parts (SCoPs)' for function 'f1'
+entry:
+  fence seq_cst
+  br label %for.i.1
+
+for.i.1:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.i.1 ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %for.i.2, label %for.i.1
+
+for.i.2:
+  %indvar.2 = phi i64 [ 0, %for.i.1 ], [ %indvar.next.2, %for.i.2 ]
+  %scevgep.2 = getelementptr i64* %A, i64 %indvar.2
+  store i64 %indvar.2, i64* %scevgep.2
+  %indvar.next.2 = add nsw i64 %indvar.2, 1
+  %exitcond.2 = icmp eq i64 %indvar.next.2, %N
+  br i1 %exitcond.2, label %return, label %for.i.2
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; C-H-E-C-K: Valid Region for Scop: for.i.1 => return
+; This one is currently not completely detected due to the PHI node in
+; for.i.2 causing a 'PHI node in exit BB' error for the first loop. This should
+; be fixed at some point. Such test cases do not really show up for us, as
+; the -loop-simplify pass always inserts a preheader as in the test case below.
+
+; Two sequential loops with a basic block in between.
+;
+;     void f(long A[], long N) {
+;       long i;
+;
+;       for (i = 0; i < N; ++i)
+;         A[i] = i;
+; preheader:
+;       ;
+;
+;       for (i = 0; i < N; ++i)
+;         A[i] = i;
+;     }
+
+define void @f2(i64* %A, i64 %N) nounwind {
+; CHECK-LABEL: 'Polly - Detect static control parts (SCoPs)' for function 'f2'
+entry:
+  fence seq_cst
+  br label %for.i.1
+
+for.i.1:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.i.1 ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %preheader, label %for.i.1
+
+preheader:
+  br label %for.i.2
+
+for.i.2:
+  %indvar.2 = phi i64 [ 0, %preheader ], [ %indvar.next.2, %for.i.2 ]
+  %scevgep.2 = getelementptr i64* %A, i64 %indvar.2
+  store i64 %indvar.2, i64* %scevgep.2
+  %indvar.next.2 = add nsw i64 %indvar.2, 1
+  %exitcond.2 = icmp eq i64 %indvar.next.2, %N
+  br i1 %exitcond.2, label %return, label %for.i.2
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.i.1 => return
diff --git a/final/test/ScopDetect/simple_loop.ll b/final/test/ScopDetect/simple_loop.ll
new file mode 100644
index 0000000..9670f4e
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop.ll
@@ -0,0 +1,31 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.i => return
diff --git a/final/test/ScopDetect/simple_loop_non_single_entry.ll b/final/test/ScopDetect/simple_loop_non_single_entry.ll
new file mode 100644
index 0000000..346bf1c
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop_non_single_entry.ll
@@ -0,0 +1,46 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;
+;  if (true)
+;    goto loop;
+;  else
+;    goto loop;
+;
+; loop:
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+; We will not detect this scop, as the loop is not in -loop-simplify form.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %then, label %else
+
+then:
+  br label %for.i
+
+else:
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %then ], [ 0, %else], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK-NOT: Valid Region for Scop
diff --git a/final/test/ScopDetect/simple_loop_non_single_exit.ll b/final/test/ScopDetect/simple_loop_non_single_exit.ll
new file mode 100644
index 0000000..270336c
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop_non_single_exit.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   if (true)
+;     for (i = 0; i < N; ++i)
+;       A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br label %next
+
+next:
+  br i1 true, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %next], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: next => return
diff --git a/final/test/ScopDetect/simple_loop_non_single_exit_2.ll b/final/test/ScopDetect/simple_loop_non_single_exit_2.ll
new file mode 100644
index 0000000..9201739
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop_non_single_exit_2.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   if (true)
+;     if (true)
+;       for (i = 0; i < N; ++i)
+;         A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %next, label %return
+
+next:
+  br i1 true, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %next], [ %indvar.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: next => return
diff --git a/final/test/ScopDetect/simple_loop_two_phi_nodes.ll b/final/test/ScopDetect/simple_loop_two_phi_nodes.ll
new file mode 100644
index 0000000..249deb3
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop_two_phi_nodes.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-detect  -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;   long i_non_canonical = 1;
+;   for (i = 0; i < N; ++i) {
+;     A[i] = i_non_canonical;
+;     i_non_canonical += 1;
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  %cmp = icmp sgt i64 %N, 0
+  br i1 %cmp, label %for.i, label %return
+
+for.i:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.i ]
+  %indvar_non_canonical = phi i64 [ 1, %entry ], [ %indvar_non_canonical.next, %for.i ]
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar_non_canonical, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %indvar_non_canonical.next = add nsw i64 %indvar_non_canonical, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.i => return
diff --git a/final/test/ScopDetect/simple_loop_with_param.ll b/final/test/ScopDetect/simple_loop_with_param.ll
new file mode 100644
index 0000000..aa5a9b3
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop_with_param.ll
@@ -0,0 +1,51 @@
+; RUN: opt %loadPolly -basicaa -polly-detect -analyze  < %s | FileCheck %s
+
+; void f(long A[], long N, long *init_ptr) {
+;   long i, j;
+;   long i_non_canonical;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     i_non_canonical = init;
+;     for (i = 0; i < N; ++i) {
+;       A[i] = i_non_canonical;
+;       i_non_canonical += 1;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+  %init = load i64* %init_ptr
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %indvar.j.non_canonical = phi i64 [ %init, %entry.next ], [ %indvar.j.non_canonical.next, %for.j ]
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %indvar.j.non_canonical, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %indvar.j.non_canonical.next = add nsw i64 %indvar.j.non_canonical, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.j => for.i.end
diff --git a/final/test/ScopDetect/simple_loop_with_param_2.ll b/final/test/ScopDetect/simple_loop_with_param_2.ll
new file mode 100644
index 0000000..15ec620
--- /dev/null
+++ b/final/test/ScopDetect/simple_loop_with_param_2.ll
@@ -0,0 +1,48 @@
+; RUN: opt %loadPolly -basicaa -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     for (i = 0; i < N; ++i) {
+;       A[i] = init + 2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+  %init = load i64* %init_ptr
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init_plus_two = add i64 %init, 2
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_plus_two, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
+
+; CHECK: Valid Region for Scop: for.i => return
diff --git a/final/test/ScopDetect/simple_non_single_entry.ll b/final/test/ScopDetect/simple_non_single_entry.ll
new file mode 100644
index 0000000..7465971
--- /dev/null
+++ b/final/test/ScopDetect/simple_non_single_entry.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-scops-in-regions-without-loops -polly-detect -analyze < %s | FileCheck %s
+
+; void f(long A[], long N) {
+;   long i;
+;
+;  if (true){
+;    i = 0;
+;    goto next;
+;  }else{
+;    i = 1;
+;    goto next;
+; }
+;
+; next:
+;  if (true)
+;    goto for.i;
+;  else
+;    goto for.i;
+;
+; for.i:
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %then1, label %else1
+
+then1:
+  br label %next
+
+else1:
+  br label %next
+
+next:
+  br i1 true, label %then, label %else
+
+then:
+  br label %for.i.head
+
+else:
+  br label %for.i.head
+
+for.i.head:
+  br label %for.i.head1
+
+for.i.head1:
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %for.i.head1], [ %indvar.next, %for.i ]
+  fence seq_cst
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Valid Region for Scop: next => for.i.head1
diff --git a/final/test/ScopDetect/skip_function_attribute.ll b/final/test/ScopDetect/skip_function_attribute.ll
new file mode 100644
index 0000000..9d181fe
--- /dev/null
+++ b/final/test/ScopDetect/skip_function_attribute.ll
@@ -0,0 +1,44 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+;
+; Verify polly skips this function
+;
+; CHECK-NOT: Valid Region for Scop
+;
+;    void polly_skip_me(int *A, int N) {
+;      for (int i = 0; i < N; i++)
+;        A[i] = A[i] * A[i] + A[i];
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @polly_skip_me(i32* %A, i32 %N) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  %cmp1 = icmp sgt i32 %N, 0
+  br i1 %cmp1, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry.split
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %i.02 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.02
+  %tmp = load i32* %arrayidx, align 4
+  %mul = mul nsw i32 %tmp, %tmp
+  %add = add nsw i32 %mul, %tmp
+  %arrayidx3 = getelementptr inbounds i32* %A, i32 %i.02
+  store i32 %add, i32* %arrayidx3, align 4
+  %inc = add nsw i32 %i.02, 1
+  %cmp = icmp slt i32 %inc, %N
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry.split
+  ret void
+}
+
+attributes #0 = { "polly.skip.fn" }
diff --git a/final/test/ScopDetectionDiagnostics/ReportAlias-01.ll b/final/test/ScopDetectionDiagnostics/ReportAlias-01.ll
new file mode 100644
index 0000000..ad65128
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportAlias-01.ll
@@ -0,0 +1,70 @@
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=false -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
+
+;void f(int A[], int B[]) {
+;  for (int i=0; i<42; i++)
+;    A[i] = B[i];
+;}
+
+; CHECK: remark: ReportAlias-01.c:2:8: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportAlias-01.c:3:5: Accesses to the arrays "B", "A" may access the same memory.
+; CHECK: remark: ReportAlias-01.c:3:5: Invalid Scop candidate ends here.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i32* %A, i32* %B) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  tail call void @llvm.dbg.value(metadata i32* %A, i64 0, metadata !13), !dbg !14
+  tail call void @llvm.dbg.value(metadata i32* %B, i64 0, metadata !15), !dbg !16
+  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !18), !dbg !20
+  br label %for.body, !dbg !21
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %indvar = phi i64 [ 0, %entry.split ], [ %indvar.next, %for.body ]
+  %arrayidx = getelementptr i32* %B, i64 %indvar, !dbg !22
+  %arrayidx2 = getelementptr i32* %A, i64 %indvar, !dbg !22
+  %0 = load i32* %arrayidx, align 4, !dbg !22
+  store i32 %0, i32* %arrayidx2, align 4, !dbg !22
+  tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !18), !dbg !20
+  %indvar.next = add i64 %indvar, 1, !dbg !21
+  %exitcond = icmp ne i64 %indvar.next, 42, !dbg !21
+  br i1 %exitcond, label %for.body, label %for.end, !dbg !21
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !23
+}
+
+declare void @llvm.dbg.declare(metadata, metadata)
+declare void @llvm.dbg.value(metadata, i64, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!12}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [test/ScopDetectionDiagnostic/ReportAlias-01.c] [DW_LANG_C99]
+!1 = !{!"ReportAlias-01.c", !"test/ScopDetectionDiagnostic/"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00f\00f\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32*, i32*)* @f, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [f]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [test/ScopDetectionDiagnostic/ReportAlias-01.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{null, !8, !8}
+!8 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
+!9 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 2}
+!12 = !{!"clang version 3.6.0 "}
+!13 = !{!"0x101\00A\0016777217\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [A] [line 1]
+!14 = !MDLocation(line: 1, column: 12, scope: !4)
+!15 = !{!"0x101\00B\0033554433\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [B] [line 1]
+!16 = !MDLocation(line: 1, column: 21, scope: !4)
+!17 = !{i32 0}
+!18 = !{!"0x100\00i\002\000", !19, !5, !9} ; [ DW_TAG_auto_variable ] [i] [line 2]
+!19 = !{!"0xb\002\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [test/ScopDetectionDiagnostic/ReportAlias-01.c]
+!20 = !MDLocation(line: 2, column: 12, scope: !19)
+!21 = !MDLocation(line: 2, column: 8, scope: !19)
+!22 = !MDLocation(line: 3, column: 5, scope: !19)
+!23 = !MDLocation(line: 4, column: 1, scope: !4)
diff --git a/final/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll b/final/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll
new file mode 100644
index 0000000..040e343
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll
@@ -0,0 +1,67 @@
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
+
+; 1 void differenttypes(char *A)
+; 2 {
+; 3   for (long i = 0; i < 1024; ++i)
+; 4     ((float*)A)[i] = ((double*)A)[i];
+; 5 }
+
+; CHECK: remark: /tmp/test.c:3:20: The following errors keep this region from being a Scop.
+; CHECK-NEXT: remark: /tmp/test.c:4:14: The array "A" is accessed through elements that differ in size
+; CHECK-NEXT: remark: /tmp/test.c:4:32: Invalid Scop candidate ends here.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @differenttypes(i8* nocapture %A)  {
+entry:
+  br label %for.body, !dbg !10
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.05 = phi i64 [ 0, %entry ], [ %tmp11, %for.body ]
+  %tmp = shl i64 %i.05, 3, !dbg !15
+  %uglygep = getelementptr i8* %A, i64 %tmp
+  %arrayidx = bitcast i8* %uglygep to double*, !dbg !16
+  %tmp9 = shl i64 %i.05, 2, !dbg !15
+  %uglygep7 = getelementptr i8* %A, i64 %tmp9
+  %arrayidx1 = bitcast i8* %uglygep7 to float*, !dbg !17
+  %tmp10 = load double* %arrayidx, align 8, !dbg !16, !tbaa !18
+  %conv = fptrunc double %tmp10 to float, !dbg !16
+  store float %conv, float* %arrayidx1, align 4, !dbg !17, !tbaa !22
+  %tmp11 = add nsw i64 %i.05, 1, !dbg !24
+  %exitcond = icmp eq i64 %tmp11, 1024, !dbg !10
+  br i1 %exitcond, label %for.end, label %for.body, !dbg !10
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !25
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+!llvm.ident = !{!9}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 \001\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c] [DW_LANG_C99]
+!1 = !{!"/tmp/test.c", !"/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00differenttypes\00differenttypes\00\001\000\001\000\006\00256\001\002", !1, !5, !6, null, void (i8*)* @differenttypes, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [scope 2] [differenttypes]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 2}
+!9 = !{!"clang version 3.6.0 "}
+!10 = !MDLocation(line: 3, column: 20, scope: !11)
+!11 = !{!"0xb\002", !1, !12} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
+!12 = !{!"0xb\001", !1, !13} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
+!13 = !{!"0xb\003\003\001", !1, !14} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
+!14 = !{!"0xb\003\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
+!15 = !MDLocation(line: 4, column: 32, scope: !13)
+!16 = !MDLocation(line: 4, column: 22, scope: !13)
+!17 = !MDLocation(line: 4, column: 14, scope: !13)
+!18 = !{!19, !19, i64 0}
+!19 = !{!"double", !20, i64 0}
+!20 = !{!"omnipotent char", !21, i64 0}
+!21 = !{!"Simple C/C++ TBAA"}
+!22 = !{!23, !23, i64 0}
+!23 = !{!"float", !20, i64 0}
+!24 = !MDLocation(line: 3, column: 30, scope: !13)
+!25 = !MDLocation(line: 5, column: 1, scope: !4)
diff --git a/final/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll b/final/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll
new file mode 100644
index 0000000..823c487
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll
@@ -0,0 +1,67 @@
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1 | FileCheck %s
+
+; #define N 1024
+; double invalidCall(double A[N]);
+;
+; void a(double A[N], int n) {
+;   for (int i=0; i<n; ++i) {
+;     A[i] = invalidCall(A);
+;   }
+; }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @a(double* %A, i32 %n) #0 {
+entry:
+  %cmp1 = icmp sgt i32 %n, 0, !dbg !10
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end, !dbg !10
+
+for.body.lr.ph:                                   ; preds = %entry
+  %0 = zext i32 %n to i64
+  br label %for.body, !dbg !10
+
+for.body:                                         ; preds = %for.body, %for.body.lr.ph
+  %indvar = phi i64 [ 0, %for.body.lr.ph ], [ %indvar.next, %for.body ]
+  %arrayidx = getelementptr double* %A, i64 %indvar, !dbg !12
+  %call = tail call double @invalidCall(double* %A) #2, !dbg !12
+  store double %call, double* %arrayidx, align 8, !dbg !12, !tbaa !14
+  %indvar.next = add i64 %indvar, 1, !dbg !10
+  %exitcond = icmp eq i64 %indvar.next, %0, !dbg !10
+  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !10
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void, !dbg !18
+}
+
+declare double @invalidCall(double*) #1
+
+; CHECK: remark: ReportFuncCall.c:4:8: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportFuncCall.c:5:12: This function call cannot be handled. Try to inline it.
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+!llvm.ident = !{!9}
+
+!0 = !{!"0x11\0012\00clang version 3.5.0 \001\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c] [DW_LANG_C99]
+!1 = !{!"ReportFuncCall.c", !"/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00a\00a\00\003\000\001\000\006\00256\001\003", !1, !5, !6, null, void (double*, i32)* @a, null, null, !2} ; [ DW_TAG_subprogram ] [line 3] [def] [a]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 2}
+!9 = !{!"clang version 3.5.0 "}
+!10 = !MDLocation(line: 4, column: 8, scope: !11)
+!11 = !{!"0xb\004\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!12 = !MDLocation(line: 5, column: 12, scope: !13)
+!13 = !{!"0xb\004\0027\000", !1, !11} ; [ DW_TAG_lexical_block ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!14 = !{!15, !15, i64 0}
+!15 = !{!"double", !16, i64 0}
+!16 = !{!"omnipotent char", !17, i64 0}
+!17 = !{!"Simple C/C++ TBAA"}
+!18 = !MDLocation(line: 7, column: 1, scope: !4)
diff --git a/final/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll b/final/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll
new file mode 100644
index 0000000..1d24864
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll
@@ -0,0 +1,89 @@
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
+
+; void f(int A[], int n) {
+;   for (int i = 0; i < A[n]; i++)
+;     A[i] = 0;
+; }
+
+; CHECK: remark: ReportLoopBound-01.c:2:8: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportLoopBound-01.c:2:8: Failed to derive an affine function from the loop bounds.
+; CHECK: remark: ReportLoopBound-01.c:3:5: Invalid Scop candidate ends here.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i32* %A, i32 %n) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  tail call void @llvm.dbg.value(metadata i32* %A, i64 0, metadata !13), !dbg !14
+  tail call void @llvm.dbg.value(metadata i32 %n, i64 0, metadata !15), !dbg !16
+  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !18), !dbg !20
+  %idxprom = sext i32 %n to i64, !dbg !21
+  %arrayidx = getelementptr inbounds i32* %A, i64 %idxprom, !dbg !21
+  %0 = load i32* %arrayidx, align 4, !dbg !21
+  %cmp3 = icmp sgt i32 %0, 0, !dbg !21
+  br i1 %cmp3, label %for.body.lr.ph, label %for.end, !dbg !21
+
+for.body.lr.ph:                                   ; preds = %entry.split
+  br label %for.body, !dbg !22
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.body
+  %indvar = phi i64 [ 0, %for.body.lr.ph ], [ %indvar.next, %for.body ]
+  %arrayidx2 = getelementptr i32* %A, i64 %indvar, !dbg !24
+  %1 = add i64 %indvar, 1, !dbg !24
+  %inc = trunc i64 %1 to i32, !dbg !21
+  store i32 0, i32* %arrayidx2, align 4, !dbg !24
+  tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !18), !dbg !20
+  %2 = load i32* %arrayidx, align 4, !dbg !21
+  %cmp = icmp slt i32 %inc, %2, !dbg !21
+  %indvar.next = add i64 %indvar, 1, !dbg !21
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge, !dbg !21
+
+for.cond.for.end_crit_edge:                       ; preds = %for.body
+  br label %for.end, !dbg !25
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry.split
+  ret void, !dbg !27
+}
+
+declare void @llvm.dbg.declare(metadata, metadata)
+
+declare void @llvm.dbg.value(metadata, i64, metadata)
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!12}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [test/ScopDetectionDiagnostic/ReportLoopBound-01.c] [DW_LANG_C99]
+!1 = !{!"ReportLoopBound-01.c", !"test/ScopDetectionDiagnostic/"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00f\00f\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32*, i32)* @f, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [f]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [test/ScopDetectionDiagnostic/ReportLoopBound-01.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{null, !8, !9}
+!8 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
+!9 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 2}
+!12 = !{!"clang version 3.6.0 "}
+!13 = !{!"0x101\00A\0016777217\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [A] [line 1]
+!14 = !MDLocation(line: 1, column: 12, scope: !4)
+!15 = !{!"0x101\00n\0033554433\000", !4, !5, !9} ; [ DW_TAG_arg_variable ] [n] [line 1]
+!16 = !MDLocation(line: 1, column: 21, scope: !4)
+!17 = !{i32 0}
+!18 = !{!"0x100\00i\002\000", !19, !5, !9} ; [ DW_TAG_auto_variable ] [i] [line 2]
+!19 = !{!"0xb\002\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [test/ScopDetectionDiagnostic/ReportLoopBound-01.c]
+!20 = !MDLocation(line: 2, column: 12, scope: !19)
+!21 = !MDLocation(line: 2, column: 8, scope: !19)
+!22 = !MDLocation(line: 2, column: 8, scope: !23)
+!23 = !{!"0xb\002\008\001", !1, !19} ; [ DW_TAG_lexical_block ] [test/ScopDetectionDiagnostic/ReportLoopBound-01.c]
+!24 = !MDLocation(line: 3, column: 5, scope: !19)
+!25 = !MDLocation(line: 2, column: 8, scope: !26)
+!26 = !{!"0xb\002\008\002", !1, !19} ; [ DW_TAG_lexical_block ] [test/ScopDetectionDiagnostic/ReportLoopBound-01.c]
+!27 = !MDLocation(line: 4, column: 1, scope: !4)
diff --git a/final/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll b/final/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll
new file mode 100644
index 0000000..4e6727e
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll
@@ -0,0 +1,154 @@
+; RUN: opt %loadPolly -basicaa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
+; RUN: opt %loadPolly -basicaa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -polly-detect-keep-going -analyze < %s 2>&1| FileCheck %s -check-prefix=ALL
+; RUN: opt %loadPolly -basicaa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -polly-delinearize -analyze < %s 2>&1| FileCheck %s -check-prefix=DELIN
+; RUN: opt %loadPolly -basicaa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -polly-delinearize -polly-detect-keep-going -analyze < %s 2>&1| FileCheck %s -check-prefix=DELIN-ALL
+; RUN: opt %loadPolly -basicaa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -polly-allow-nonaffine -analyze < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE
+; RUN: opt %loadPolly -basicaa -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -polly-delinearize -polly-allow-nonaffine -analyze < %s 2>&1| FileCheck %s -check-prefix=NONAFFINE
+
+;  1 void manyaccesses(float A[restrict], long n, float B[restrict][n])
+;  2 {
+;  3   for (long i = 0; i < 1024; ++i) {
+;  4     float a1 = A[2 * i * i];
+;  5     float a2 = A[2 * i * i + 1];
+;  6     float b1 = B[0][0];
+;  7     float b2 = B[i][i];
+;  8     float b3 = B[i * i][i];
+;  9     float b4 = B[i][0];
+; 10     float b5 = B[0][i];
+; 11     float b6 = B[0][i*i];
+; 12
+; 13     A[i * i] = a1 + a2 + b1 + b2 + b3 + b4 + b5 + b6;
+; 14   }
+; 15 }
+
+; CHECK: remark: /tmp/test.c:3:20: The following errors keep this region from being a Scop.
+; CHECK-NEXT: remark: /tmp/test.c:4:16: The array subscript of "A" is not affine
+; CHECK-NEXT: remark: /tmp/test.c:13:51: Invalid Scop candidate ends here.
+
+; ALL: remark: /tmp/test.c:3:20: The following errors keep this region from being a Scop.
+; ALL-NEXT: remark: /tmp/test.c:4:16: The array subscript of "A" is not affine
+; ALL-NEXT: remark: /tmp/test.c:5:16: The array subscript of "A" is not affine
+; -> B[0][0] is affine
+; ALL-NEXT: remark: /tmp/test.c:7:16: The array subscript of "B" is not affine
+; ALL-NEXT: remark: /tmp/test.c:8:16: The array subscript of "B" is not affine
+; ALL-NEXT: remark: /tmp/test.c:9:16: The array subscript of "B" is not affine
+; -> B[0][i] is affine
+; ALL-NEXT: remark: /tmp/test.c:11:16: The array subscript of "B" is not affine
+; ALL-NEXT: remark: /tmp/test.c:13:5: The array subscript of "A" is not affine
+; ALL-NEXT: remark: /tmp/test.c:13:51: Invalid Scop candidate ends here.
+
+; DELIN: remark: /tmp/test.c:3:20: The following errors keep this region from being a Scop.
+; DELIN-NEXT: remark: /tmp/test.c:4:16: The array subscript of "A" is not affine
+; DELIN-NEXT: remark: /tmp/test.c:13:51: Invalid Scop candidate ends here.
+
+; DELIN-ALL: remark: /tmp/test.c:3:20: The following errors keep this region from being a Scop.
+; DELIN-ALL-NEXT: remark: /tmp/test.c:4:16: The array subscript of "A" is not affine
+; DELIN-ALL-NEXT: remark: /tmp/test.c:5:16: The array subscript of "A" is not affine
+; DELIN-ALL-NEXT: remark: /tmp/test.c:13:5: The array subscript of "A" is not affine
+; -> B[0][0] is affine if delinearized
+; -> B[i][i] is affine if delinearized
+; DELIN-ALL-NEXT: remark: /tmp/test.c:8:16: The array subscript of "B" is not affine
+; -> B[i][0] is affine if delinearized
+; -> B[0][i] is affine if delinearized
+; DELIN-ALL-NEXT: remark: /tmp/test.c:11:16: The array subscript of "B" is not affine
+; DELIN-ALL-NEXT: remark: /tmp/test.c:13:51: Invalid Scop candidate ends here.
+
+; NONAFFINE-NOT: remark: The following errors keep this region from being a Scop.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @manyaccesses(float* noalias %A, i64 %n, float* noalias %B) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  %tmp = add i64 %n, 1, !dbg !10
+  br label %for.body, !dbg !10
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %tmp3 = phi i64 [ 0, %entry.split ], [ %tmp14, %for.body ], !dbg !15
+  %mul = mul i64 %tmp3, 2, !dbg !17
+  %tmp4 = mul i64 %tmp, %tmp3, !dbg !18
+  %arrayidx8 = getelementptr float* %B, i64 %tmp4, !dbg !19
+  %mul9 = mul i64 %n, %tmp3, !dbg !15
+  %arrayidx12 = getelementptr float* %B, i64 %mul9, !dbg !20
+  %arrayidx15 = getelementptr float* %B, i64 %tmp3, !dbg !21
+  %mul1 = mul nsw i64 %mul, %tmp3, !dbg !17
+  %arrayidx = getelementptr inbounds float* %A, i64 %mul1, !dbg !22
+  %tmp5 = load float* %arrayidx, align 4, !dbg !22
+  %mul3 = mul nsw i64 %mul, %tmp3, !dbg !27
+  %add1 = or i64 %mul3, 1, !dbg !27
+  %arrayidx4 = getelementptr inbounds float* %A, i64 %add1, !dbg !28
+  %tmp6 = load float* %arrayidx4, align 4, !dbg !28
+  %tmp7 = load float* %B, align 4, !dbg !29
+  %tmp8 = load float* %arrayidx8, align 4, !dbg !19
+  %tmp9 = mul i64 %mul9, %tmp3, !dbg !15
+  %arrayidx10.sum = add i64 %tmp9, %tmp3, !dbg !15
+  %arrayidx11 = getelementptr inbounds float* %B, i64 %arrayidx10.sum, !dbg !15
+  %tmp10 = load float* %arrayidx11, align 4, !dbg !15
+  %tmp11 = load float* %arrayidx12, align 4, !dbg !20
+  %tmp12 = load float* %arrayidx15, align 4, !dbg !21
+  %mul16 = mul nsw i64 %tmp3, %tmp3, !dbg !30
+  %arrayidx18 = getelementptr inbounds float* %B, i64 %mul16, !dbg !31
+  %tmp13 = load float* %arrayidx18, align 4, !dbg !31
+  %add19 = fadd float %tmp5, %tmp6, !dbg !32
+  %add20 = fadd float %add19, %tmp7, !dbg !33
+  %add21 = fadd float %add20, %tmp8, !dbg !34
+  %add22 = fadd float %add21, %tmp10, !dbg !35
+  %add23 = fadd float %add22, %tmp11, !dbg !36
+  %add24 = fadd float %add23, %tmp12, !dbg !37
+  %add25 = fadd float %add24, %tmp13, !dbg !38
+  %mul26 = mul nsw i64 %tmp3, %tmp3, !dbg !39
+  %arrayidx27 = getelementptr inbounds float* %A, i64 %mul26, !dbg !40
+  store float %add25, float* %arrayidx27, align 4, !dbg !40
+  %tmp14 = add nsw i64 %tmp3, 1, !dbg !41
+  %exitcond = icmp ne i64 %tmp14, 1024, !dbg !10
+  br i1 %exitcond, label %for.body, label %for.end, !dbg !10
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !42
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+!llvm.ident = !{!9}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 \001\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c] [DW_LANG_C99]
+!1 = !{!"/tmp/test.c", !"/home/grosser/Projects/polly/git/tools/polly/test"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00manyaccesses\00manyaccesses\00\001\000\001\000\006\00256\001\002", !1, !5, !6, null, void (float*, i64, float*)* @manyaccesses, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [scope 2] [manyaccesses]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 2}
+!9 = !{!"clang version 3.6.0 "}
+!10 = !MDLocation(line: 3, column: 20, scope: !11)
+!11 = !{!"0xb\002", !1, !12} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c]
+!12 = !{!"0xb\001", !1, !13} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c]
+!13 = !{!"0xb\003\003\001", !1, !14} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c]
+!14 = !{!"0xb\003\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c]
+!15 = !MDLocation(line: 8, column: 16, scope: !16)
+!16 = !{!"0xb\003\0035\002", !1, !13} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test//tmp/test.c]
+!17 = !MDLocation(line: 4, column: 26, scope: !16)
+!18 = !MDLocation(line: 4, column: 22, scope: !16)
+!19 = !MDLocation(line: 7, column: 16, scope: !16)
+!20 = !MDLocation(line: 9, column: 16, scope: !16)
+!21 = !MDLocation(line: 10, column: 16, scope: !16)
+!22 = !MDLocation(line: 4, column: 16, scope: !16)
+!27 = !MDLocation(line: 5, column: 26, scope: !16)
+!28 = !MDLocation(line: 5, column: 16, scope: !16)
+!29 = !MDLocation(line: 6, column: 16, scope: !16)
+!30 = !MDLocation(line: 11, column: 23, scope: !16) ; [ DW_TAG_lexical_block ] [/]
+!31 = !MDLocation(line: 11, column: 16, scope: !16) ; [ DW_TAG_lexical_block ] [/]
+!32 = !MDLocation(line: 13, column: 21, scope: !16)
+!33 = !MDLocation(line: 13, column: 26, scope: !16)
+!34 = !MDLocation(line: 13, column: 31, scope: !16)
+!35 = !MDLocation(line: 13, column: 36, scope: !16)
+!36 = !MDLocation(line: 13, column: 41, scope: !16)
+!37 = !MDLocation(line: 13, column: 46, scope: !16)
+!38 = !MDLocation(line: 13, column: 51, scope: !16)
+!39 = !MDLocation(line: 13, column: 11, scope: !16)
+!40 = !MDLocation(line: 13, column: 5, scope: !16)
+!41 = !MDLocation(line: 3, column: 30, scope: !13)
+!42 = !MDLocation(line: 15, column: 1, scope: !4)
diff --git a/final/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll b/final/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll
new file mode 100644
index 0000000..dab633b
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll
@@ -0,0 +1,73 @@
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
+
+; void f(int A[]) {
+;   for(int i=0; i<42; ++i)
+;     A[i*i] = 0;
+; }
+
+
+; CHECK: remark: ReportNonAffineAccess-01.c:2:7: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportNonAffineAccess-01.c:3:5: The array subscript of "A" is not affine
+; CHECK: remark: ReportNonAffineAccess-01.c:3:5: Invalid Scop candidate ends here.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i32* %A) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  tail call void @llvm.dbg.value(metadata i32* %A, i64 0, metadata !13), !dbg !14
+  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !16), !dbg !18
+  br label %for.body, !dbg !19
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %0 = phi i32 [ 0, %entry.split ], [ %1, %for.body ], !dbg !20
+  %mul = mul nsw i32 %0, %0, !dbg !20
+  %idxprom1 = zext i32 %mul to i64, !dbg !20
+  %arrayidx = getelementptr inbounds i32* %A, i64 %idxprom1, !dbg !20
+  store i32 0, i32* %arrayidx, align 4, !dbg !20
+  %1 = add nsw i32 %0, 1, !dbg !21
+  tail call void @llvm.dbg.value(metadata i32 %1, i64 0, metadata !16), !dbg !18
+  %exitcond = icmp ne i32 %1, 42, !dbg !19
+  br i1 %exitcond, label %for.body, label %for.end, !dbg !19
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !22
+}
+
+declare void @llvm.dbg.declare(metadata, metadata)
+
+declare void @llvm.dbg.value(metadata, i64, metadata)
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!12}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [test/ScopDetectionDiagnostic/ReportNonAffineAccess-01.c] [DW_LANG_C99]
+!1 = !{!"ReportNonAffineAccess-01.c", !"test/ScopDetectionDiagnostic/"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00f\00f\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32*)* @f, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [f]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [test/ScopDetectionDiagnostic/ReportNonAffineAccess-01.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{null, !8}
+!8 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
+!9 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 2}
+!12 = !{!"clang version 3.6.0 "}
+!13 = !{!"0x101\00A\0016777217\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [A] [line 1]
+!14 = !MDLocation(line: 1, column: 12, scope: !4)
+!15 = !{i32 0}
+!16 = !{!"0x100\00i\002\000", !17, !5, !9} ; [ DW_TAG_auto_variable ] [i] [line 2]
+!17 = !{!"0xb\002\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [test/ScopDetectionDiagnostic/ReportNonAffineAccess-01.c]
+!18 = !MDLocation(line: 2, column: 11, scope: !17)
+!19 = !MDLocation(line: 2, column: 7, scope: !17)
+!20 = !MDLocation(line: 3, column: 5, scope: !17)
+!21 = !MDLocation(line: 2, column: 22, scope: !17)
+!22 = !MDLocation(line: 4, column: 1, scope: !4)
diff --git a/final/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll b/final/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll
new file mode 100644
index 0000000..eb6cd8b
--- /dev/null
+++ b/final/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll
@@ -0,0 +1,99 @@
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
+
+; struct b {
+;   double **b;
+; };
+;
+; void a(struct b *A) {
+;   for (int i=0; i<32; i++)
+;     A->b[i] = 0;
+; }
+
+; CHECK: remark: ReportVariantBasePtr01.c:6:8: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportVariantBasePtr01.c:7:5: The base address of this array is not invariant inside the loop
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.b = type { double** }
+
+define void @a(%struct.b* nocapture readonly %A) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  tail call void @llvm.dbg.value(metadata %struct.b* %A, i64 0, metadata !16), !dbg !23
+  tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !17), !dbg !25
+  %b = getelementptr inbounds %struct.b* %A, i64 0, i32 0, !dbg !26
+  br label %for.body, !dbg !27
+
+for.body:                                         ; preds = %for.body, %entry.split
+  %indvar4 = phi i64 [ %indvar.next, %for.body ], [ 0, %entry.split ]
+  %0 = mul i64 %indvar4, 4, !dbg !26
+  %1 = add i64 %0, 3, !dbg !26
+  %2 = add i64 %0, 2, !dbg !26
+  %3 = add i64 %0, 1, !dbg !26
+  %4 = load double*** %b, align 8, !dbg !26, !tbaa !28
+  %arrayidx = getelementptr double** %4, i64 %0, !dbg !26
+  store double* null, double** %arrayidx, align 8, !dbg !26, !tbaa !33
+  %5 = load double*** %b, align 8, !dbg !26, !tbaa !28
+  %arrayidx.1 = getelementptr double** %5, i64 %3, !dbg !26
+  store double* null, double** %arrayidx.1, align 8, !dbg !26, !tbaa !33
+  %6 = load double*** %b, align 8, !dbg !26, !tbaa !28
+  %arrayidx.2 = getelementptr double** %6, i64 %2, !dbg !26
+  store double* null, double** %arrayidx.2, align 8, !dbg !26, !tbaa !33
+  %7 = load double*** %b, align 8, !dbg !26, !tbaa !28
+  %arrayidx.3 = getelementptr double** %7, i64 %1, !dbg !26
+  store double* null, double** %arrayidx.3, align 8, !dbg !26, !tbaa !33
+  %indvar.next = add i64 %indvar4, 1, !dbg !27
+  %exitcond = icmp eq i64 %indvar.next, 8, !dbg !27
+  br i1 %exitcond, label %for.end, label %for.body, !dbg !27
+
+for.end:                                          ; preds = %for.body
+  ret void, !dbg !34
+}
+
+declare void @llvm.dbg.value(metadata, i64, metadata) #1
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!20, !21}
+!llvm.ident = !{!22}
+
+!0 = !{!"0x11\0012\00clang version 3.5.0 \001\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [test/ScopDetectionDiagnostics/ReportVariantBasePtr01.c] [DW_LANG_C99]
+!1 = !{!"ReportVariantBasePtr01.c", !"test/ScopDetectionDiagnostics"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00a\00a\00\005\000\001\000\006\00256\001\005", !1, !5, !6, null, void (%struct.b*)* @a, null, null, !15} ; [ DW_TAG_subprogram ] [line 5] [def] [a]
+!5 = !{!"0x29", !1}          ; [ DW_TAG_file_type ] [test/ScopDetectionDiagnostics/ReportVariantBasePtr01.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{null, !8}
+!8 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from b]
+!9 = !{!"0x13\00b\001\0064\0064\000\000\000", !1, null, null, !10, null, null, null} ; [ DW_TAG_structure_type ] [b] [line 1, size 64, align 64, offset 0] [def] [from ]
+!10 = !{!11}
+!11 = !{!"0xd\00b\002\0064\0064\000\000", !1, !9, !12} ; [ DW_TAG_member ] [b] [line 2, size 64, align 64, offset 0] [from ]
+!12 = !{!"0xf\00\000\0064\0064\000\000", null, null, !13} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ]
+!13 = !{!"0xf\00\000\0064\0064\000\000", null, null, !14} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from double]
+!14 = !{!"0x24\00double\000\0064\0064\000\000\004", null, null} ; [ DW_TAG_base_type ] [double] [line 0, size 64, align 64, offset 0, enc DW_ATE_float]
+!15 = !{!16, !17}
+!16 = !{!"0x101\00A\0016777221\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [A] [line 5]
+!17 = !{!"0x100\00i\006\000", !18, !5, !19} ; [ DW_TAG_auto_variable ] [i] [line 6]
+!18 = !{!"0xb\006\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [test/ScopDetectionDiagnostics/ReportVariantBasePtr01.c]
+!19 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!20 = !{i32 2, !"Dwarf Version", i32 4}
+!21 = !{i32 2, !"Debug Info Version", i32 2}
+!22 = !{!"clang version 3.5.0 "}
+!23 = !MDLocation(line: 5, column: 18, scope: !4)
+!24 = !{i32 0}
+!25 = !MDLocation(line: 6, column: 12, scope: !18)
+!26 = !MDLocation(line: 7, column: 5, scope: !18)
+!27 = !MDLocation(line: 6, column: 8, scope: !18)
+!28 = !{!29, !30, i64 0}
+!29 = !{!"b", !30, i64 0}
+!30 = !{!"any pointer", !31, i64 0}
+!31 = !{!"omnipotent char", !32, i64 0}
+!32 = !{!"Simple C/C++ TBAA"}
+!33 = !{!30, !30, i64 0}
+!34 = !MDLocation(line: 8, column: 1, scope: !4)
diff --git a/final/test/ScopInfo/20111108-Parameter-not-detected.ll b/final/test/ScopInfo/20111108-Parameter-not-detected.ll
new file mode 100644
index 0000000..c4f62ea
--- /dev/null
+++ b/final/test/ScopInfo/20111108-Parameter-not-detected.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @foo()
+
+define i32 @main(i8* %A) nounwind uwtable {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc5, %entry
+  %indvar_out = phi i64 [ %indvar_out.next, %for.inc5 ], [ 0, %entry ]
+  call void @foo()
+  %tmp = add i64 %indvar_out, 2
+  %exitcond5 = icmp ne i64 %indvar_out, 1023
+  br i1 %exitcond5, label %for.body, label %for.end7
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body ]
+  %exitcond = icmp ne i64 %indvar, 1023
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %tmp1 = add i64 %tmp, %indvar
+  %cmp4 = icmp sgt i64 %tmp1, 1000
+  br i1 %cmp4, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body3
+  %arrayidx = getelementptr i8* %A, i64 %indvar
+  store i8 5, i8* %arrayidx
+  br label %if.end
+
+if.end:                                           ; preds = %if.end.single_exit
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc5
+
+for.inc5:                                         ; preds = %for.end
+  %indvar_out.next = add i64 %indvar_out, 1
+  br label %for.cond
+
+for.end7:                                         ; preds = %for.cond
+  ret i32 0
+}
+
+; CHECK: Context:
+; CHECK: p0: {0,+,1}<%for.cond>
+
+; CHECK: Domain :=
+; CHECK: [p_0] -> { Stmt_if_then[i0] : i0 >= 0 and i0 <= 1022 and i0 >= 999 - p_0 };
+
diff --git a/final/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll b/final/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll
new file mode 100644
index 0000000..64cff17
--- /dev/null
+++ b/final/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll
@@ -0,0 +1,32 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-a0:0-n32"
+target triple = "hexagon-unknown-linux-gnu"
+
+@array = external global [64 x i8], align 8
+
+define void @foo(i32* %A) nounwind {
+entry:
+  br label %if.then132
+
+if.then132:
+  %loaded = load i32* %A
+  %0 = icmp ugt i32 %loaded, 10
+  %umax = select i1 %0, i32 %loaded, i32 10
+  br label %do.body
+
+do.body:
+  %indvar = phi i32 [ %3, %do.body ], [ 0, %if.then132 ]
+  %1 = add i32 0, %umax
+  %2 = sub i32 %1, %indvar
+  %arrayidx = getelementptr [64 x i8]* @array, i32 0, i32 %2
+  store i8 1, i8* %arrayidx, align 1
+  %3 = add i32 %indvar, 1
+  %exitcond = icmp eq i32 %3, 20
+  br i1 %exitcond, label %for.end, label %do.body
+
+for.end:
+  ret void
+}
+
+;CHECK: p0: (10 umax %loaded)
diff --git a/final/test/ScopInfo/Alias-0.ll b/final/test/ScopInfo/Alias-0.ll
new file mode 100644
index 0000000..5faa9b6
--- /dev/null
+++ b/final/test/ScopInfo/Alias-0.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
+; REQUIRES: asserts
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+define void @f(i32* nocapture %a, i32* nocapture %b) nounwind {
+bb.nph:
+  %0 = tail call i32 (...)* @rnd() nounwind       ; <i32> [#uses=1]
+  %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
+  %iftmp.0.0 = select i1 %1, i32* %b, i32* %a     ; <i32*> [#uses=2]
+  br label %bb3
+
+bb3:                                              ; preds = %bb3, %bb.nph
+  %i.06 = phi i64 [ 0, %bb.nph ], [ %tmp, %bb3 ]  ; <i64> [#uses=3]
+  %scevgep = getelementptr i32* %a, i64 %i.06     ; <i32*> [#uses=1]
+  %scevgep7 = getelementptr i32* %iftmp.0.0, i64 %i.06 ; <i32*> [#uses=1]
+  %tmp = add i64 %i.06, 1                         ; <i64> [#uses=3]
+  %scevgep8 = getelementptr i32* %iftmp.0.0, i64 %tmp ; <i32*> [#uses=1]
+  %2 = load i32* %scevgep, align 4                ; <i32> [#uses=1]
+  %3 = load i32* %scevgep8, align 4               ; <i32> [#uses=1]
+  %4 = shl i32 %3, 1                              ; <i32> [#uses=1]
+  %5 = add nsw i32 %4, %2                         ; <i32> [#uses=1]
+  store i32 %5, i32* %scevgep7, align 4
+  %exitcond = icmp eq i64 %tmp, 64                ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb3
+
+return:                                           ; preds = %bb3
+  ret void
+}
+
+declare i32 @rnd(...)
+
+
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/final/test/ScopInfo/Alias-1.ll b/final/test/ScopInfo/Alias-1.ll
new file mode 100644
index 0000000..aeb0c15
--- /dev/null
+++ b/final/test/ScopInfo/Alias-1.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
+; REQUIRES: asserts
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+define void @f(i32* nocapture %a, i32* nocapture %b) nounwind {
+bb.nph:
+  %0 = tail call i32 (...)* @rnd() nounwind       ; <i32> [#uses=1]
+  %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
+  %sel.b = getelementptr inbounds i32* %b, i64 4 
+  %iftmp.0.0 = select i1 %1, i32* %sel.b, i32* %a     ; <i32*> [#uses=2]
+  br label %bb3
+
+bb3:                                              ; preds = %bb3, %bb.nph
+  %i.06 = phi i64 [ 0, %bb.nph ], [ %tmp, %bb3 ]  ; <i64> [#uses=3]
+  %scevgep = getelementptr i32* %a, i64 %i.06     ; <i32*> [#uses=1]
+  %scevgep7 = getelementptr i32* %iftmp.0.0, i64 %i.06 ; <i32*> [#uses=1]
+  %tmp = add i64 %i.06, 1                         ; <i64> [#uses=3]
+  %scevgep8 = getelementptr i32* %iftmp.0.0, i64 %tmp ; <i32*> [#uses=1]
+  %2 = load i32* %scevgep, align 4                ; <i32> [#uses=1]
+  %3 = load i32* %scevgep8, align 4               ; <i32> [#uses=1]
+  %4 = shl i32 %3, 1                              ; <i32> [#uses=1]
+  %5 = add nsw i32 %4, %2                         ; <i32> [#uses=1]
+  store i32 %5, i32* %scevgep7, align 4
+  %exitcond = icmp eq i64 %tmp, 64                ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb3
+
+return:                                           ; preds = %bb3
+  ret void
+}
+
+declare i32 @rnd(...)
+
+
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/final/test/ScopInfo/Alias-2.ll b/final/test/ScopInfo/Alias-2.ll
new file mode 100644
index 0000000..cd27ebf
--- /dev/null
+++ b/final/test/ScopInfo/Alias-2.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
+; REQUIRES: asserts
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+define void @f(i32** nocapture %ptrs, i64 %p0, i64 %p1, i64 %p2) nounwind {
+bb.nph:
+  %0 = getelementptr inbounds i32** %ptrs, i64 %p0 ; <i32**> [#uses=1]
+  %1 = load i32** %0, align 8                     ; <i32*> [#uses=1]
+  %2 = getelementptr inbounds i32** %ptrs, i64 %p1 ; <i32**> [#uses=1]
+  %3 = load i32** %2, align 8                     ; <i32*> [#uses=1]
+  %4 = getelementptr inbounds i32** %ptrs, i64 %p2 ; <i32**> [#uses=1]
+  %5 = load i32** %4, align 8                     ; <i32*> [#uses=1]
+  br label %bb
+
+bb:                                               ; preds = %bb, %bb.nph
+  %i.03 = phi i64 [ 0, %bb.nph ], [ %tmp, %bb ]   ; <i64> [#uses=3]
+  %scevgep = getelementptr i32* %3, i64 %i.03     ; <i32*> [#uses=1]
+  %scevgep4 = getelementptr i32* %5, i64 %i.03    ; <i32*> [#uses=1]
+  %tmp = add i64 %i.03, 1                         ; <i64> [#uses=3]
+  %scevgep5 = getelementptr i32* %1, i64 %tmp     ; <i32*> [#uses=1]
+  %6 = load i32* %scevgep, align 4                ; <i32> [#uses=1]
+  %7 = load i32* %scevgep4, align 4               ; <i32> [#uses=1]
+  %8 = add nsw i32 %7, %6                         ; <i32> [#uses=1]
+  store i32 %8, i32* %scevgep5, align 4
+  %exitcond = icmp eq i64 %tmp, 64                ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb
+
+return:                                           ; preds = %bb
+  ret void
+}
+
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/final/test/ScopInfo/Alias-3.ll b/final/test/ScopInfo/Alias-3.ll
new file mode 100644
index 0000000..440ea55
--- /dev/null
+++ b/final/test/ScopInfo/Alias-3.ll
@@ -0,0 +1,29 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
+; REQUIRES: asserts
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+define void @f(i32* nocapture %a, i32* nocapture %b) nounwind {
+bb.nph:
+  br label %bb
+
+bb:                                               ; preds = %bb, %bb.nph
+  %i.03 = phi i64 [ 0, %bb.nph ], [ %2, %bb ]     ; <i64> [#uses=3]
+  %scevgep = getelementptr i32* %b, i64 %i.03     ; <i32*> [#uses=1]
+  %scevgep4 = getelementptr i32* %a, i64 %i.03    ; <i32*> [#uses=1]
+  %0 = load i32* %scevgep, align 4                ; <i32> [#uses=1]
+  %1 = add nsw i32 %0, 2                          ; <i32> [#uses=1]
+  store i32 %1, i32* %scevgep4, align 4
+  %2 = add nsw i64 %i.03, 1                       ; <i64> [#uses=2]
+  %exitcond = icmp eq i64 %2, 128                 ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb
+
+return:                                           ; preds = %bb
+  ret void
+}
+
+
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/final/test/ScopInfo/Alias-4.ll b/final/test/ScopInfo/Alias-4.ll
new file mode 100644
index 0000000..85a6158
--- /dev/null
+++ b/final/test/ScopInfo/Alias-4.ll
@@ -0,0 +1,29 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
+; REQUIRES: asserts
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+define void @f(i32* noalias nocapture %a, i32* noalias nocapture %b) nounwind {
+bb.nph:
+  br label %bb
+
+bb:                                               ; preds = %bb, %bb.nph
+  %i.03 = phi i64 [ 0, %bb.nph ], [ %2, %bb ]     ; <i64> [#uses=3]
+  %scevgep = getelementptr i32* %b, i64 %i.03     ; <i32*> [#uses=1]
+  %scevgep4 = getelementptr i32* %a, i64 %i.03    ; <i32*> [#uses=1]
+  %0 = load i32* %scevgep, align 4                ; <i32> [#uses=1]
+  %1 = add nsw i32 %0, 2                          ; <i32> [#uses=1]
+  store i32 %1, i32* %scevgep4, align 4
+  %2 = add nsw i64 %i.03, 1                       ; <i64> [#uses=2]
+  %exitcond = icmp eq i64 %2, 128                 ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb
+
+return:                                           ; preds = %bb
+  ret void
+}
+
+
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/final/test/ScopInfo/aliasing_conditional_alias_groups_1.ll b/final/test/ScopInfo/aliasing_conditional_alias_groups_1.ll
new file mode 100644
index 0000000..0614af3
--- /dev/null
+++ b/final/test/ScopInfo/aliasing_conditional_alias_groups_1.ll
@@ -0,0 +1,56 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze < %s | FileCheck %s
+;
+; Check that there is no alias group because we either access A or B never both.
+;
+; CHECK: Alias Groups (0):
+;
+;    void jd(int b, int *A, int *B) {
+;      for (int i = 0; i < 1024; i++) {
+;        if (b)
+;          A[i] = A[i - 1];
+;        else
+;          B[i] = B[i - 1];
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32 %b, i32* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %for.body
+  %tmp = add nsw i64 %indvars.iv, -1
+  %arrayidx = getelementptr inbounds i32* %A, i64 %tmp
+  %tmp3 = load i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp3, i32* %arrayidx2, align 4
+  br label %if.end
+
+if.else:                                          ; preds = %for.body
+  %tmp4 = add nsw i64 %indvars.iv, -1
+  %arrayidx5 = getelementptr inbounds i32* %B, i64 %tmp4
+  %tmp5 = load i32* %arrayidx5, align 4
+  %arrayidx7 = getelementptr inbounds i32* %B, i64 %indvars.iv
+  store i32 %tmp5, i32* %arrayidx7, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/aliasing_conditional_alias_groups_2.ll b/final/test/ScopInfo/aliasing_conditional_alias_groups_2.ll
new file mode 100644
index 0000000..7b5660c
--- /dev/null
+++ b/final/test/ScopInfo/aliasing_conditional_alias_groups_2.ll
@@ -0,0 +1,55 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze < %s | FileCheck %s
+;
+; Check that we create two alias groups since the mininmal/maximal accesses
+; depend on %b.
+;
+; CHECK: Alias Groups (2):
+;
+;    void jd(int b, int *A, int *B) {
+;      for (int i = 0; i < 1024; i++) {
+;        if (b)
+;          A[i] = B[5];
+;        else
+;          B[i] = A[7];
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32 %b, i32* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %for.body
+  %arrayidx = getelementptr inbounds i32* %B, i64 5
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx1, align 4
+  br label %if.end
+
+if.else:                                          ; preds = %for.body
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 7
+  %tmp1 = load i32* %arrayidx2, align 4
+  %arrayidx4 = getelementptr inbounds i32* %B, i64 %indvars.iv
+  store i32 %tmp1, i32* %arrayidx4, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/aliasing_dead_access.ll b/final/test/ScopInfo/aliasing_dead_access.ll
new file mode 100644
index 0000000..b59e196
--- /dev/null
+++ b/final/test/ScopInfo/aliasing_dead_access.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -analyze -polly-scops < %s | FileCheck %s
+;
+; Check that RTC generation does not die when accesses are dead.
+;
+; CHECK: Alias Groups (0):
+;
+;    void jd(int *A, int *B) {
+;      for (int i = 0; i < 1024; i++)
+;        for (int j = i; j < 0; j++)
+;          A[i] = B[i];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc6 ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  %tmp = trunc i64 %indvars.iv to i32
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ %tmp, %for.body ], [ %inc, %for.inc ]
+  %cmp2 = icmp slt i32 %j.0, 0
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %B, i64 %indvars.iv
+  %tmp1 = load i32* %arrayidx, align 4
+  %arrayidx5 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp1, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll b/final/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll
new file mode 100644
index 0000000..fe36741
--- /dev/null
+++ b/final/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll
@@ -0,0 +1,91 @@
+; RUN: opt %loadPolly -polly-scops -polly-code-generator=isl -polly-rtc-max-parameters=8 -analyze < %s | FileCheck %s --check-prefix=MAX8
+; RUN: opt %loadPolly -polly-scops -polly-code-generator=isl -polly-rtc-max-parameters=7 -analyze < %s | FileCheck %s --check-prefix=MAX7
+;
+; Check that we allow this SCoP even though it has 10 parameters involved in posisbly aliasing accesses.
+; However, only 7 are involved in accesses through B, 8 through C and none in accesses through A.
+;
+; MAX8:       Printing analysis 'Polly - Create polyhedral description of Scops' for region: 'for.cond => for.end' in function 'jd':
+; MAX8-NEXT:  Function: jd
+
+; MAX7:       Printing analysis 'Polly - Create polyhedral description of Scops' for region: 'for.cond => for.end' in function 'jd':
+; MAX7-NEXT:  Invalid Scop!
+;
+;    void jd(int *A, int *B, int *C, long p1, long p2, long p3, long p4, long p5,
+;            long p6, long p7, long p8, long p9, long p10) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[p1] - B[p2] + B[-p3] - B[p4] + B[p5] - B[-p6] + B[p7] - C[p3] +
+;               C[-p4] - C[p5] + C[p6] - C[-p7] + C[p8] - C[p9] + C[-p10];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32* %C, i64 %p1, i64 %p2, i64 %p3, i64 %p4, i64 %p5, i64 %p6, i64 %p7, i64 %p8, i64 %p9, i64 %p10) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %B, i64 %p1
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 %p2
+  %tmp1 = load i32* %arrayidx1, align 4
+  %sub = sub nsw i32 %tmp, %tmp1
+  %sub2 = sub nsw i64 0, %p3
+  %arrayidx3 = getelementptr inbounds i32* %B, i64 %sub2
+  %tmp2 = load i32* %arrayidx3, align 4
+  %add = add nsw i32 %sub, %tmp2
+  %arrayidx4 = getelementptr inbounds i32* %B, i64 %p4
+  %tmp3 = load i32* %arrayidx4, align 4
+  %sub5 = sub nsw i32 %add, %tmp3
+  %arrayidx6 = getelementptr inbounds i32* %B, i64 %p5
+  %tmp4 = load i32* %arrayidx6, align 4
+  %add7 = add nsw i32 %sub5, %tmp4
+  %sub8 = sub nsw i64 0, %p6
+  %arrayidx9 = getelementptr inbounds i32* %B, i64 %sub8
+  %tmp5 = load i32* %arrayidx9, align 4
+  %sub10 = sub nsw i32 %add7, %tmp5
+  %arrayidx11 = getelementptr inbounds i32* %B, i64 %p7
+  %tmp6 = load i32* %arrayidx11, align 4
+  %add12 = add nsw i32 %sub10, %tmp6
+  %arrayidx13 = getelementptr inbounds i32* %C, i64 %p3
+  %tmp7 = load i32* %arrayidx13, align 4
+  %sub14 = sub nsw i32 %add12, %tmp7
+  %sub15 = sub nsw i64 0, %p4
+  %arrayidx16 = getelementptr inbounds i32* %C, i64 %sub15
+  %tmp8 = load i32* %arrayidx16, align 4
+  %add17 = add nsw i32 %sub14, %tmp8
+  %arrayidx18 = getelementptr inbounds i32* %C, i64 %p5
+  %tmp9 = load i32* %arrayidx18, align 4
+  %sub19 = sub nsw i32 %add17, %tmp9
+  %arrayidx20 = getelementptr inbounds i32* %C, i64 %p6
+  %tmp10 = load i32* %arrayidx20, align 4
+  %add21 = add nsw i32 %sub19, %tmp10
+  %sub22 = sub nsw i64 0, %p7
+  %arrayidx23 = getelementptr inbounds i32* %C, i64 %sub22
+  %tmp11 = load i32* %arrayidx23, align 4
+  %sub24 = sub nsw i32 %add21, %tmp11
+  %arrayidx25 = getelementptr inbounds i32* %C, i64 %p8
+  %tmp12 = load i32* %arrayidx25, align 4
+  %add26 = add nsw i32 %sub24, %tmp12
+  %arrayidx27 = getelementptr inbounds i32* %C, i64 %p9
+  %tmp13 = load i32* %arrayidx27, align 4
+  %sub28 = sub nsw i32 %add26, %tmp13
+  %sub29 = sub nsw i64 0, %p10
+  %arrayidx30 = getelementptr inbounds i32* %C, i64 %sub29
+  %tmp14 = load i32* %arrayidx30, align 4
+  %add31 = add nsw i32 %sub28, %tmp14
+  %arrayidx32 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %add31, i32* %arrayidx32, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/aliasing_multiple_alias_groups.ll b/final/test/ScopInfo/aliasing_multiple_alias_groups.ll
new file mode 100644
index 0000000..b656de5
--- /dev/null
+++ b/final/test/ScopInfo/aliasing_multiple_alias_groups.ll
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze          < %s | FileCheck %s --check-prefix=NOAA
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze -tbaa    < %s | FileCheck %s --check-prefix=TBAA
+;
+;    void jd(int *Int0, int *Int1, float *Float0, float *Float1) {
+;      for (int i = 0; i < 1024; i++) {
+;        Int0[i] = Int1[i];
+;        Float0[i] = Float1[i];
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* nocapture %Int0, i32* nocapture readonly %Int1, float* nocapture %Float0, float* nocapture readonly %Float1) {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %arrayidx = getelementptr inbounds i32* %Int1, i64 %indvars.iv
+  %tmp = load i32* %arrayidx, align 4, !tbaa !0
+  %arrayidx2 = getelementptr inbounds i32* %Int0, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4, !tbaa !0
+  %arrayidx4 = getelementptr inbounds float* %Float1, i64 %indvars.iv
+  %tmp1 = load float* %arrayidx4, align 4, !tbaa !4
+  %arrayidx6 = getelementptr inbounds float* %Float0, i64 %indvars.iv
+  store float %tmp1, float* %arrayidx6, align 4, !tbaa !4
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 1024
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+!0 = !{!1, !1, i64 0}
+!1 = !{!"int", !2, i64 0}
+!2 = !{!"omnipotent char", !3, i64 0}
+!3 = !{!"Simple C/C++ TBAA"}
+!4 = !{!5, !5, i64 0}
+!5 = !{!"float", !2, i64 0}
+
+; NOAA: Alias Groups (2):
+; NOAA-NEXT: {{\[\[}}
+; NOAA-DAG:      <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
+; NOAA-DAG:      <{ MemRef_{{(Int|Float)}}1[(0)] }, { MemRef_{{(Int|Float)}}1[(1024)] }>
+; NOAA-DAG:      <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
+; NOAA:      {{\]\]}}
+; NOAA-NEXT: {{\[\[}}
+; NOAA-DAG:      <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
+; NOAA-DAG:      <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
+; NOAA-DAG:      <{ MemRef_{{(Int|Float)}}1[(0)] }, { MemRef_{{(Int|Float)}}1[(1024)] }>
+; NOAA:      {{\]\]}}
+
+
+; TBAA: Alias Groups (2):
+; TBAA-NEXT: {{\[\[}}
+; TBAA-DAG:      <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
+; TBAA-DAG:      <{ MemRef_Int1[(0)] }, { MemRef_Int1[(1024)] }>
+; TBAA:      {{\]\]}}
+; TBAA-NEXT: {{\[\[}}
+; TBAA-DAG:      <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
+; TBAA-DAG:      <{ MemRef_Float1[(0)] }, { MemRef_Float1[(1024)] }>
+; TBBA:      {{\]\]}}
diff --git a/final/test/ScopInfo/assume_gep_bounds.ll b/final/test/ScopInfo/assume_gep_bounds.ll
new file mode 100644
index 0000000..8422dad
--- /dev/null
+++ b/final/test/ScopInfo/assume_gep_bounds.ll
@@ -0,0 +1,76 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+;    void foo(float A[][20][30], long n, long m, long p) {
+;      for (long i = 0; i < n; i++)
+;        for (long j = 0; j < m; j++)
+;          for (long k = 0; k < p; k++)
+;            A[i][j][k] = i + j + k;
+;    }
+
+; For the above code we want to assume that all memory accesses are within the
+; bounds of the array A. In C (and LLVM-IR) this is not required, such that out
+; of bounds accesses are valid. However, as such accesses are uncommon, cause
+; complicated dependence pattern and as a result make dependence analysis more
+; costly and may prevent or hinder useful program transformations, we assume
+; absence of out-of-bound accesses. To do so we derive the set of parameter
+; values for which our assumption holds.
+
+; CHECK: Assumed Context
+; CHECK-NEXT: [n, m, p] -> {  : p <= 30 and m <= 20 }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo([20 x [30 x float]]* %A, i64 %n, i64 %m, i64 %p) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc13, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %inc14, %for.inc13 ]
+  %cmp = icmp slt i64 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end15
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc10, %for.body
+  %j.0 = phi i64 [ 0, %for.body ], [ %inc11, %for.inc10 ]
+  %cmp2 = icmp slt i64 %j.0, %m
+  br i1 %cmp2, label %for.body3, label %for.end12
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.cond4
+
+for.cond4:                                        ; preds = %for.inc, %for.body3
+  %k.0 = phi i64 [ 0, %for.body3 ], [ %inc, %for.inc ]
+  %cmp5 = icmp slt i64 %k.0, %p
+  br i1 %cmp5, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4
+  %add = add nsw i64 %i.0, %j.0
+  %add7 = add nsw i64 %add, %k.0
+  %conv = sitofp i64 %add7 to float
+  %arrayidx9 = getelementptr inbounds [20 x [30 x float]]* %A, i64 %i.0, i64 %j.0, i64 %k.0
+  store float %conv, float* %arrayidx9, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body6
+  %inc = add nsw i64 %k.0, 1
+  br label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end
+  %inc11 = add nsw i64 %j.0, 1
+  br label %for.cond1
+
+for.end12:                                        ; preds = %for.cond1
+  br label %for.inc13
+
+for.inc13:                                        ; preds = %for.end12
+  %inc14 = add nsw i64 %i.0, 1
+  br label %for.cond
+
+for.end15:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/assume_gep_bounds_2.ll b/final/test/ScopInfo/assume_gep_bounds_2.ll
new file mode 100644
index 0000000..3c27e53
--- /dev/null
+++ b/final/test/ScopInfo/assume_gep_bounds_2.ll
@@ -0,0 +1,94 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+;
+;    void foo(float A[restrict][20], float B[restrict][20], long n, long m,
+;             long p) {
+;      for (long i = 0; i < n; i++)
+;        for (long j = 0; j < m; j++)
+;          A[i][j] = i + j;
+;      for (long i = 0; i < m; i++)
+;        for (long j = 0; j < p; j++)
+;          B[i][j] = i + j;
+;    }
+
+; This code is within bounds either if m and p are smaller than the array sizes,
+; but also if only p is smaller than the size of the second B dimension and n
+; is such that the first loop is never executed and consequently A is never
+; accessed. In this case the value of m does not matter.
+
+; CHECK: Assumed Context:
+; CHECK-NEXT: [n, m, p] -> { : (n >= 1 and m <= 20 and p <= 20) or (n <= 0 and p <= 20) }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo([20 x float]* noalias %A, [20 x float]* noalias %B, i64 %n, i64 %m, i64 %p) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc5, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %inc6, %for.inc5 ]
+  %cmp = icmp slt i64 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end7
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i64 [ 0, %for.body ], [ %inc, %for.inc ]
+  %cmp2 = icmp slt i64 %j.0, %m
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %add = add nsw i64 %i.0, %j.0
+  %conv = sitofp i64 %add to float
+  %arrayidx4 = getelementptr inbounds [20 x float]* %A, i64 %i.0, i64 %j.0
+  store float %conv, float* %arrayidx4, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i64 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc5
+
+for.inc5:                                         ; preds = %for.end
+  %inc6 = add nsw i64 %i.0, 1
+  br label %for.cond
+
+for.end7:                                         ; preds = %for.cond
+  br label %for.cond9
+
+for.cond9:                                        ; preds = %for.inc25, %for.end7
+  %i8.0 = phi i64 [ 0, %for.end7 ], [ %inc26, %for.inc25 ]
+  %cmp10 = icmp slt i64 %i8.0, %m
+  br i1 %cmp10, label %for.body12, label %for.end27
+
+for.body12:                                       ; preds = %for.cond9
+  br label %for.cond14
+
+for.cond14:                                       ; preds = %for.inc22, %for.body12
+  %j13.0 = phi i64 [ 0, %for.body12 ], [ %inc23, %for.inc22 ]
+  %cmp15 = icmp slt i64 %j13.0, %p
+  br i1 %cmp15, label %for.body17, label %for.end24
+
+for.body17:                                       ; preds = %for.cond14
+  %add18 = add nsw i64 %i8.0, %j13.0
+  %conv19 = sitofp i64 %add18 to float
+  %arrayidx21 = getelementptr inbounds [20 x float]* %B, i64 %i8.0, i64 %j13.0
+  store float %conv19, float* %arrayidx21, align 4
+  br label %for.inc22
+
+for.inc22:                                        ; preds = %for.body17
+  %inc23 = add nsw i64 %j13.0, 1
+  br label %for.cond14
+
+for.end24:                                        ; preds = %for.cond14
+  br label %for.inc25
+
+for.inc25:                                        ; preds = %for.end24
+  %inc26 = add nsw i64 %i8.0, 1
+  br label %for.cond9
+
+for.end27:                                        ; preds = %for.cond9
+  ret void
+}
diff --git a/final/test/ScopInfo/bug_2010_10_22.ll b/final/test/ScopInfo/bug_2010_10_22.ll
new file mode 100644
index 0000000..54b0a5f
--- /dev/null
+++ b/final/test/ScopInfo/bug_2010_10_22.ll
@@ -0,0 +1,46 @@
+; RUN: opt %loadPolly -polly-analyze-ir < %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define fastcc void @_Z8wavModelR5Mixer() {
+entry:
+  br label %bb230
+
+bb230:                                            ; preds = %bb233, %bb.nph433
+  %indvar600 = phi i64 [ 0, %entry ], [ %tmp610, %bb233 ]
+  %tmp217 = add i64 %indvar600, -1
+  %tmp204 = trunc i64 %tmp217 to i32
+  %tmp205 = zext i32 %tmp204 to i64
+  %tmp206 = add i64 %tmp205, 1
+  %tmp610 = add i64 %indvar600, 1
+  br i1 false, label %bb231.preheader, label %bb233
+
+bb231.preheader:                                  ; preds = %bb230
+  br label %bb231
+
+bb231:                                            ; preds = %bb231, %bb231.preheader
+  %indvar589 = phi i64 [ %tmp611, %bb231 ], [ 0, %bb231.preheader ]
+  %tmp611 = add i64 %indvar589, 1
+  %exitcond207 = icmp eq i64 %tmp611, %tmp206
+  br i1 %exitcond207, label %bb233.loopexit, label %bb231
+
+bb233.loopexit:                                   ; preds = %bb231
+  br label %bb233
+
+bb233:                                            ; preds = %bb233.loopexit, %bb230
+  %exitcond213 = icmp eq i64 %tmp610, 0
+  br i1 %exitcond213, label %bb241, label %bb230
+
+bb241:                                            ; preds = %bb233, %bb228
+  br label %bb244.preheader
+
+bb244.preheader:                                  ; preds = %bb241, %bb176
+  br i1 undef, label %bb245, label %bb.nph416
+
+bb.nph416:                                        ; preds = %bb244.preheader
+  unreachable
+
+bb245:                                            ; preds = %bb244.preheader
+  ret void
+}
diff --git a/final/test/ScopInfo/bug_2011_1_5.ll b/final/test/ScopInfo/bug_2011_1_5.ll
new file mode 100644
index 0000000..9253d5a
--- /dev/null
+++ b/final/test/ScopInfo/bug_2011_1_5.ll
@@ -0,0 +1,60 @@
+; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s
+
+; Bug description: Alias Analysis thinks IntToPtrInst aliases with alloca instructions created by IndependentBlocks Pass.
+;                  This will trigger the assertion when we are verifying the SCoP after IndependentBlocks.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.precisionType = type { i16, i16, i16, i8, [1 x i16] }
+
+define void @main() nounwind {
+entry:
+ br label %bb1.i198.i
+
+bb1.i198.i:                                       ; preds = %bb.i197.i, %psetq.exit196.i
+  %tmp51.i = inttoptr i64 0 to %struct.precisionType*
+  br i1 undef, label %bb1.i210.i, label %bb.i209.i
+
+bb.i209.i:                                        ; preds = %bb1.i198.i
+  br label %bb1.i210.i
+
+bb1.i210.i:                                       ; preds = %bb.i209.i, %bb1.i198.i
+  %0 = icmp eq i64 0, 0
+  br i1 %0, label %bb1.i216.i, label %bb.i215.i
+
+bb.i215.i:                                        ; preds = %bb1.i210.i
+  %1 = getelementptr inbounds %struct.precisionType* %tmp51.i, i64 0, i32 0
+  store i16 undef, i16* %1, align 2
+  br label %bb1.i216.i
+
+bb1.i216.i:                                       ; preds = %bb.i215.i, %bb1.i210.i
+  br i1 undef, label %psetq.exit220.i, label %bb2.i217.i
+
+bb2.i217.i:                                       ; preds = %bb1.i216.i
+  br i1 undef, label %bb3.i218.i, label %psetq.exit220.i
+
+bb3.i218.i:                                       ; preds = %bb2.i217.i
+  br label %psetq.exit220.i
+
+psetq.exit220.i:                                  ; preds = %bb3.i218.i, %bb2.i217.i, %bb1.i216.i
+  br i1 undef, label %bb14.i76, label %bb15.i77
+
+bb14.i76:                                         ; preds = %psetq.exit220.i
+  unreachable
+
+bb15.i77:                                         ; preds = %psetq.exit220.i
+  br i1 %0, label %psetq.exit238.i, label %bb2.i235.i
+
+bb2.i235.i:                                       ; preds = %bb15.i77
+  br i1 undef, label %bb3.i236.i, label %psetq.exit238.i
+
+bb3.i236.i:                                       ; preds = %bb2.i235.i
+  unreachable
+
+psetq.exit238.i:                                  ; preds = %bb2.i235.i, %bb15.i77
+  unreachable
+
+bb56.i.loopexit:                                  ; preds = %psetq.exit172.i
+  unreachable
+}
diff --git a/final/test/ScopInfo/bug_scev_not_fully_eval.ll b/final/test/ScopInfo/bug_scev_not_fully_eval.ll
new file mode 100644
index 0000000..fa8098c
--- /dev/null
+++ b/final/test/ScopInfo/bug_scev_not_fully_eval.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-detect -analyze  < %s | not FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@edge.8265 = external global [72 x i32], align 32 ; <[72 x i32]*> [#uses=1]
+
+define void @compact_unitcell_edges() nounwind {
+bb.nph19:
+  br label %bb4
+
+bb4:                                              ; preds = %bb4, %bb.nph19
+  %e.118 = phi i32 [ 0, %bb.nph19 ], [ %tmp23, %bb4 ] ; <i32> [#uses=1]
+  %i.017 = phi i32 [ 0, %bb.nph19 ], [ %0, %bb4 ] ; <i32> [#uses=1]
+  %tmp23 = add i32 %e.118, 8                      ; <i32> [#uses=2]
+  %0 = add nsw i32 %i.017, 1                      ; <i32> [#uses=2]
+  %exitcond42 = icmp eq i32 %0, 6                 ; <i1> [#uses=1]
+  br i1 %exitcond42, label %bb.nph, label %bb4
+
+bb.nph:                                           ; preds = %bb4
+  %tmp = sext i32 %tmp23 to i64                   ; <i64> [#uses=1]
+  br label %bb7
+
+bb7:                                              ; preds = %bb7, %bb.nph
+  %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb7 ] ; <i64> [#uses=2]
+  %tmp21 = add i64 %tmp, %indvar                  ; <i64> [#uses=1]
+  %scevgep = getelementptr [72 x i32]* @edge.8265, i64 0, i64 %tmp21 ; <i32*> [#uses=1]
+  store i32 undef, i32* %scevgep, align 4
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=1]
+  br i1 undef, label %bb10, label %bb7
+
+bb10:                                             ; preds = %bb7
+  ret void
+}
+
+; CHECK: SCOP:
diff --git a/final/test/ScopInfo/cond_constant_in_loop.ll b/final/test/ScopInfo/cond_constant_in_loop.ll
new file mode 100644
index 0000000..a71ec46
--- /dev/null
+++ b/final/test/ScopInfo/cond_constant_in_loop.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+;void f(long a[], long N, long M) {
+;  long i, j, k;
+;  for (j = 0; j < M; ++j)
+;    if (true)
+;      a[j] = j;
+;    else {
+;      a[j] = M;
+;      a[j - N] = 0;
+;    }
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* nocapture %a, i64 %N, i64 %M) nounwind {
+entry:
+  %0 = icmp sgt i64 %M, 0                         ; <i1> [#uses=1]
+  br i1 %0, label %bb, label %return
+
+bb:                                               ; preds = %bb3, %entry
+  %1 = phi i64 [ 0, %entry ], [ %2, %bb3 ]        ; <i64> [#uses=5]
+  %scevgep = getelementptr i64* %a, i64 %1        ; <i64*> [#uses=2]
+  br i1 true, label %bb1, label %bb2
+
+bb1:                                              ; preds = %bb
+  store i64 %1, i64* %scevgep, align 8
+  br label %bb3
+
+bb2:                                              ; preds = %bb
+  %tmp7 = sub i64 %1, %N                          ; <i64> [#uses=1]
+  %scevgep8 = getelementptr i64* %a, i64 %tmp7    ; <i64*> [#uses=1]
+  store i64 %M, i64* %scevgep, align 8
+  store i64 0, i64* %scevgep8, align 8
+  br label %bb3
+
+bb3:                                              ; preds = %bb2, %bb1
+  %2 = add nsw i64 %1, 1                          ; <i64> [#uses=2]
+  %exitcond = icmp eq i64 %2, %M                  ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb
+
+return:                                           ; preds = %bb3, %entry
+  ret void
+}
+
+; CHECK: Stmt_bb1
+; CHECK:   Domain :=
+; CHECK:     [M, N] -> { Stmt_bb1[i0] : i0 >= 0 and i0 <= -1 + M };
+; CHECK: Stmt_bb2
+; CHECK:   Domain :=
+; CHECK:     [M, N] -> { Stmt_bb2[i0] : 1 = 0 };
+
diff --git a/final/test/ScopInfo/cond_in_loop.ll b/final/test/ScopInfo/cond_in_loop.ll
new file mode 100644
index 0000000..55ab6dc
--- /dev/null
+++ b/final/test/ScopInfo/cond_in_loop.ll
@@ -0,0 +1,48 @@
+; RUN: opt %loadPolly -polly-analyze-ir  -analyze < %s | not FileCheck %s
+
+;void f(long a[], long N, long M) {
+;  long i, j, k;
+;  for (j = 0; j < M; ++j)
+;    if (N > j)
+;      a[j] = j;
+;    else {
+;      a[j] = M;
+;      a[j - N] = 0;
+;    }
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* nocapture %a, i64 %N, i64 %M) nounwind {
+entry:
+  %0 = icmp sgt i64 %M, 0                         ; <i1> [#uses=1]
+  br i1 %0, label %bb, label %return
+
+bb:                                               ; preds = %bb3, %entry
+  %1 = phi i64 [ 0, %entry ], [ %3, %bb3 ]        ; <i64> [#uses=5]
+  %scevgep = getelementptr i64* %a, i64 %1        ; <i64*> [#uses=2]
+  %2 = icmp slt i64 %1, %N                        ; <i1> [#uses=1]
+  br i1 %2, label %bb1, label %bb2
+
+bb1:                                              ; preds = %bb
+  store i64 %1, i64* %scevgep, align 8
+  br label %bb3
+
+bb2:                                              ; preds = %bb
+  %tmp7 = sub i64 %1, %N                          ; <i64> [#uses=1]
+  %scevgep8 = getelementptr i64* %a, i64 %tmp7    ; <i64*> [#uses=1]
+  store i64 %M, i64* %scevgep, align 8
+  store i64 0, i64* %scevgep8, align 8
+  br label %bb3
+
+bb3:                                              ; preds = %bb2, %bb1
+  %3 = add nsw i64 %1, 1                          ; <i64> [#uses=2]
+  %exitcond = icmp eq i64 %3, %M                  ; <i1> [#uses=1]
+  br i1 %exitcond, label %return, label %bb
+
+return:                                           ; preds = %bb3, %entry
+  ret void
+}
+
+; CHECK: Scop!
diff --git a/final/test/ScopInfo/constant_start_integer.ll b/final/test/ScopInfo/constant_start_integer.ll
new file mode 100644
index 0000000..f28b9d8
--- /dev/null
+++ b/final/test/ScopInfo/constant_start_integer.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(float *input) {
+;   for (int j = 0; j < 8; j++) {
+;     //SCoP begin
+;     for (int i = 0; i < 63; i++) {
+;       float x = input[j * 64 + i + 1];
+;       input[j * 64 + i + 0] = x * x;
+;     }
+;   }
+; }
+
+; CHECK  p0: {0,+,256}<%for.cond1.preheader>
+; CHECK-NOT: p1
+
+; CHECK: ReadAccess
+; CHECK:   [p_0] -> { Stmt_for_body3[i0] -> MemRef_input[o0] : 4o0 = 4 + p_0 + 4i0 };
+; CHECK: MustWriteAccess
+; CHECK:   [p_0] -> { Stmt_for_body3[i0] -> MemRef_input[o0] : 4o0 = p_0 + 4i0 };
+
+define void @foo(float* nocapture %input) {
+entry:
+  br label %for.cond1.preheader
+
+for.cond1.preheader:                              ; preds = %for.inc10, %entry
+  %j.021 = phi i64 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %mul = shl nsw i64 %j.021, 6
+  br label %for.body3
+
+for.body3:                                        ; preds = %for.body3, %for.cond1.preheader
+  %i.020 = phi i64 [ 0, %for.cond1.preheader ], [ %inc, %for.body3 ]
+  %add = add nsw i64 %i.020, %mul
+  %add4 = add nsw i64 %add, 1
+  %arrayidx = getelementptr inbounds float* %input, i64 %add4
+  %0 = load float* %arrayidx, align 8
+  %mul5 = fmul float %0, %0
+  %arrayidx9 = getelementptr inbounds float* %input, i64 %add
+  store float %mul5, float* %arrayidx9, align 8
+  %inc = add nsw i64 %i.020, 1
+  %exitcond = icmp eq i64 %inc, 63
+  br i1 %exitcond, label %for.inc10, label %for.body3
+
+for.inc10:                                        ; preds = %for.body3
+  %inc11 = add nsw i64 %j.021, 1
+  %exitcond22 = icmp eq i64 %inc11, 8
+  fence seq_cst
+  br i1 %exitcond22, label %for.end12, label %for.cond1.preheader
+
+for.end12:                                        ; preds = %for.inc10
+  ret void
+}
diff --git a/final/test/ScopInfo/delinearize-together-all-data-refs.ll b/final/test/ScopInfo/delinearize-together-all-data-refs.ll
new file mode 100644
index 0000000..fc98b2e
--- /dev/null
+++ b/final/test/ScopInfo/delinearize-together-all-data-refs.ll
@@ -0,0 +1,77 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;   for (long i = 0; i < n-3; i++)
+;     for (long j = 4; j < m; j++)
+;       for (long k = 0; k < o-7; k++) {
+;         A[i+3][j-4][k+7] = 1.0;
+;         A[i][0][k] = 2.0;
+;       }
+; }
+
+; CHECK: [n, m, o] -> { Stmt_for_body6[i0, i1, i2] -> MemRef_A[3 + i0, i1, 7 + i2] };
+; CHECK: [n, m, o] -> { Stmt_for_body6[i0, i1, i2] -> MemRef_A[i0, 0, i2] };
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @foo(i64 %n, i64 %m, i64 %o, double* nocapture %A) {
+entry:
+  %cmp35 = icmp sgt i64 %n, 0
+  br i1 %cmp35, label %for.cond1.preheader.lr.ph, label %for.end18
+
+for.cond1.preheader.lr.ph:                        ; preds = %entry
+  %cmp233 = icmp sgt i64 %m, 0
+  %cmp531 = icmp sgt i64 %o, 0
+  %0 = mul nuw i64 %o, %m
+  br label %for.cond1.preheader
+
+for.cond1.preheader:                              ; preds = %for.inc16, %for.cond1.preheader.lr.ph
+  %i.036 = phi i64 [ 0, %for.cond1.preheader.lr.ph ], [ %inc17, %for.inc16 ]
+  br i1 %cmp233, label %for.cond4.preheader.lr.ph, label %for.inc16
+
+for.cond4.preheader.lr.ph:                        ; preds = %for.cond1.preheader
+  %add7 = add nsw i64 %i.036, 3
+  %1 = mul nsw i64 %add7, %0
+  %add = add i64 %1, 7
+  %2 = mul nsw i64 %i.036, %0
+  br label %for.cond4.preheader
+
+for.cond4.preheader:                              ; preds = %for.inc13, %for.cond4.preheader.lr.ph
+  %j.034 = phi i64 [ 4, %for.cond4.preheader.lr.ph ], [ %inc14, %for.inc13 ]
+  br i1 %cmp531, label %for.body6.lr.ph, label %for.inc13
+
+for.body6.lr.ph:                                  ; preds = %for.cond4.preheader
+  %sub = add nsw i64 %j.034, -4
+  %3 = mul nsw i64 %sub, %o
+  %arrayidx.sum = add i64 %add, %3
+  br label %for.body6
+
+for.body6:                                        ; preds = %for.body6, %for.body6.lr.ph
+  %k.032 = phi i64 [ 0, %for.body6.lr.ph ], [ %inc, %for.body6 ]
+  %arrayidx8.sum = add i64 %arrayidx.sum, %k.032
+  %arrayidx9 = getelementptr inbounds double* %A, i64 %arrayidx8.sum
+  store double 1.000000e+00, double* %arrayidx9, align 8
+  %arrayidx10.sum = add i64 %k.032, %2
+  %arrayidx12 = getelementptr inbounds double* %A, i64 %arrayidx10.sum
+  store double 2.000000e+00, double* %arrayidx12, align 8
+  %inc = add nsw i64 %k.032, 1
+  %osub = sub nsw i64 %o, 7
+  %exitcond = icmp eq i64 %inc, %osub
+  br i1 %exitcond, label %for.inc13, label %for.body6
+
+for.inc13:                                        ; preds = %for.body6, %for.cond4.preheader
+  %inc14 = add nsw i64 %j.034, 1
+  %exitcond37 = icmp eq i64 %inc14, %m
+  br i1 %exitcond37, label %for.inc16, label %for.cond4.preheader
+
+for.inc16:                                        ; preds = %for.inc13, %for.cond1.preheader
+  %inc17 = add nsw i64 %i.036, 1
+  %nsub = sub nsw i64 %n, 3
+  %exitcond38 = icmp eq i64 %inc17, %nsub
+  br i1 %exitcond38, label %for.end18, label %for.cond1.preheader
+
+for.end18:                                        ; preds = %for.inc16, %entry
+  ret void
+}
diff --git a/final/test/ScopInfo/independent-blocks-never-stop-on-big-scop.ll b/final/test/ScopInfo/independent-blocks-never-stop-on-big-scop.ll
new file mode 100644
index 0000000..871f9ec
--- /dev/null
+++ b/final/test/ScopInfo/independent-blocks-never-stop-on-big-scop.ll
@@ -0,0 +1,200 @@
+; RUN: opt %loadPolly -polly-independent < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind uwtable readnone {
+  %arr = alloca [100 x i32], align 16
+  br label %1
+
+; <label>:1                                       ; preds = %1, %0
+  %indvars.iv3 = phi i64 [ 0, %0 ], [ %indvars.iv.next4, %1 ]
+  %2 = getelementptr inbounds [100 x i32]* %arr, i64 0, i64 %indvars.iv3
+  %3 = trunc i64 %indvars.iv3 to i32
+  store i32 %3, i32* %2, align 4, !tbaa !0
+  %indvars.iv.next4 = add i64 %indvars.iv3, 1
+  %lftr.wideiv5 = trunc i64 %indvars.iv.next4 to i32
+  %exitcond6 = icmp eq i32 %lftr.wideiv5, 100
+  br i1 %exitcond6, label %.preheader, label %1
+
+.preheader:                                       ; preds = %.preheader, %1
+  %indvars.iv = phi i64 [ %indvars.iv.next, %.preheader ], [ 0, %1 ]
+  %4 = getelementptr inbounds [100 x i32]* %arr, i64 0, i64 %indvars.iv
+  %5 = load i32* %4, align 4, !tbaa !0
+  %6 = xor i32 %5, -1
+  %7 = shl i32 %5, 15
+  %8 = add nsw i32 %7, %6
+  %9 = ashr i32 %8, 12
+  %10 = xor i32 %9, %8
+  %11 = mul i32 %10, 9
+  %12 = ashr i32 %11, 4
+  %13 = xor i32 %12, %11
+  %14 = mul nsw i32 %13, 20571
+  %15 = ashr i32 %14, 16
+  %16 = xor i32 %15, %14
+  %17 = xor i32 %16, -1
+  %18 = shl i32 %16, 15
+  %19 = add nsw i32 %18, %17
+  %20 = ashr i32 %19, 12
+  %21 = xor i32 %20, %19
+  %22 = mul i32 %21, 5
+  %23 = ashr i32 %22, 4
+  %24 = xor i32 %23, %22
+  %25 = mul nsw i32 %24, 20576
+  %26 = ashr i32 %25, 16
+  %27 = xor i32 %26, %25
+  %28 = xor i32 %27, -1
+  %29 = shl i32 %27, 15
+  %30 = add nsw i32 %29, %28
+  %31 = ashr i32 %30, 12
+  %32 = xor i32 %31, %30
+  %33 = mul i32 %32, 5
+  %34 = ashr i32 %33, 4
+  %35 = xor i32 %34, %33
+  %36 = mul nsw i32 %35, 2057
+  %37 = ashr i32 %36, 16
+  %38 = xor i32 %37, %36
+  %39 = xor i32 %38, -1
+  %40 = shl i32 %38, 15
+  %41 = add nsw i32 %40, %39
+  %42 = ashr i32 %41, 12
+  %43 = xor i32 %42, %41
+  %44 = mul i32 %43, 5
+  %45 = ashr i32 %44, 4
+  %46 = xor i32 %45, %44
+  %47 = mul nsw i32 %46, 20572
+  %48 = ashr i32 %47, 16
+  %49 = xor i32 %48, %47
+  %50 = xor i32 %49, -1
+  %51 = shl i32 %49, 15
+  %52 = add nsw i32 %51, %50
+  %53 = ashr i32 %52, 12
+  %54 = xor i32 %53, %52
+  %55 = mul i32 %54, 5
+  %56 = ashr i32 %55, 4
+  %57 = xor i32 %56, %55
+  %58 = mul nsw i32 %57, 2051
+  %59 = ashr i32 %58, 16
+  %60 = xor i32 %59, %58
+  %61 = xor i32 %60, -1
+  %62 = shl i32 %60, 15
+  %63 = add nsw i32 %62, %61
+  %64 = ashr i32 %63, 12
+  %65 = xor i32 %64, %63
+  %66 = mul i32 %65, 5
+  %67 = ashr i32 %66, 4
+  %68 = xor i32 %67, %66
+  %69 = mul nsw i32 %68, 2057
+  %70 = ashr i32 %69, 16
+  %71 = xor i32 %70, %69
+  %72 = xor i32 %71, -1
+  %73 = shl i32 %71, 15
+  %74 = add nsw i32 %73, %72
+  %75 = ashr i32 %74, 12
+  %76 = xor i32 %75, %74
+  %77 = mul i32 %76, 5
+  %78 = ashr i32 %77, 4
+  %79 = xor i32 %78, %77
+  %80 = mul nsw i32 %79, 205
+  %81 = ashr i32 %80, 17
+  %82 = xor i32 %81, %80
+  %83 = xor i32 %82, -1
+  %84 = shl i32 %82, 15
+  %85 = add nsw i32 %84, %83
+  %86 = ashr i32 %85, 12
+  %87 = xor i32 %86, %85
+  %88 = mul i32 %87, 5
+  %89 = ashr i32 %88, 4
+  %90 = xor i32 %89, %88
+  %91 = mul nsw i32 %90, 2057
+  %92 = ashr i32 %91, 16
+  %93 = xor i32 %92, %91
+  %94 = xor i32 %93, -1
+  %95 = shl i32 %93, 15
+  %96 = add nsw i32 %95, %94
+  %97 = ashr i32 %96, 12
+  %98 = xor i32 %97, %96
+  %99 = mul i32 %98, 5
+  %100 = ashr i32 %99, 3
+  %101 = xor i32 %100, %99
+  %102 = mul nsw i32 %101, 20571
+  %103 = ashr i32 %102, 16
+  %104 = xor i32 %103, %102
+  %105 = xor i32 %104, -1
+  %106 = shl i32 %104, 15
+  %107 = add nsw i32 %106, %105
+  %108 = ashr i32 %107, 12
+  %109 = xor i32 %108, %107
+  %110 = mul i32 %109, 5
+  %111 = ashr i32 %110, 4
+  %112 = xor i32 %111, %110
+  %113 = mul nsw i32 %112, 2057
+  %114 = ashr i32 %113, 16
+  %115 = xor i32 %114, %113
+  %116 = xor i32 %115, -1
+  %117 = shl i32 %115, 15
+  %118 = add nsw i32 %117, %116
+  %119 = ashr i32 %118, 12
+  %120 = xor i32 %119, %118
+  %121 = mul i32 %120, 5
+  %122 = ashr i32 %121, 4
+  %123 = xor i32 %122, %121
+  %124 = mul nsw i32 %123, 20572
+  %125 = ashr i32 %124, 16
+  %126 = xor i32 %125, %124
+  %127 = xor i32 %126, -1
+  %128 = shl i32 %126, 15
+  %129 = add nsw i32 %128, %127
+  %130 = ashr i32 %129, 12
+  %131 = xor i32 %130, %129
+  %132 = mul i32 %131, 5
+  %133 = ashr i32 %132, 4
+  %134 = xor i32 %133, %132
+  %135 = mul nsw i32 %134, 2057
+  %136 = ashr i32 %135, 16
+  %137 = xor i32 %136, %135
+  %138 = xor i32 %137, -1
+  %139 = shl i32 %137, 15
+  %140 = add nsw i32 %139, %138
+  %141 = ashr i32 %140, 12
+  %142 = xor i32 %141, %140
+  %143 = mul i32 %142, 5
+  %144 = ashr i32 %143, 4
+  %145 = xor i32 %144, %143
+  %146 = mul nsw i32 %145, 2057
+  %147 = ashr i32 %146, 16
+  %148 = xor i32 %147, %146
+  %149 = xor i32 %148, -1
+  %150 = shl i32 %148, 15
+  %151 = add nsw i32 %150, %149
+  %152 = ashr i32 %151, 12
+  %153 = xor i32 %152, %151
+  %154 = mul i32 %153, 5
+  %155 = ashr i32 %154, 4
+  %156 = xor i32 %155, %154
+  %157 = mul nsw i32 %156, 2057
+  %158 = ashr i32 %157, 16
+  %159 = xor i32 %158, %157
+  %160 = xor i32 %159, -1
+  %161 = shl i32 %159, 15
+  %162 = add nsw i32 %161, %160
+  %163 = ashr i32 %162, 12
+  %164 = xor i32 %163, %162
+  %165 = mul i32 %164, 5
+  %166 = ashr i32 %165, 4
+  %167 = xor i32 %166, %165
+  %168 = mul nsw i32 %167, 2057
+  %169 = ashr i32 %168, 16
+  %170 = xor i32 %169, %168
+  store i32 %170, i32* %4, align 4, !tbaa !0
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+  %exitcond = icmp eq i32 %lftr.wideiv, 100
+  br i1 %exitcond, label %171, label %.preheader
+
+; <label>:171                                     ; preds = %.preheader
+  ret i32 0
+}
+
+!0 = !{!"int", !1}
+!1 = !{!"omnipotent char", !2}
+!2 = !{!"Simple C/C++ TBAA", null}
diff --git a/final/test/ScopInfo/integers.ll b/final/test/ScopInfo/integers.ll
new file mode 100644
index 0000000..f36bf1f
--- /dev/null
+++ b/final/test/ScopInfo/integers.ll
@@ -0,0 +1,123 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+; Check that we correctly convert integers to isl values.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Large positive integer
+define void @f(i1024* nocapture %a) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %indvar = phi i1024 [ 0, %entry ], [ %indvar.next, %bb ]
+  %scevgep = getelementptr i1024* %a, i1024 %indvar
+  store i1024 %indvar, i1024* %scevgep, align 8
+  %indvar.next = add nsw i1024 %indvar, 1
+  %exitcond = icmp eq i1024 %indvar, 123456000000000000000000000
+; CHECK:  'bb => return' in function 'f'
+; CHECK: i0 <= 123456000000000000000000000
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
+
+; Normal positive integer
+define void @f2(i32* nocapture %a) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ]
+  %scevgep = getelementptr i32* %a, i32 %indvar
+  store i32 %indvar, i32* %scevgep, align 8
+  %indvar.next = add nsw i32 %indvar, 1
+  %exitcond = icmp eq i32 %indvar, 123456
+; CHECK:  'bb => return' in function 'f2'
+; CHECK: i0 <= 123456
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
+
+; Normal negative integer
+define void @f3(i32* nocapture %a, i32 %n) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ]
+  %scevgep = getelementptr i32* %a, i32 %indvar
+  store i32 %indvar, i32* %scevgep, align 8
+  %indvar.next = add nsw i32 %indvar, 1
+  %sub = sub i32 %n, 123456
+  %exitcond = icmp eq i32 %indvar, %sub
+; CHECK:  'bb => return' in function 'f3'
+; CHECK: -123456
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
+
+; Large negative integer
+define void @f4(i1024* nocapture %a, i1024 %n) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %indvar = phi i1024 [ 0, %entry ], [ %indvar.next, %bb ]
+  %scevgep = getelementptr i1024* %a, i1024 %indvar
+  store i1024 %indvar, i1024* %scevgep, align 8
+  %indvar.next = add nsw i1024 %indvar, 1
+  %sub = sub i1024 %n, 123456000000000000000000000000000000
+; CHECK:  'bb => return' in function 'f4'
+; CHECK: -123456000000000000000000000000000000
+  %exitcond = icmp eq i1024 %indvar, %sub
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
+
+define void @f5(i1023* nocapture %a, i1023 %n) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %indvar = phi i1023 [ 0, %entry ], [ %indvar.next, %bb ]
+  %scevgep = getelementptr i1023* %a, i1023 %indvar
+  store i1023 %indvar, i1023* %scevgep, align 8
+  %indvar.next = add nsw i1023 %indvar, 1
+  %sub = sub i1023 %n, 123456000000000000000000000000000000
+; CHECK:  'bb => return' in function 'f5'
+; CHECK: -123456000000000000000000000000000000
+  %exitcond = icmp eq i1023 %indvar, %sub
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
+
+; Tiny negative integer
+define void @f6(i3* nocapture %a, i3 %n) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %indvar = phi i3 [ 0, %entry ], [ %indvar.next, %bb ]
+  %scevgep = getelementptr i3* %a, i3 %indvar
+  store i3 %indvar, i3* %scevgep, align 8
+  %indvar.next = add nsw i3 %indvar, 1
+  %sub = sub i3 %n, 3
+; CHECK:  'bb => return' in function 'f6'
+; CHECK: -3
+  %exitcond = icmp eq i3 %indvar, %sub
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
diff --git a/final/test/ScopInfo/isl_aff_out_of_bounds.ll b/final/test/ScopInfo/isl_aff_out_of_bounds.ll
new file mode 100644
index 0000000..94dc395
--- /dev/null
+++ b/final/test/ScopInfo/isl_aff_out_of_bounds.ll
@@ -0,0 +1,40 @@
+; RUN: opt %loadPolly -basicaa -polly-detect < %s
+
+; Used to fail with:
+; ../../isl/isl_aff.c:591: position out of bounds
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare double @frexp(double)
+
+define void @vorbis_lsp_to_curve(float* %lsp, i32 %m) {
+entry:
+  %q.1.reg2mem = alloca float, align 4
+  br i1 undef, label %do.body, label %while.end
+
+do.body:                                          ; preds = %do.body, %entry
+  %ftmp.0 = phi float* [ %add.ptr, %do.body ], [ %lsp, %entry ]
+  %add.ptr = getelementptr inbounds float* %ftmp.0, i64 2
+  br i1 true, label %do.end, label %do.body
+
+do.end:                                           ; preds = %do.body
+  br i1 false, label %if.end.single_exit, label %if.then
+
+if.then:                                          ; preds = %do.end
+  %0 = load float* %add.ptr, align 4
+  store float %0, float* %q.1.reg2mem, align 4
+  br label %if.end.single_exit
+
+if.end.single_exit:                               ; preds = %do.end, %if.then
+  br label %if.end
+
+if.end:                                           ; preds = %if.end.single_exit
+  %q.1.reload = load float* %q.1.reg2mem, align 4
+  %conv31 = fpext float %q.1.reload to double
+  %call32 = call double @frexp(double %conv31)
+  unreachable
+
+while.end:                                        ; preds = %entry
+  ret void
+}
diff --git a/final/test/ScopInfo/loop_affine_bound_0.ll b/final/test/ScopInfo/loop_affine_bound_0.ll
new file mode 100644
index 0000000..6f5778b
--- /dev/null
+++ b/final/test/ScopInfo/loop_affine_bound_0.ll
@@ -0,0 +1,64 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+; void f(long a[][128], long N, long M) {
+;   long i, j;
+;   for (j = 0; j < (4*N + 7*M +3); ++j)
+;     for (i = 0; i < (5*N + 2); ++i)
+;       a[j][i] = 0
+;   }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f([128 x i64]* nocapture %a, i64 %N, i64 %M) nounwind {
+entry:
+  %0 = shl i64 %N, 2                              ; <i64> [#uses=2]
+  %1 = mul i64 %M, 7                              ; <i64> [#uses=2]
+  %2 = or i64 %0, 3                               ; <i64> [#uses=1]
+  %3 = add nsw i64 %2, %1                         ; <i64> [#uses=1]
+  %4 = icmp sgt i64 %3, 0                         ; <i1> [#uses=1]
+  br i1 %4, label %bb.nph8, label %return
+
+bb1:                                              ; preds = %bb2.preheader, %bb1
+  %i.06 = phi i64 [ 0, %bb2.preheader ], [ %5, %bb1 ] ; <i64> [#uses=2]
+  %scevgep = getelementptr [128 x i64]* %a, i64 %i.06, i64 %10 ; <i64*> [#uses=1]
+  store i64 0, i64* %scevgep, align 8
+  %5 = add nsw i64 %i.06, 1                       ; <i64> [#uses=2]
+  %exitcond = icmp eq i64 %5, %8                  ; <i1> [#uses=1]
+  br i1 %exitcond, label %bb3, label %bb1
+
+bb3:                                              ; preds = %bb1
+  %6 = add i64 %10, 1                             ; <i64> [#uses=2]
+  %exitcond14 = icmp eq i64 %6, %tmp13            ; <i1> [#uses=1]
+  br i1 %exitcond14, label %return, label %bb2.preheader
+
+bb.nph8:                                          ; preds = %entry
+  %7 = mul i64 %N, 5                              ; <i64> [#uses=1]
+  %8 = add nsw i64 %7, 2                          ; <i64> [#uses=2]
+  %9 = icmp sgt i64 %8, 0                         ; <i1> [#uses=1]
+  br i1 %9, label %bb.nph8.split, label %return
+
+bb.nph8.split:                                    ; preds = %bb.nph8
+  %tmp12 = add i64 %1, %0                         ; <i64> [#uses=1]
+  %tmp13 = add i64 %tmp12, 3                      ; <i64> [#uses=1]
+  br label %bb2.preheader
+
+bb2.preheader:                                    ; preds = %bb.nph8.split, %bb3
+  %10 = phi i64 [ 0, %bb.nph8.split ], [ %6, %bb3 ] ; <i64> [#uses=2]
+  br label %bb1
+
+return:                                           ; preds = %bb.nph8, %bb3, %entry
+  ret void
+}
+
+; CHECK:  p0: %N
+; CHECK:  p1: %M
+; CHECK:  Statements {
+; CHECK:    Stmt_bb1
+; CHECK:          Domain :=
+; CHECK:              [N, M] -> { Stmt_bb1[i0, i1] : i0 >= 0 and i0 <= 2 + 4N + 7M and i1 >= 0 and i1 <= 1 + 5N and N >= 0 };
+; CHECK:          Scattering :=
+; CHECK:              [N, M] -> { Stmt_bb1[i0, i1] -> scattering[i0, i1] };
+; CHECK:          MustWriteAccess := [Reduction Type: NONE]
+; CHECK:              [N, M] -> { Stmt_bb1[i0, i1] -> MemRef_a[i0 + 128i1] };
+; CHECK:  }
diff --git a/final/test/ScopInfo/loop_affine_bound_1.ll b/final/test/ScopInfo/loop_affine_bound_1.ll
new file mode 100644
index 0000000..3c2fe35
--- /dev/null
+++ b/final/test/ScopInfo/loop_affine_bound_1.ll
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+;void f(long a[][128], long N, long M) {
+;  long i, j;
+;  for (j = 0; j < (4*N + 7*M +3); ++j)
+;    for (i = j; i < (5*N + 2); ++i)
+;        ...
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f([128 x i64]* nocapture %a, i64 %N, i64 %M) nounwind {
+entry:
+  %0 = shl i64 %N, 2                              ; <i64> [#uses=2]
+  %1 = mul i64 %M, 7                              ; <i64> [#uses=2]
+  %2 = or i64 %0, 3                               ; <i64> [#uses=1]
+  %3 = add nsw i64 %2, %1                         ; <i64> [#uses=1]
+  %4 = icmp sgt i64 %3, 0                         ; <i1> [#uses=1]
+  br i1 %4, label %bb.nph8, label %return
+
+bb1:                                              ; preds = %bb2.preheader, %bb1
+  %indvar = phi i64 [ 0, %bb2.preheader ], [ %indvar.next, %bb1 ] ; <i64> [#uses=2]
+  %scevgep = getelementptr [128 x i64]* %a, i64 %indvar, i64 %tmp10 ; <i64*> [#uses=1]
+  store i64 0, i64* %scevgep, align 8
+  %indvar.next = add i64 %indvar, 1               ; <i64> [#uses=2]
+  %exitcond = icmp eq i64 %indvar.next, %tmp9     ; <i1> [#uses=1]
+  br i1 %exitcond, label %bb3, label %bb1
+
+bb3:                                              ; preds = %bb2.preheader, %bb1
+  %5 = add i64 %8, 1                              ; <i64> [#uses=2]
+  %exitcond14 = icmp eq i64 %5, %tmp13            ; <i1> [#uses=1]
+  br i1 %exitcond14, label %return, label %bb2.preheader
+
+bb.nph8:                                          ; preds = %entry
+  %6 = mul i64 %N, 5                              ; <i64> [#uses=1]
+  %7 = add nsw i64 %6, 2                          ; <i64> [#uses=2]
+  %tmp12 = add i64 %1, %0                         ; <i64> [#uses=1]
+  %tmp13 = add i64 %tmp12, 3                      ; <i64> [#uses=1]
+  br label %bb2.preheader
+
+bb2.preheader:                                    ; preds = %bb.nph8, %bb3
+  %8 = phi i64 [ 0, %bb.nph8 ], [ %5, %bb3 ]      ; <i64> [#uses=4]
+  %tmp10 = mul i64 %8, 129                        ; <i64> [#uses=1]
+  %tmp9 = sub i64 %7, %8                          ; <i64> [#uses=1]
+  %9 = icmp sgt i64 %7, %8                        ; <i1> [#uses=1]
+  br i1 %9, label %bb1, label %bb3
+
+return:                                           ; preds = %bb3, %entry
+  ret void
+}
+
+; CHECK: p0: %N
+; CHECK: p1: %M
+; CHECK: Statements {
+; CHECK:   Stmt_bb1
+; CHECK:         Domain :=
+; CHECK:             [N, M] -> { Stmt_bb1[i0, i1] : i0 >= 0 and i0 <= 2 + 4N + 7M and i1 >= 0 and i1 <= 1 + 5N - i0 and i0 <= 1 + 5N };
+; CHECK:         Scattering :=
+; CHECK:             [N, M] -> { Stmt_bb1[i0, i1] -> scattering[i0, i1] };
+; CHECK:         MustWriteAccess := [Reduction Type: NONE]
+; CHECK:             [N, M] -> { Stmt_bb1[i0, i1] -> MemRef_a[129i0 + 128i1] };
+; CHECK: }
diff --git a/final/test/ScopInfo/loop_affine_bound_2.ll b/final/test/ScopInfo/loop_affine_bound_2.ll
new file mode 100644
index 0000000..f686c78
--- /dev/null
+++ b/final/test/ScopInfo/loop_affine_bound_2.ll
@@ -0,0 +1,74 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+; void f(long a[][128], long N, long M) {
+;   long i, j;
+;   for (j = 0; j < (4*N + 7*M +3); ++j)
+;     for (i = (7*j + 6*M -9); i < (3*j + 5*N + 2) ; ++i)
+;         a[i][j] = 0;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f([128 x i64]* nocapture %a, i64 %N, i64 %M) nounwind {
+entry:
+  %0 = shl i64 %N, 2
+  %1 = mul i64 %M, 7
+  %2 = or i64 %0, 3
+  %3 = add nsw i64 %2, %1
+  %4 = icmp sgt i64 %3, 0
+  br i1 %4, label %bb.nph8, label %return
+
+bb.nph8:                                          ; preds = %entry
+  %tmp14 = mul i64 %M, 6
+  %tmp15 = add i64 %tmp14, -9
+  %tmp20 = add i64 %1, %0
+  %tmp21 = add i64 %tmp20, 3
+  %tmp25 = mul i64 %M, -6
+  %tmp26 = mul i64 %N, 5
+  %tmp27 = add i64 %tmp25, %tmp26
+  %tmp28 = add i64 %tmp27, 11
+  %tmp35 = add i64 %tmp26, 2
+  br label %bb
+
+bb:                                               ; preds = %bb3, %bb.nph8
+  %j.07 = phi i64 [ 0, %bb.nph8 ], [ %6, %bb3 ]
+  %tmp17 = mul i64 %j.07, 897
+  %tmp24 = mul i64 %j.07, -4
+  %tmp13 = add i64 %tmp24, %tmp28
+  %tmp30 = mul i64 %j.07, 7
+  %tmp33 = add i64 %tmp30, %tmp15
+  %tmp34 = mul i64 %j.07, 3
+  %tmp36 = add i64 %tmp34, %tmp35
+  %5 = icmp sgt i64 %tmp36, %tmp33
+  br i1 %5, label %bb1, label %bb3
+
+bb1:                                              ; preds = %bb1, %bb
+  %indvar = phi i64 [ 0, %bb ], [ %indvar.next, %bb1 ]
+  %tmp16 = add i64 %indvar, %tmp15
+  %scevgep = getelementptr [128 x i64]* %a, i64 %tmp16, i64 %tmp17
+  store i64 0, i64* %scevgep
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %tmp13
+  br i1 %exitcond, label %bb3, label %bb1
+
+bb3:                                              ; preds = %bb1, %bb
+  %6 = add nsw i64 %j.07, 1
+  %exitcond22 = icmp eq i64 %6, %tmp21
+  br i1 %exitcond22, label %return, label %bb
+
+return:                                           ; preds = %bb3, %entry
+  ret void
+}
+
+; CHECK: p0: %N
+; CHECK: p1: %M
+; CHECK: Statements {
+; CHECK:   Stmt_bb1
+; CHECK:         Domain :=
+; CHECK:             [N, M] -> { Stmt_bb1[i0, i1] : i0 >= 0 and i0 <= 2 + 4N + 7M and i1 >= 0 and i1 <= 10 + 5N - 6M - 4i0 and 4i0 <= 10 + 5N - 6M };
+; CHECK:         Scattering :=
+; CHECK:             [N, M] -> { Stmt_bb1[i0, i1] -> scattering[i0, i1] };
+; CHECK:         MustWriteAccess := [Reduction Type: NONE]
+; CHECK:             [N, M] -> { Stmt_bb1[i0, i1] -> MemRef_a[-1152 + 768M + 897i0 + 128i1] };
+; CHECK: }
diff --git a/final/test/ScopInfo/loop_carry.ll b/final/test/ScopInfo/loop_carry.ll
new file mode 100644
index 0000000..d72316c
--- /dev/null
+++ b/final/test/ScopInfo/loop_carry.ll
@@ -0,0 +1,81 @@
+; RUN: opt %loadPolly -basicaa -polly-prepare -polly-scops -analyze  < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+;long f(long a[], long n) {
+;  long i, k;
+;  k = 1;
+;  for (i = 1; i < n; ++i) {
+;   a[i] = k * a[i - 1];
+;   k = a[i + 3] + a[2 * i];
+;  }
+;  return 0;
+;}
+
+define i64 @f(i64* nocapture %a, i64 %n) nounwind {
+entry:
+  %0 = icmp sgt i64 %n, 1                         ; <i1> [#uses=1]
+  br i1 %0, label %bb.nph, label %bb2
+
+bb.nph:                                           ; preds = %entry
+  %tmp = add i64 %n, -1                           ; <i64> [#uses=1]
+  %.pre = load i64* %a, align 8                   ; <i64> [#uses=1]
+  br label %bb
+
+bb:                                               ; preds = %bb, %bb.nph
+  %1 = phi i64 [ %.pre, %bb.nph ], [ %2, %bb ]    ; <i64> [#uses=1]
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ] ; <i64> [#uses=3]
+  %k.05 = phi i64 [ 1, %bb.nph ], [ %5, %bb ]     ; <i64> [#uses=1]
+  %tmp6 = add i64 %indvar, 1                      ; <i64> [#uses=3]
+  %scevgep = getelementptr i64* %a, i64 %tmp6     ; <i64*> [#uses=1]
+  %2 = mul nsw i64 %1, %k.05                      ; <i64> [#uses=2]
+  store i64 %2, i64* %scevgep, align 8
+  %tmp7 = shl i64 %indvar, 1                      ; <i64> [#uses=1]
+  %tmp11 = add i64 %indvar, 4                     ; <i64> [#uses=1]
+  %tmp8 = add i64 %tmp7, 2                        ; <i64> [#uses=1]
+  %scevgep12 = getelementptr i64* %a, i64 %tmp11  ; <i64*> [#uses=1]
+  %scevgep9 = getelementptr i64* %a, i64 %tmp8    ; <i64*> [#uses=1]
+  %3 = load i64* %scevgep9, align 8               ; <i64> [#uses=1]
+  %4 = load i64* %scevgep12, align 8              ; <i64> [#uses=1]
+  %5 = add nsw i64 %3, %4                         ; <i64> [#uses=1]
+  %exitcond = icmp eq i64 %tmp6, %tmp             ; <i1> [#uses=1]
+  br i1 %exitcond, label %bb2, label %bb
+
+bb2:                                              ; preds = %bb, %entry
+  ret i64 0
+}
+
+; CHECK: Context:
+; CHECK: [n] -> { : n >= -9223372036854775808 and n <= 9223372036854775807 }
+; CHECK:     Statements {
+; CHECK:     	Stmt_bb_nph
+; CHECK:             Domain :=
+; CHECK:                 [n] -> { Stmt_bb_nph[] : n >= 2 };
+; CHECK:             Scattering :=
+; CHECK:                 [n] -> { Stmt_bb_nph[] -> scattering[0, 0] };
+; CHECK:             ReadAccess :=
+; CHECK:                 [n] -> { Stmt_bb_nph[] -> MemRef_a[0] };
+; CHECK:             MustWriteAccess :=
+; CHECK:                 [n] -> { Stmt_bb_nph[] -> MemRef_k_05_reg2mem[0] };
+; CHECK:             MustWriteAccess :=
+; CHECK:                 [n] -> { Stmt_bb_nph[] -> MemRef__reg2mem[0] };
+; CHECK:     	Stmt_bb
+; CHECK:             Domain :=
+; CHECK:                 [n] -> { Stmt_bb[i0] : i0 >= 0 and i0 <= -2 + n and n >= 2 };
+; CHECK:             Scattering :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> scattering[1, i0] };
+; CHECK:             ReadAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef__reg2mem[0] };
+; CHECK:             ReadAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef_k_05_reg2mem[0] };
+; CHECK:             MustWriteAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef_a[1 + i0] };
+; CHECK:             ReadAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef_a[2 + 2i0] };
+; CHECK:             ReadAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef_a[4 + i0] };
+; CHECK:             MustWriteAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef_k_05_reg2mem[0] };
+; CHECK:             MustWriteAccess :=
+; CHECK:                 [n] -> { Stmt_bb[i0] -> MemRef__reg2mem[0] };
diff --git a/final/test/ScopInfo/max-loop-depth.ll b/final/test/ScopInfo/max-loop-depth.ll
new file mode 100644
index 0000000..3e0f806
--- /dev/null
+++ b/final/test/ScopInfo/max-loop-depth.ll
@@ -0,0 +1,79 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+;    void bar();
+;    void foo(int *A, int *B, long int N, long int M) {
+;      for (long int j = 0; j < M; ++j) {
+;        bar();
+;        for (long int i = 0; i < N; ++i)
+;          A[i] += 1;
+;        for (long int i = 0; i < N; ++i)
+;          A[i] += 1;
+;      }
+;    }
+;
+; Test to check that the scop only counts loop depth for loops fully contained
+; in the scop.
+; CHECK: Max Loop Depth: 1
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo(i32* %A, i32* %B, i64 %N, i64 %M) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc13, %entry
+  %j.0 = phi i64 [ 0, %entry ], [ %inc14, %for.inc13 ]
+  %cmp = icmp slt i64 %j.0, %M
+  br i1 %cmp, label %for.body, label %for.end15
+
+for.body:                                         ; preds = %for.cond
+  call void (...)* @bar() #2
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %i.0 = phi i64 [ 0, %for.body ], [ %inc, %for.inc ]
+  %cmp2 = icmp slt i64 %i.0, %N
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %A, i64 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 1
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nuw nsw i64 %i.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc10, %for.end
+  %i4.0 = phi i64 [ 0, %for.end ], [ %inc11, %for.inc10 ]
+  %cmp6 = icmp slt i64 %i4.0, %N
+  br i1 %cmp6, label %for.body7, label %for.end12
+
+for.body7:                                        ; preds = %for.cond5
+  %arrayidx8 = getelementptr inbounds i32* %A, i64 %i4.0
+  %tmp1 = load i32* %arrayidx8, align 4
+  %add9 = add nsw i32 %tmp1, 1
+  store i32 %add9, i32* %arrayidx8, align 4
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.body7
+  %inc11 = add nuw nsw i64 %i4.0, 1
+  br label %for.cond5
+
+for.end12:                                        ; preds = %for.cond5
+  br label %for.inc13
+
+for.inc13:                                        ; preds = %for.end12
+  %inc14 = add nuw nsw i64 %j.0, 1
+  br label %for.cond
+
+for.end15:                                        ; preds = %for.cond
+  ret void
+}
+
+declare void @bar(...) #1
+
diff --git a/final/test/ScopInfo/multi-scop.ll b/final/test/ScopInfo/multi-scop.ll
new file mode 100644
index 0000000..09998a3
--- /dev/null
+++ b/final/test/ScopInfo/multi-scop.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -analyze < %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This test case contains two scops.
+define void @test(i32 %l, double* %a) {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  %shl = shl i32 %l, 2
+  br i1 false, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.body, %entry.split
+  %j.011 = phi i32 [ 0, %entry.split ], [ %add76, %for.body ]
+  %add76 = add nsw i32 %j.011, 2
+  br i1 false, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body, %entry.split
+  br i1 undef, label %for.body81, label %for.end170
+
+for.body81:                                       ; preds = %for.body81, %for.end
+  %j.19 = phi i32 [ %shl, %for.end ], [ %add169, %for.body81 ]
+  %add13710 = or i32 %j.19, 1
+  %idxprom138 = sext i32 %add13710 to i64
+  %arrayidx139 = getelementptr inbounds double* %a, i64 %idxprom138
+  store double undef, double* %arrayidx139, align 8
+  %add169 = add nsw i32 %j.19, 2
+  br i1 false, label %for.body81, label %for.end170
+
+for.end170:                                       ; preds = %for.body81
+  ret void
+}
+
+; CHECK: Valid Region for Scop: entry.split => for.end
+; CHECK: Valid Region for Scop: for.body81 => for.end170
+
diff --git a/final/test/ScopInfo/multidim_2d-diagonal-matrix.ll b/final/test/ScopInfo/multidim_2d-diagonal-matrix.ll
new file mode 100644
index 0000000..964724a
--- /dev/null
+++ b/final/test/ScopInfo/multidim_2d-diagonal-matrix.ll
@@ -0,0 +1,43 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Derived from the following code:
+;
+; void foo(long n, double A[n][n]) {
+;   for (long i = 0; i < n; i++)
+;     A[i][i] = 1.0;
+; }
+
+
+; CHECK: Assumed Context:
+; CHECK:   [n] -> {  :  }
+
+; CHECK: p0: %n
+; CHECK-NOT: p1
+
+; CHECK: Domain :=
+; CHECK:   [n] -> { Stmt_for_i[i0] : i0 >= 0 and i0 <= -1 + n };
+; CHECK: Scattering :=
+; CHECK:   [n] -> { Stmt_for_i[i0] -> scattering[i0] };
+; CHECK: MustWriteAccess :=
+; CHECK:   [n] -> { Stmt_for_i[i0] -> MemRef_A[i0, i0] };
+
+
+define void @foo(i64 %n, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i ]
+  %tmp = mul nsw i64 %i, %n
+  %vlaarrayidx.sum = add i64 %i, %tmp
+  %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum
+  store double 1.0, double* %arrayidx
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_2d_outer_parametric_offset.ll b/final/test/ScopInfo/multidim_2d_outer_parametric_offset.ll
new file mode 100644
index 0000000..176cbfe
--- /dev/null
+++ b/final/test/ScopInfo/multidim_2d_outer_parametric_offset.ll
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Derived from the following code:
+;
+; void foo(long n, long m, long p, double A[n][m]) {
+;   for (long i = 0; i < 100; i++)
+;     for (long j = 0; j < m; j++)
+;       A[i+p][j] = 1.0;
+; }
+
+; CHECK:  Assumed Context:
+; CHECK:  [m, p] -> {  : }
+; CHECK:  p0: %m
+; CHECK:  p1: %p
+; CHECK:  Statements {
+; CHECK:    Stmt_for_j
+; CHECK:          Domain :=
+; CHECK:              [m, p] -> { Stmt_for_j[i0, i1] : i0 >= 0 and i0 <= 99 and i1 >= 0 and i1 <= -1 + m };
+; CHECK:          Scattering :=
+; CHECK:              [m, p] -> { Stmt_for_j[i0, i1] -> scattering[i0, i1] };
+; CHECK:          MustWriteAccess := [Reduction Type: NONE]
+; CHECK:              [m, p] -> { Stmt_for_j[i0, i1] -> MemRef_A[p + i0, i1] };
+; CHECK:  }
+
+define void @foo(i64 %n, i64 %m, i64 %p, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  %add = add nsw i64 %i, %p
+  %tmp = mul nsw i64 %add, %m
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j ]
+  %vlaarrayidx.sum = add i64 %j, %tmp
+  %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum
+  store double 1.0, double* %arrayidx
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, 100
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll b/final/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll
new file mode 100644
index 0000000..f19d649
--- /dev/null
+++ b/final/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll
@@ -0,0 +1,49 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Derived from the following code:
+;
+; void foo(long n, long m, double A[n][m]) {
+;   for (long i = 0; i < 100; i++)
+;     for (long j = 0; j < 150; j++)
+;       A[i][j] = 1.0;
+; }
+; CHECK: Assumed Context:
+; CHECK: [m] -> {  : m >= 150 }
+; CHECK: p0: %m
+; CHECK: Statements {
+; CHECK:   Stmt_for_j
+; CHECK:         Domain :=
+; CHECK:             [m] -> { Stmt_for_j[i0, i1] : i0 >= 0 and i0 <= 99 and i1 >= 0 and i1 <= 149 };
+; CHECK:         Scattering :=
+; CHECK:             [m] -> { Stmt_for_j[i0, i1] -> scattering[i0, i1] };
+; CHECK:         MustWriteAccess := [Reduction Type: NONE]
+; CHECK:             [m] -> { Stmt_for_j[i0, i1] -> MemRef_A[i0, i1] };
+
+define void @foo(i64 %n, i64 %m, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  %tmp = mul nsw i64 %i, %m
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j ]
+  %vlaarrayidx.sum = add i64 %j, %tmp
+  %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum
+  store double 1.0, double* %arrayidx
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, 150
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, 100
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll b/final/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll
new file mode 100644
index 0000000..08a17d7
--- /dev/null
+++ b/final/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll
@@ -0,0 +1,65 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;
+;   for (long i = 0; i < 100; i++)
+;     for (long j = 0; j < 150; j++)
+;       for (long k = 0; k < 200; k++)
+;         A[i][j][k] = 1.0;
+; }
+
+; CHECK:   Assumed Context:
+; CHECK:   [m, o] -> {  : m >= 150 and o >= 200 }
+; CHECK:   p0: %m
+; CHECK:   p1: %o
+; CHECK:   Statements {
+; CHECK:     Stmt_for_k
+; CHECK:           Domain :=
+; CHECK:               [m, o] -> { Stmt_for_k[i0, i1, i2] : i0 >= 0 and i0 <= 99 and i1 >= 0 and i1 <= 149 and i2 >= 0 and i2 <= 199 };
+; CHECK:           Scattering :=
+; CHECK:               [m, o] -> { Stmt_for_k[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK:           MustWriteAccess := [Reduction Type: NONE]
+; CHECK:               [m, o] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[i0, i1, i2] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.j ], [ %k.inc, %for.k.inc ]
+  %subscript0 = mul i64 %i, %m
+  %subscript1 = add i64 %j, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %subscript = add i64 %subscript2, %k
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %k.exitcond = icmp eq i64 %k.inc, 200
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, 150
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, 100
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll b/final/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll
new file mode 100644
index 0000000..d275457
--- /dev/null
+++ b/final/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;
+;   for (long i = 0; i < n-3; i++)
+;     for (long j = 4; j < m; j++)
+;       for (long k = 0; k < o-7; k++)
+;         A[i+3][j-4][k+7] = 1.0;
+; }
+
+; CHECK: Assumed Context:
+; CHECK: {  :  }
+
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK: p2: %o
+; CHECK-NOT: p3
+
+; CHECK: Domain
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] : i0 >= 0 and i0 <= -4 + n and i1 >= 0 and i1 <= -5 + m and i2 >= 0 and i2 <= -8 + o };
+; CHECK: Scattering
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK: MustWriteAccess
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[3 + i0, i1, 7 + i2] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 4, %for.i ], [ %j.inc, %for.j.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.j ], [ %k.inc, %for.k.inc ]
+  %offset0 = add nsw i64 %i, 3
+  %subscript0 = mul i64 %offset0, %m
+  %offset1 = add nsw i64 %j, -4
+  %subscript1 = add i64 %offset1, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %offset2 = add nsw i64 %k, 7
+  %subscript = add i64 %subscript2, %offset2
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %osub = sub nsw i64 %o, 7
+  %k.exitcond = icmp eq i64 %k.inc, %osub
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %nsub = sub nsw i64 %n, 3
+  %i.exitcond = icmp eq i64 %i.inc, %nsub
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll b/final/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll
new file mode 100644
index 0000000..8b17ab0
--- /dev/null
+++ b/final/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll
@@ -0,0 +1,77 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, long o, double A[n][m][o], long p, long q, long r) {
+;
+;   for (long i = 0; i < n; i++)
+;     for (long j = 0; j < m; j++)
+;       for (long k = 0; k < o; k++)
+;         A[i+p][j+q][k+r] = 1.0;
+; }
+;
+; Access function:
+;    {{{((8 * ((((%m * %p) + %q) * %o) + %r)) + %A),+,(8 * %m * %o)}<%for.i>,+,
+;        (8 * %o)}<%for.j>,+,8}<%for.k>
+
+; CHECK: Assumed Context:
+; CHECK: [n, m, o, p, q, r] -> { : q = 0 and r = 0 }
+;
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK: p2: %o
+; CHECK: p3: %p
+; CHECK: p4: %q
+; CHECK: p5: %r
+; CHECK-NOT: p6
+;
+; CHECK: Domain
+; CHECK:   [n, m, o, p, q, r] -> { Stmt_for_k[i0, i1, i2] : i0 >= 0 and i0 <= -1 + n and i1 >= 0 and i1 <= -1 + m and i2 >= 0 and i2 <= -1 + o };
+; CHECK: Scattering
+; CHECK:   [n, m, o, p, q, r] -> { Stmt_for_k[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK: MustWriteAccess
+; CHECK:   [n, m, o, p, q, r] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[p + i0, q + i1, r + i2] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A, i64 %p, i64 %q, i64 %r) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.j ], [ %k.inc, %for.k.inc ]
+  %offset0 = add nsw i64 %i, %p
+  %subscript0 = mul i64 %offset0, %m
+  %offset1 = add nsw i64 %j, %q
+  %subscript1 = add i64 %offset1, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %offset2 = add nsw i64 %k, %r
+  %subscript = add i64 %subscript2, %offset2
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %k.exitcond = icmp eq i64 %k.inc, %o
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_nested_start_integer.ll b/final/test/ScopInfo/multidim_nested_start_integer.ll
new file mode 100644
index 0000000..bd78a76
--- /dev/null
+++ b/final/test/ScopInfo/multidim_nested_start_integer.ll
@@ -0,0 +1,69 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;   for (long i = 0; i < n - 3; i++)
+;     for (long j = 4; j < m; j++)
+;       for (long k = 0; k < o - 7; k++)
+;         A[i+3][j-4][k+7] = 1.0;
+; }
+;
+; CHECK: Assumed Context:
+; CHECK:   {  :  }
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK: p2: %o
+; CHECK-NOT: p3
+; CHECK: Domain
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] : i0 >= 0 and i0 <= -4 + n and i1 >= 0 and i1 <= -5 + m and i2 >= 0 and i2 <= -8 + o };
+; CHECK: Scattering
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK: MustWriteAccess
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[3 + i0, i1, 7 + i2] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 4, %for.i ], [ %j.inc, %for.j.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.j ], [ %k.inc, %for.k.inc ]
+  %offset0 = add nsw i64 %i, 3
+  %subscript0 = mul i64 %offset0, %m
+  %offset1 = add nsw i64 %j, -4
+  %subscript1 = add i64 %offset1, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %offset2 = add nsw i64 %k, 7
+  %subscript = add i64 %subscript2, %offset2
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %osub = sub nsw i64 %o, 7
+  %k.exitcond = icmp eq i64 %k.inc, %osub
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %nsub = sub nsw i64 %n, 3
+  %i.exitcond = icmp eq i64 %i.inc, %nsub
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_nested_start_share_parameter.ll b/final/test/ScopInfo/multidim_nested_start_share_parameter.ll
new file mode 100644
index 0000000..76ca349
--- /dev/null
+++ b/final/test/ScopInfo/multidim_nested_start_share_parameter.ll
@@ -0,0 +1,81 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;
+;   for (long i = 0; i < n-13; i++)
+;     for (long j = 14; j < m; j++)
+;       for (long k = 0; k < o-17; k++) {
+;         A[i+3][j-4][k+7] = 1.0;
+;         A[i+13][j-14][k+17] = 11.0;
+;       }
+; }
+;
+; CHECK: Assumed Context:
+; CHECK:   {  :  }
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK: p2: %o
+; CHECK-NOT: p3
+;
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[3 + i0, 10 + i1, 7 + i2] };
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[13 + i0, i1, 17 + i2] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 14, %for.i ], [ %j.inc, %for.j.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.j ], [ %k.inc, %for.k.inc ]
+
+  %offset0 = add nsw i64 %i, 3
+  %subscript0 = mul i64 %offset0, %m
+  %offset1 = add nsw i64 %j, -4
+  %subscript1 = add i64 %offset1, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %offset2 = add nsw i64 %k, 7
+  %subscript3 = add i64 %subscript2, %offset2
+  %idx = getelementptr inbounds double* %A, i64 %subscript3
+  store double 1.0, double* %idx
+
+  %offset3 = add nsw i64 %i, 13
+  %subscript4 = mul i64 %offset3, %m
+  %offset4 = add nsw i64 %j, -14
+  %subscript5 = add i64 %offset4, %subscript4
+  %subscript6 = mul i64 %subscript5, %o
+  %offset5 = add nsw i64 %k, 17
+  %subscript7 = add i64 %subscript6, %offset5
+  %idx1 = getelementptr inbounds double* %A, i64 %subscript7
+  store double 11.0, double* %idx1
+
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %osub = sub nsw i64 %o, 17
+  %k.exitcond = icmp eq i64 %k.inc, %osub
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %nsub = sub nsw i64 %n, 13
+  %i.exitcond = icmp eq i64 %i.inc, %nsub
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_only_ivs_2d.ll b/final/test/ScopInfo/multidim_only_ivs_2d.ll
new file mode 100644
index 0000000..1c8b363
--- /dev/null
+++ b/final/test/ScopInfo/multidim_only_ivs_2d.ll
@@ -0,0 +1,51 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Derived from the following code:
+;
+; void foo(long n, long m, double A[n][m]) {
+;   for (long i = 0; i < n; i++)
+;     for (long j = 0; j < m; j++)
+;       A[i][j] = 1.0;
+; }
+
+; CHECK: Assumed Context:
+; CHECK:   [n, m] -> {  :  }
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK-NOT: p3
+
+; CHECK: Domain
+; CHECK:   [n, m] -> { Stmt_for_j[i0, i1] : i0 >= 0 and i0 <= -1 + n and i1 >= 0 and i1 <= -1 + m };
+; CHECK: Scattering
+; CHECK:   [n, m] -> { Stmt_for_j[i0, i1] -> scattering[i0, i1] };
+; CHECK: MustWriteAccess
+; CHECK:   [n, m] -> { Stmt_for_j[i0, i1] -> MemRef_A[i0, i1] };
+
+define void @foo(i64 %n, i64 %m, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  %tmp = mul nsw i64 %i, %m
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j ]
+  %vlaarrayidx.sum = add i64 %j, %tmp
+  %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum
+  store double 1.0, double* %arrayidx
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_only_ivs_3d.ll b/final/test/ScopInfo/multidim_only_ivs_3d.ll
new file mode 100644
index 0000000..6d682a7
--- /dev/null
+++ b/final/test/ScopInfo/multidim_only_ivs_3d.ll
@@ -0,0 +1,66 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;
+;   for (long i = 0; i < n; i++)
+;     for (long j = 0; j < m; j++)
+;       for (long k = 0; k < o; k++)
+;         A[i][j][k] = 1.0;
+; }
+
+; CHECK: Assumed Context:
+; CHECK:   [n, m, o] -> {  :  }
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK: p2: %o
+; CHECK-NOT: p3
+;
+; CHECK: Domain
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] : i0 >= 0 and i0 <= -1 + n and i1 >= 0 and i1 <= -1 + m and i2 >= 0 and i2 <= -1 + o };
+; CHECK: Scattering
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK: WriteAccess
+; CHECK:   [n, m, o] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[i0, i1, i2] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.j ], [ %k.inc, %for.k.inc ]
+  %subscript0 = mul i64 %i, %m
+  %subscript1 = add i64 %j, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %subscript = add i64 %subscript2, %k
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %k.exitcond = icmp eq i64 %k.inc, %o
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_only_ivs_3d_cast.ll b/final/test/ScopInfo/multidim_only_ivs_3d_cast.ll
new file mode 100644
index 0000000..2dd2f1b
--- /dev/null
+++ b/final/test/ScopInfo/multidim_only_ivs_3d_cast.ll
@@ -0,0 +1,81 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+
+; void foo(int n, int m, int o, double A[n][m][o]) {
+;
+;   for (int i = 0; i < n; i++)
+;     for (int j = 0; j < m; j++)
+;       for (int k = 0; k < o; k++)
+;         A[i][j][k] = 1.0;
+; }
+
+; We currently fail to get the relation between the 32 and 64 bit versions of
+; m and o, such that we generate unnecessary run-time checks. This is not a
+; correctness issue, but could be improved.
+
+; CHECK: Assumed Context:
+; CHECK:  [n, m, o, p_3, p_4] -> { : p_4 >= o and p_3 >= m }
+; CHECK: p0: %n
+; CHECK: p1: %m
+; CHECK: p2: %o
+; CHECK: p3: (zext i32 %m to i64)
+; CHECK: p4: (zext i32 %o to i64)
+; CHECK-NOT: p5
+
+; CHECK: Domain
+; CHECK:   [n, m, o, p_3, p_4] -> { Stmt_for_k[i0, i1, i2] : i0 >= 0 and i0 <= -1 + n and i1 >= 0 and i1 <= -1 + m and i2 >= 0 and i2 <= -1 + o };
+; CHECK: Scattering
+; CHECK:   [n, m, o, p_3, p_4] -> { Stmt_for_k[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK: WriteAccess
+; CHECK:   [n, m, o, p_3, p_4] -> { Stmt_for_k[i0, i1, i2] -> MemRef_A[i0, i1, i2] };
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i32 %n, i32 %m, i32 %o, double* %A) {
+entry:
+  %m_zext = zext i32 %m to i64
+  %n_zext = zext i32 %o to i64
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ %i.inc, %for.i.inc ], [ 0, %entry ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ %j.inc, %for.j.inc ], [ 0, %for.i ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ %k.inc, %for.k.inc ], [ 0, %for.j ]
+  %tmp = mul i64 %i, %m_zext
+  %tmp1 = trunc i64 %j to i32
+  %tmp2 = trunc i64 %i to i32
+  %mul.us.us = mul nsw i32 %tmp1, %tmp2
+  %tmp.us.us = add i64 %j, %tmp
+  %tmp17.us.us = mul i64 %tmp.us.us, %n_zext
+  %subscript = add i64 %tmp17.us.us, %k
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.k.inc
+
+for.k.inc:
+  %k.inc = add i64 %k, 1
+  %k.inc.trunc = trunc i64 %k.inc to i32
+  %k.exitcond = icmp eq i32 %k.inc.trunc, %o
+  br i1 %k.exitcond, label %for.j.inc, label %for.k
+
+for.j.inc:
+  %j.inc = add i64 %j, 1
+  %j.inc.trunc = trunc i64 %j.inc to i32
+  %j.exitcond = icmp eq i32 %j.inc.trunc, %m
+  br i1 %j.exitcond, label %for.i.inc, label %for.j
+
+for.i.inc:
+  %i.inc = add i64 %i, 1
+  %i.inc.trunc = trunc i64 %i.inc to i32
+  %i.exitcond = icmp eq i32 %i.inc.trunc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_only_ivs_3d_reverse.ll b/final/test/ScopInfo/multidim_only_ivs_3d_reverse.ll
new file mode 100644
index 0000000..babe759
--- /dev/null
+++ b/final/test/ScopInfo/multidim_only_ivs_3d_reverse.ll
@@ -0,0 +1,71 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-delinearize < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This test case checks for array access functions where the order in which the
+; loop ivs appear in the array subscript does not follow the order of the
+; the loops in which they are defined. This (very common) case caused problems
+; in the delinearization pass.
+;
+; void foo(long n, long m, long o, double A[n][m][o]) {
+;
+;   for (long i = 0; i < n; i++)
+;     for (long k = 0; k < o; k++)
+;       for (long j = 0; j < m; j++)
+;         A[i][j][k] = 1.0;
+; }
+
+; CHECK: Assumed Context:
+; CHECK:   {  :  }
+; CHECK: p0: %n
+; CHECK: p1: %o
+; CHECK: p2: %m
+; CHECK-NOT: p3
+;
+; CHECK: Domain
+; CHECK:  [n, o, m] -> { Stmt_for_j[i0, i1, i2] : i0 >= 0 and i0 <= -1 + n and i1 >= 0 and i1 <= -1 + o and i2 >= 0 and i2 <= -1 + m };
+; CHECK: Scattering
+; CHECK:   [n, o, m] -> { Stmt_for_j[i0, i1, i2] -> scattering[i0, i1, i2] };
+; CHECK: WriteAccess
+; CHECK:   [n, o, m] -> { Stmt_for_j[i0, i1, i2] -> MemRef_A[i0, i2, i1] };
+
+define void @foo(i64 %n, i64 %m, i64 %o, double* %A) {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ]
+  br label %for.k
+
+for.k:
+  %k = phi i64 [ 0, %for.i ], [ %k.inc, %for.k.inc ]
+  br label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.k ], [ %j.inc, %for.j.inc ]
+  %subscript0 = mul i64 %i, %m
+  %subscript1 = add i64 %j, %subscript0
+  %subscript2 = mul i64 %subscript1, %o
+  %subscript = add i64 %subscript2, %k
+  %idx = getelementptr inbounds double* %A, i64 %subscript
+  store double 1.0, double* %idx
+  br label %for.j.inc
+
+for.j.inc:
+  %j.inc = add nsw i64 %j, 1
+  %j.exitcond = icmp eq i64 %j.inc, %m
+  br i1 %j.exitcond, label %for.k.inc, label %for.j
+
+for.k.inc:
+  %k.inc = add nsw i64 %k, 1
+  %k.exitcond = icmp eq i64 %k.inc, %o
+  br i1 %k.exitcond, label %for.i.inc, label %for.k
+
+for.i.inc:
+  %i.inc = add nsw i64 %i, 1
+  %i.exitcond = icmp eq i64 %i.inc, %n
+  br i1 %i.exitcond, label %end, label %for.i
+
+end:
+  ret void
+}
diff --git a/final/test/ScopInfo/multidim_single_and_multidim_array.ll b/final/test/ScopInfo/multidim_single_and_multidim_array.ll
new file mode 100644
index 0000000..1190b20
--- /dev/null
+++ b/final/test/ScopInfo/multidim_single_and_multidim_array.ll
@@ -0,0 +1,68 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine -analyze < %s | FileCheck %s --check-prefix=NONAFFINE
+; RUN: opt %loadPolly -polly-scops -polly-delinearize -analyze < %s | FileCheck %s --check-prefix=DELIN
+; RUN: opt %loadPolly -polly-scops -polly-delinearize -polly-allow-nonaffine -analyze < %s | FileCheck %s --check-prefix=DELIN
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; void single-and-multi-dimensional-array(long n,float X[n][n]) {
+;  for (long i1 = 0; i1 < n; i1++)
+;    X[i1][0] = 1;
+;
+;  for (long i2 = 0; i2 < n; i2++)
+;    X[n-1][i2] = 1;
+; }
+;
+; In previous versions of Polly, the second access was detected as single
+; dimensional access whereas the first one was detected as multi-dimensional.
+; This test case checks that we now consistently delinearize the array accesses.
+
+; CHECK-NOT: Stmt_for_i_1
+
+; NONAFFINE: p0: %n
+; NONAFFINE: p1: (4 * (-1 + %n) * %n)
+; NONAFFINE: Statements {
+; NONAFFINE:   Stmt_for_i_1
+; NONAFFINE:         MayWriteAccess :=   [Reduction Type: NONE]
+; NONAFFINE:             [n, p_1] -> { Stmt_for_i_1[i0] -> MemRef_X[o0] };
+; NONAFFINE:   Stmt_for_i_2
+; NONAFFINE:         MustWriteAccess :=  [Reduction Type: NONE]
+; NONAFFINE:             [n, p_1] -> { Stmt_for_i_2[i0] -> MemRef_X[o0] : 4o0 = p_1 + 4i0 };
+
+; DELIN: Stmt_for_i_1
+; DELIN:   MustWriteAccess :=
+; DELIN:      [n] -> { Stmt_for_i_1[i0] -> MemRef_X[i0, 0] };
+; DELIN: Stmt_for_i_2
+; DELIN:   MustWriteAccess :=
+; DELIN:      [n] -> { Stmt_for_i_2[i0] -> MemRef_X[-1 + n, i0] };
+
+define void @single-and-multi-dimensional-array(i64 %n, float* %X) {
+entry:
+  br label %for.i.1
+
+for.i.1:
+  %indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %for.i.1 ]
+  %offset.1 = mul i64 %n, %indvar.1
+  %arrayidx.1 = getelementptr float* %X, i64 %offset.1
+  store float 1.000000e+00, float* %arrayidx.1
+  %indvar.next.1 = add nsw i64 %indvar.1, 1
+  %exitcond.1 = icmp ne i64 %indvar.next.1, %n
+  br i1 %exitcond.1, label %for.i.1, label %next
+
+next:
+  br label %for.i.2
+
+for.i.2:
+  %indvar.2 = phi i64 [ 0, %next ], [ %indvar.next.2, %for.i.2 ]
+  %offset.2.a = add i64 %n, -1
+  %offset.2.b = mul i64 %n, %offset.2.a
+  %offset.2.c = add i64 %offset.2.b, %indvar.2
+  %arrayidx.2 = getelementptr float* %X, i64 %offset.2.c
+  store float 1.000000e+00, float* %arrayidx.2
+  %indvar.next.2 = add nsw i64 %indvar.2, 1
+  %exitcond.2 = icmp ne i64 %indvar.next.2, %n
+  br i1 %exitcond.2, label %for.i.2, label %exit
+
+exit:
+  ret void
+}
diff --git a/final/test/ScopInfo/non_affine_access.ll b/final/test/ScopInfo/non_affine_access.ll
new file mode 100644
index 0000000..f06ad6f
--- /dev/null
+++ b/final/test/ScopInfo/non_affine_access.ll
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -polly-delinearize -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine -analyze < %s | FileCheck %s -check-prefix=NONAFFINE
+; RUN: opt %loadPolly -polly-scops -polly-delinearize -polly-allow-nonaffine -analyze < %s | FileCheck %s -check-prefix=NONAFFINE
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.7.2"
+
+; void foo(long *A) {
+;   for (i = 0; i < 1024; i++)
+;     A[i * i] = i;
+;
+
+define void @foo(i64 *%A) nounwind uwtable ssp {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %indvar = phi i64 [ 0, %entry.split ], [ %indvar.next, %for.body ]
+  %mul = mul nsw i64 %indvar, %indvar
+  %arrayidx = getelementptr inbounds i64* %A, i64 %mul
+  store i64 %indvar, i64* %arrayidx, align 4
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp ne i64 %indvar.next, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+; CHECK-NOT: Stmt_for_body
+; NONAFFINE: { Stmt_for_body[i0] -> MemRef_A[o0] };
diff --git a/final/test/ScopInfo/non_affine_parametric_loop.ll b/final/test/ScopInfo/non_affine_parametric_loop.ll
new file mode 100644
index 0000000..d78f18c
--- /dev/null
+++ b/final/test/ScopInfo/non_affine_parametric_loop.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze -polly-allow-nonaffine < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; void foo(long n, double A[], int INDEX[]) {
+;   for (long i = 0; i < n; i++)
+;     A[INDEX[i]] = i;
+; }
+
+define void @foo(i64 %n, double* noalias %A, i64* noalias %INDEX) {
+entry:
+  br label %for.body
+
+for.body:
+  %i = phi i64 [ %inc, %for.body ], [ 0, %entry ]
+  %arrayidx = getelementptr inbounds i64* %INDEX, i64 %i
+  %val = load i64* %arrayidx
+  %arrayidx1 = getelementptr inbounds double* %A, i64 %val
+  store double 1.0, double* %arrayidx1
+  %inc = add nsw i64 %i, 1
+  %exitcond = icmp eq i64 %inc, %n
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+; CHECK: p0: %n
+
+; CHECK: Domain
+; CHECK:   [n] -> { Stmt_for_body[i0] : i0 >= 0 and i0 <= -1 + n };
+; CHECK: Scattering
+; CHECK:   [n] -> { Stmt_for_body[i0] -> scattering[i0] };
+; CHECK: ReadAccess
+; CHECK:   [n] -> { Stmt_for_body[i0] -> MemRef_INDEX[i0] };
+; CHECK: WriteAccess
+; CHECK:   [n] -> { Stmt_for_body[i0] -> MemRef_A[o0] };
diff --git a/final/test/ScopInfo/parameter_product.ll b/final/test/ScopInfo/parameter_product.ll
new file mode 100644
index 0000000..2bd9793
--- /dev/null
+++ b/final/test/ScopInfo/parameter_product.ll
@@ -0,0 +1,31 @@
+; RUN: opt %loadPolly -polly-scops -analyze -S < %s | FileCheck %s
+;
+; int n, m;
+; void foo(char* __restrict a)
+; {
+;   for (int i = 0; i < n*m; ++i)
+;     a[i]=2;
+; }
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i8* noalias %a, i32 %param_n, i32 %param_m) {
+entry:
+  %mul = mul nsw i32 %param_m, %param_n
+  %cmp1 = icmp sgt i32 %mul, 0
+  br i1 %cmp1, label %for.body, label %for.end
+
+for.body:
+  %i.02 = phi i32 [ %add, %for.body ], [ 0, %entry ]
+  %arrayidx = getelementptr inbounds i8* %a, i64 0
+  store i8 2, i8* %arrayidx, align 1
+  %add = add nsw i32 %i.02, 1
+  %cmp = icmp slt i32 %add, %mul
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+
+; CHECK: p0: (%param_n * %param_m)
+
diff --git a/final/test/ScopInfo/phi_not_grouped_at_top.ll b/final/test/ScopInfo/phi_not_grouped_at_top.ll
new file mode 100644
index 0000000..49613ab
--- /dev/null
+++ b/final/test/ScopInfo/phi_not_grouped_at_top.ll
@@ -0,0 +1,29 @@
+; RUN: opt %loadPolly -polly-prepare  -analyze  < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+declare i32 @funa() align 2
+
+declare i32 @generic_personality_v0(i32, i64, i8*, i8*)
+
+define void @funb() align 2 {
+entry:
+  br label %bb117
+
+bb117:                                            ; preds = %bb56
+  %0 = invoke i32 @funa()
+          to label %bb121 unwind label %invcont118 ; <%struct.btHullTriangle*> [#uses=1]
+
+invcont118:                                       ; preds = %bb117
+  %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality_v0 cleanup catch i32* null
+  br label %bb121
+
+bb121:                                            ; preds = %bb120, %invcont118
+  %iftmp.82.0 = phi i32 [ 0, %bb117 ], [ 1, %invcont118 ] ; <i8> [#uses=1]
+  %te.1 = phi i32 [ undef, %invcont118 ], [ %0, %bb117 ] ;
+  %cnd = icmp ne i32 %iftmp.82.0, %te.1          ; <i1> [#uses=1]
+  br label %return
+
+return:                                           ; preds = %entry
+  ret void
+}
diff --git a/final/test/ScopInfo/phi_with_invoke_edge.ll b/final/test/ScopInfo/phi_with_invoke_edge.ll
new file mode 100644
index 0000000..8fb74e6
--- /dev/null
+++ b/final/test/ScopInfo/phi_with_invoke_edge.ll
@@ -0,0 +1,27 @@
+; RUN: opt %loadPolly -polly-prepare -polly-detect  -analyze  < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-linux-gnu"
+
+declare i32 @generic_personality_v0(i32, i64, i8*, i8*)
+
+define i16 @v() {
+entry:
+  br i1 undef, label %bb16, label %invcont12
+
+invcont12:                                        ; preds = %invcont11
+  %a = invoke i16 @v() to label %return unwind label %lpad22   ; <i16*> [#uses=1]
+
+bb16:                                             ; preds = %bb7
+  br i1 undef, label %bb9, label %return
+
+return:                                           ; preds = %bb16, %invcont12
+  %b = phi i16 [ %a, %invcont12 ], [ 0, %bb16 ] ; <i16*> [#uses=1]
+  ret i16 %b
+
+bb9:                                             ; preds = %bb3
+  ret i16 0
+
+lpad22:                                           ; preds = %invcont12
+  %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality_v0 cleanup catch i32* null
+  unreachable
+}
diff --git a/final/test/ScopInfo/reduction_alternating_base.ll b/final/test/ScopInfo/reduction_alternating_base.ll
new file mode 100644
index 0000000..ce98f01
--- /dev/null
+++ b/final/test/ScopInfo/reduction_alternating_base.ll
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; FIXME: We cannot detect this SCoP yet but as soon as we can we should check
+;        that the reduction is detected!
+;
+; CHECK-NOT: Scattering
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i % 2] += i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %rem = srem i32 %i.0, 2
+  %arrayidx = getelementptr inbounds i32* %A, i32 %rem
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  store i32 %add, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll b/final/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll
new file mode 100644
index 0000000..42d768e
--- /dev/null
+++ b/final/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Reduction Type: NONE
+;
+;    int c, d;
+;    void f(int *sum) {
+;      for (int i = 0; i < 1024; i++)
+;        *sum = c + d;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+@c = common global i32 0, align 4
+@d = common global i32 0, align 4
+
+define void @loads_outside_scop(i32* %sum) {
+entry:
+  %tmp = load i32* @c, align 4
+  %tmp1 = load i32* @d, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %add = add nsw i32 %tmp, %tmp1
+  store i32 %add, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+
+define void @binop_outside_scop(i32* %sum) {
+entry:
+  %tmp = load i32* @c, align 4
+  %tmp1 = load i32* @d, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  store i32 %add, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_disabled_multiplicative.ll b/final/test/ScopInfo/reduction_disabled_multiplicative.ll
new file mode 100644
index 0000000..5e32129
--- /dev/null
+++ b/final/test/ScopInfo/reduction_disabled_multiplicative.ll
@@ -0,0 +1,52 @@
+; RUN: opt -basicaa %loadPolly -polly-scops -analyze -polly-disable-multiplicative-reductions < %s | FileCheck %s
+;
+; CHECK: ReadAccess :=       [Reduction Type: +
+; CHECK:     { Stmt_for_body[i0] -> MemRef_sum[0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: +
+; CHECK:     { Stmt_for_body[i0] -> MemRef_sum[0] };
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_prod[0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_prod[0] };
+;
+; int sum, prod;
+; 
+; void f() {
+;   int i;
+;   for (int i = 0; i < 100; i++) {
+;     sum += i * 3;
+;     prod *= (i + 3);
+;   }
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+@sum = common global i32 0, align 4
+@prod = common global i32 0, align 4
+
+define void @f() #0 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i1.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i1.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %mul = mul nsw i32 %i1.0, 3
+  %tmp = load i32* @sum, align 4
+  %add = add nsw i32 %tmp, %mul
+  store i32 %add, i32* @sum, align 4
+  %add2 = add nsw i32 %i1.0, 3
+  %tmp1 = load i32* @prod, align 4
+  %mul3 = mul nsw i32 %tmp1, %add2
+  store i32 %mul3, i32* @prod, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i1.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_escaping_intermediate.ll b/final/test/ScopInfo/reduction_escaping_intermediate.ll
new file mode 100644
index 0000000..2c4f74c
--- /dev/null
+++ b/final/test/ScopInfo/reduction_escaping_intermediate.ll
@@ -0,0 +1,62 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+;
+; void f(int N, int * restrict sums, int * restrict escape) {
+;   int i, j;
+;   for (i = 0; i < 1024; i++) {
+;     for (j = 0; j < 1024; j++) {
+;       sums[i] += 5;
+;       escape[N - i + j] = sums[i];
+;     }
+;   }
+; }
+;
+; CHECK: Reduction Type: NONE
+; CHECK: sums
+; CHECK: Reduction Type: NONE
+; CHECK: sums
+; CHECK: Reduction Type: NONE
+; CHECK: escape
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32 %N, i32* noalias %sums, i32* noalias %escape) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc7, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc8, %for.inc7 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end9
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sums, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 5
+  store i32 %add, i32* %arrayidx, align 4
+  %sub = sub nsw i32 %N, %i.0
+  %add5 = add nsw i32 %sub, %j.0
+  %arrayidx6 = getelementptr inbounds i32* %escape, i32 %add5
+  store i32 %add, i32* %arrayidx6, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc7
+
+for.inc7:                                         ; preds = %for.end
+  %inc8 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end9:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_escaping_intermediate_2.ll b/final/test/ScopInfo/reduction_escaping_intermediate_2.ll
new file mode 100644
index 0000000..2d8c09e
--- /dev/null
+++ b/final/test/ScopInfo/reduction_escaping_intermediate_2.ll
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+;
+; void f(int N, int * restrict sums, int * restrict escape) {
+;   int i, j;
+;   for (i = 0; i < 1024; i++) {
+;     for (j = 0; j < 1024; j++) {
+;       sums[i] += 5;
+;       escape[N-j] = escape[i] + sums[i-1];
+;     }
+;   }
+; }
+;
+; CHECK: Reduction Type: NONE
+; CHECK: sums
+; CHECK: Reduction Type: NONE
+; CHECK: sums
+; CHECK: Reduction Type: NONE
+; CHECK: escape
+; CHECK: Reduction Type: NONE
+; CHECK: sums
+; CHECK: Reduction Type: NONE
+; CHECK: escape
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32 %N, i32* noalias %sums, i32* noalias %escape) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc11, %for.inc10 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sums, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 5
+  store i32 %add, i32* %arrayidx, align 4
+  %arrayidx4 = getelementptr inbounds i32* %escape, i32 %i.0
+  %tmp2 = load i32* %arrayidx4, align 4
+  %sub = add nsw i32 %i.0, -1
+  %arrayidx5 = getelementptr inbounds i32* %sums, i32 %sub
+  %tmp3 = load i32* %arrayidx5, align 4
+  %add6 = add nsw i32 %tmp2, %tmp3
+  %sub7 = sub nsw i32 %N, %i.0
+  %add8 = add nsw i32 %sub7, %j.0
+  %arrayidx9 = getelementptr inbounds i32* %escape, i32 %add8
+  store i32 %add6, i32* %arrayidx9, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end
+  %inc11 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_invalid_different_operators.ll b/final/test/ScopInfo/reduction_invalid_different_operators.ll
new file mode 100644
index 0000000..9f477fe
--- /dev/null
+++ b/final/test/ScopInfo/reduction_invalid_different_operators.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+;
+; int f() {
+;   int i, sum = 0, sth = 0;
+;   for (i = 0; i < 1024; i++) {
+;     sum += 5;
+;     sth = sth + sth * sth + sth;
+;     sum *= 5;
+;   }
+;   return sum + sth;
+; }
+;
+; CHECK-NOT: Reduction Type: +
+; CHECK-NOT: Reduction Type: *
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define i32 @f() {
+entry:
+  %sum.0 = alloca i32
+  %sth.0 = alloca i32
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  store i32 0, i32* %sum.0
+  store i32 0, i32* %sth.0
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entry.split
+  %i.0 = phi i32 [ 0, %entry.split ], [ %inc, %for.cond ]
+  %sth.0.reload = load i32* %sth.0
+  %sum.0.reload = load i32* %sum.0
+  %exitcond = icmp ne i32 %i.0, 1024
+  %mul = mul nsw i32 %sth.0.reload, %sth.0.reload
+  %add1 = add nsw i32 %sth.0.reload, %mul
+  %tmp = mul i32 %sum.0.reload, 5
+  store i32 %tmp, i32* %sum.0
+  %sum.1.reload = load i32* %sum.0
+  %mul3 = add i32 %sum.1.reload, 25
+  %add2 = add nsw i32 %add1, %sth.0.reload
+  %inc = add nsw i32 %i.0, 1
+  store i32 %mul3, i32* %sum.0
+  store i32 %add2, i32* %sth.0
+  br i1 %exitcond, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.cond
+  %sum.0.reload.2 = load i32* %sum.0
+  %sth.0.reload.2 = load i32* %sth.0
+  %add4 = add nsw i32 %sum.0.reload.2, %sth.0.reload.2
+  ret i32 %add4
+}
diff --git a/final/test/ScopInfo/reduction_invalid_overlapping_accesses.ll b/final/test/ScopInfo/reduction_invalid_overlapping_accesses.ll
new file mode 100644
index 0000000..2c765f7
--- /dev/null
+++ b/final/test/ScopInfo/reduction_invalid_overlapping_accesses.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; void f(int *sums) {
+;   int i, j;
+;   for (i = 0; i < 1024; i++) {
+;     for (j = 0; j < 1024; j++) {
+;       sums[i] += 5;
+;       sums[i+10] *= 5;
+;     }
+;   }
+; }
+;
+; CHECK-NOT: Reduction Type: +
+; CHECK-NOT: Reduction Type: *
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sums) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sums, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 5
+  store i32 %add, i32* %arrayidx, align 4
+  %add4 = add nsw i32 %i.0, 10
+  %arrayidx5 = getelementptr inbounds i32* %sums, i32 %add4
+  %tmp2 = load i32* %arrayidx5, align 4
+  %mul = mul nsw i32 %tmp2, 5
+  store i32 %mul, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_multiple_loops_array_sum.ll b/final/test/ScopInfo/reduction_multiple_loops_array_sum.ll
new file mode 100644
index 0000000..d61f521
--- /dev/null
+++ b/final/test/ScopInfo/reduction_multiple_loops_array_sum.ll
@@ -0,0 +1,78 @@
+; RUN: opt -basicaa %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Stmt_for_body
+; CHECK: Reduction Type: *
+; CHECK: MemRef_sum
+; CHECK: Reduction Type: *
+; CHECK: MemRef_sum
+; CHECK: Stmt_for_body3
+; CHECK: Reduction Type: NONE
+; CHECK: MemRef_A
+; CHECK: Reduction Type: +
+; CHECK: MemRef_sum
+; CHECK: Reduction Type: +
+; CHECK: MemRef_sum
+; CHECK: Stmt_for_end
+; CHECK: Reduction Type: *
+; CHECK: MemRef_sum
+; CHECK: Reduction Type: *
+; CHECK: MemRef_sum
+;
+; void f(int *restrict A, int *restrict sum) {
+;   int i, j;
+;   for (i = 0; i < 100; i++) {
+;     *sum *= 7;
+;     for (j = 0; j < 100; j++) {
+;       *sum += A[i + j];
+;     }
+;     *sum *= 5;
+;   }
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* noalias %A, i32* noalias %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %exitcond1 = icmp ne i32 %i.0, 100
+  br i1 %exitcond1, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  %tmp = load i32* %sum, align 4
+  %mul = mul nsw i32 %tmp, 7
+  store i32 %mul, i32* %sum, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 100
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %add = add nsw i32 %i.0, %j.0
+  %arrayidx = getelementptr inbounds i32* %A, i32 %add
+  %tmp2 = load i32* %arrayidx, align 4
+  %tmp3 = load i32* %sum, align 4
+  %add4 = add nsw i32 %tmp3, %tmp2
+  store i32 %add4, i32* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  %tmp4 = load i32* %sum, align 4
+  %mul5 = mul nsw i32 %tmp4, 5
+  store i32 %mul5, i32* %sum, align 4
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll b/final/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll
new file mode 100644
index 0000000..19147fe
--- /dev/null
+++ b/final/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll
@@ -0,0 +1,72 @@
+; RUN: opt -basicaa %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Stmt_for_body
+; CHECK: Reduction Type: NONE
+; CHECK: MemRef_sum_04
+; CHECK: Reduction Type: NONE
+; CHECK: MemRef_sum_12
+; CHECK: Stmt_for_inc
+; CHECK: Reduction Type: +
+; CHECK: MemRef_sum_12
+; CHECK: Reduction Type: NONE
+; CHECK: MemRef_A
+; CHECK: Reduction Type: +
+; CHECK: MemRef_sum_12
+; CHECK: Stmt_for_inc5
+; CHECK: Reduction Type: NONE
+; CHECK: MemRef_sum_12
+; CHECK: Reduction Type: NONE
+; CHECK: MemRef_sum_04
+;
+; int f(int * __restrict__ A) {
+;   int i, j, sum = 1;
+;   for (i = 0; i < 100; i++) {
+;     sum *= 7;
+;     for (j = 0; j < 100; j++) {
+;       sum += A[i+j];
+;     }
+;   }
+;   return sum;
+; }
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define i32 @f(i32* noalias %A) {
+entry:
+  %sum.04.reg2mem = alloca i32
+  %sum.12.reg2mem = alloca i32
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  store i32 0, i32* %sum.04.reg2mem
+  br label %for.body
+
+for.body:                                         ; preds = %for.inc5, %entry.split
+  %indvars.iv23 = phi i64 [ 0, %entry.split ], [ %3, %for.inc5 ]
+  %sum.04.reload = load i32* %sum.04.reg2mem
+  %mul = mul nsw i32 %sum.04.reload, 7
+  store i32 %mul, i32* %sum.12.reg2mem
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.inc, %for.body
+  %indvars.iv1 = phi i64 [ 0, %for.body ], [ %1, %for.inc ]
+  %sum.12.reload = load i32* %sum.12.reg2mem
+  %0 = add i64 %indvars.iv23, %indvars.iv1
+  %arrayidx = getelementptr i32* %A, i64 %0
+  %tmp5 = load i32* %arrayidx, align 4
+  %add4 = add nsw i32 %tmp5, %sum.12.reload
+  %1 = add nuw nsw i64 %indvars.iv1, 1
+  %exitcond1 = icmp eq i64 %1, 100
+  store i32 %add4, i32* %sum.12.reg2mem
+  br i1 %exitcond1, label %for.inc5, label %for.inc
+
+for.inc5:                                         ; preds = %for.inc
+  %2 = load i32* %sum.12.reg2mem
+  %3 = add nuw nsw i64 %indvars.iv23, 1
+  %exitcond2 = icmp eq i64 %3, 100
+  store i32 %2, i32* %sum.04.reg2mem
+  br i1 %exitcond2, label %for.end7, label %for.body
+
+for.end7:                                         ; preds = %for.inc5
+  %4 = load i32* %sum.04.reg2mem
+  ret i32 %4
+}
diff --git a/final/test/ScopInfo/reduction_multiple_simple_binary.ll b/final/test/ScopInfo/reduction_multiple_simple_binary.ll
new file mode 100644
index 0000000..c701ed1
--- /dev/null
+++ b/final/test/ScopInfo/reduction_multiple_simple_binary.ll
@@ -0,0 +1,98 @@
+; RUN: opt -basicaa %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_A[1 + i0] };
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_A[i0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_first[0] };
+; CHECK: ReadAccess :=       [Reduction Type: +
+; CHECK:     { Stmt_for_body[i0] -> MemRef_sum[0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: +
+; CHECK:     { Stmt_for_body[i0] -> MemRef_sum[0] };
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_A[-1 + i0] };
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_A[i0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_middle[0] };
+; CHECK: ReadAccess :=       [Reduction Type: *
+; CHECK:     { Stmt_for_body[i0] -> MemRef_prod[0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: *
+; CHECK:     { Stmt_for_body[i0] -> MemRef_prod[0] };
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_A[-1 + i0] };
+; CHECK: ReadAccess :=       [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_A[1 + i0] };
+; CHECK: MustWriteAccess :=  [Reduction Type: NONE
+; CHECK:     { Stmt_for_body[i0] -> MemRef_last[0] };
+;
+; int first, sum, middle, prod, last;
+;
+; void f(int * restrict A) {
+;   int i;
+;   for (int i = 0; i < 100; i++) {
+;     first = A[i+1] + A[i];
+;     sum += i * 3;
+;     middle = A[i-1] + A[i];
+;     prod *= (i + 3);
+;     last = A[i-1] + A[i+1];
+;   }
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+@first = common global i32 0, align 4
+@sum = common global i32 0, align 4
+@middle = common global i32 0, align 4
+@prod = common global i32 0, align 4
+@last = common global i32 0, align 4
+
+define void @f(i32* noalias %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i1.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i1.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %add = add nsw i32 %i1.0, 1
+  %arrayidx = getelementptr inbounds i32* %A, i32 %add
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i32 %i1.0
+  %tmp1 = load i32* %arrayidx2, align 4
+  %add3 = add nsw i32 %tmp, %tmp1
+  store i32 %add3, i32* @first, align 4
+  %mul = mul nsw i32 %i1.0, 3
+  %tmp2 = load i32* @sum, align 4
+  %add4 = add nsw i32 %tmp2, %mul
+  store i32 %add4, i32* @sum, align 4
+  %sub = add nsw i32 %i1.0, -1
+  %arrayidx5 = getelementptr inbounds i32* %A, i32 %sub
+  %tmp3 = load i32* %arrayidx5, align 4
+  %arrayidx6 = getelementptr inbounds i32* %A, i32 %i1.0
+  %tmp4 = load i32* %arrayidx6, align 4
+  %add7 = add nsw i32 %tmp3, %tmp4
+  store i32 %add7, i32* @middle, align 4
+  %add8 = add nsw i32 %i1.0, 3
+  %tmp5 = load i32* @prod, align 4
+  %mul9 = mul nsw i32 %tmp5, %add8
+  store i32 %mul9, i32* @prod, align 4
+  %sub10 = add nsw i32 %i1.0, -1
+  %arrayidx11 = getelementptr inbounds i32* %A, i32 %sub10
+  %tmp6 = load i32* %arrayidx11, align 4
+  %add12 = add nsw i32 %i1.0, 1
+  %arrayidx13 = getelementptr inbounds i32* %A, i32 %add12
+  %tmp7 = load i32* %arrayidx13, align 4
+  %add14 = add nsw i32 %tmp6, %tmp7
+  store i32 %add14, i32* @last, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i1.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_non_overlapping_chains.ll b/final/test/ScopInfo/reduction_non_overlapping_chains.ll
new file mode 100644
index 0000000..e9399ba
--- /dev/null
+++ b/final/test/ScopInfo/reduction_non_overlapping_chains.ll
@@ -0,0 +1,60 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Reduction Type: +
+; CHECK: Reduction Type: +
+; CHECK: Reduction Type: *
+; CHECK: Reduction Type: *
+;
+; void f(int *sums) {
+;   for (int i = 0; i < 1024; i++) {
+;     for (int j = 0; j < 1024; j++) {
+;       sums[i] += 5;
+;       sums[i+1024] *= 5;
+;     }
+;   }
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sums) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %exitcond1 = icmp ne i32 %i.0, 1024
+  br i1 %exitcond1, label %for.body, label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 1024
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %arrayidx = getelementptr inbounds i32* %sums, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, 5
+  store i32 %add, i32* %arrayidx, align 4
+  %add4 = add nsw i32 %i.0, 1024
+  %arrayidx5 = getelementptr inbounds i32* %sums, i32 %add4
+  %tmp2 = load i32* %arrayidx5, align 4
+  %mul = mul nsw i32 %tmp2, 5
+  store i32 %mul, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_only_reduction_like_access.ll b/final/test/ScopInfo/reduction_only_reduction_like_access.ll
new file mode 100644
index 0000000..f0009ae
--- /dev/null
+++ b/final/test/ScopInfo/reduction_only_reduction_like_access.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Reduction Type: +
+;
+; void f(int *sum) {
+;   for (int i = 0; i < 100; i++)
+;     sum[i] = sum[99-i] + i;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %sub = sub nsw i32 99, %i.0
+  %arrayidx = getelementptr inbounds i32* %sum, i32 %sub
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %i.0
+  %arrayidx1 = getelementptr inbounds i32* %sum, i32 %i.0
+  store i32 %add, i32* %arrayidx1, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_simple_fp.ll b/final/test/ScopInfo/reduction_simple_fp.ll
new file mode 100644
index 0000000..7918fcb
--- /dev/null
+++ b/final/test/ScopInfo/reduction_simple_fp.ll
@@ -0,0 +1,64 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Function: f_no_fast_math
+; CHECK: Reduction Type: NONE
+; CHECK: Function: f_fast_math
+; CHECK: Reduction Type: +
+;
+; void f(float *sum) {
+;   for (int i = 0; i < 100; i++)
+;     *sum += 3.41 * i;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f_no_fast_math(float* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %conv = sitofp i32 %i.0 to float
+  %pi = fptrunc double 3.41 to float
+  %mul = fmul float %conv, %pi
+  %tmp = load float* %sum, align 4
+  %add = fadd float %tmp, %mul
+  store float %add, float* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+define void @f_fast_math(float* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %conv = sitofp i32 %i.0 to float
+  %pi = fptrunc double 3.41 to float
+  %mul = fmul fast float %conv, %pi
+  %tmp = load float* %sum, align 4
+  %add = fadd fast float %tmp, %mul
+  store float %add, float* %sum, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_simple_w_constant.ll b/final/test/ScopInfo/reduction_simple_w_constant.ll
new file mode 100644
index 0000000..2cecb4d
--- /dev/null
+++ b/final/test/ScopInfo/reduction_simple_w_constant.ll
@@ -0,0 +1,26 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Reduction Type: +
+;
+; void f(int *sum) {
+;   for (int i = 0; i <= 100; i++)
+;     sum += 3;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entry
+  %i1.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
+  %sum.reload = load i32* %sum
+  %add = add nsw i32 %sum.reload, 3
+  %inc = add nsw i32 %i1.0, 1
+  store i32 %add, i32* %sum
+  %cmp = icmp slt i32 %i1.0, 100
+  br i1 %cmp, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_simple_w_iv.ll b/final/test/ScopInfo/reduction_simple_w_iv.ll
new file mode 100644
index 0000000..982983c
--- /dev/null
+++ b/final/test/ScopInfo/reduction_simple_w_iv.ll
@@ -0,0 +1,27 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Reduction Type: +
+;
+; void f(int* sum) {
+;   for (int i = 0; i <= 100; i++)
+;     sum += i * 3;
+; }
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %sum) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entr
+  %i1.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
+  %sum.reload = load i32* %sum
+  %mul = mul nsw i32 %i1.0, 3
+  %add = add nsw i32 %sum.reload, %mul
+  %inc = add nsw i32 %i1.0, 1
+  store i32 %add, i32* %sum
+  %cmp = icmp slt i32 %i1.0, 100
+  br i1 %cmp, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/reduction_two_identical_reads.ll b/final/test/ScopInfo/reduction_two_identical_reads.ll
new file mode 100644
index 0000000..1d71d7d
--- /dev/null
+++ b/final/test/ScopInfo/reduction_two_identical_reads.ll
@@ -0,0 +1,66 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK: Reduction Type: NONE
+;
+; Check that we do not mark these accesses as reduction like.
+; We do this for the case the loads are modelt with the same LLVM-IR value and
+; for the case there are different LLVM-IR values.
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = A[i] + A[i];
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f_one_load_case(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %add = add nsw i32 %tmp, %tmp
+  %arrayidx2 = getelementptr inbounds i32* %A, i32 %i.0
+  store i32 %add, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+define void @f_two_loads_case(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32* %A, i32 %i.0
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidxCopy = getelementptr inbounds i32* %A, i32 %i.0
+  %tmpCopy = load i32* %arrayidxCopy, align 4
+  %add = add nsw i32 %tmp, %tmpCopy
+  %arrayidx2 = getelementptr inbounds i32* %A, i32 %i.0
+  store i32 %add, i32* %arrayidx2, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
diff --git a/final/test/ScopInfo/run-time-check-many-parameters.ll b/final/test/ScopInfo/run-time-check-many-parameters.ll
new file mode 100644
index 0000000..65971b4
--- /dev/null
+++ b/final/test/ScopInfo/run-time-check-many-parameters.ll
@@ -0,0 +1,130 @@
+; RUN: opt %loadPolly -polly-scops -polly-code-generator=isl -analyze < %s | FileCheck %s
+;
+; A valid Scop would print the list of it's statements, we check that we do not
+; see that list.
+;
+; CHECK-NOT: Statements
+;
+; FIXME: Handling this is an open problem, at the moment we just bail out.
+;
+; void foo(float *A, float *B,
+; 	long p1,
+; 	long p2,
+; 	long p3,
+; 	long p4,
+; 	long p5,
+; 	long p6,
+; 	long p7,
+; 	long p8,
+; 	long p9,
+; 	long p10,
+; 	long p11,
+; 	long p12) {
+;   for (long i = 0; i < 100; i++) {
+;     A[i] =
+; 	B[i + p1] +
+; 	B[i + p2] +
+; 	B[i + p3] +
+; 	B[i + p4] +
+; 	B[i + p5] +
+; 	B[i + p6] +
+; 	B[i + p7] +
+; 	B[i + p8] +
+; 	B[i + p9] +
+; 	B[i + p10] +
+; 	B[i + p11] +
+; 	B[i + p12];
+;   }
+; }
+;
+; Computing the minimal and maximal element accessed in B is very expensive.
+; Expressing the minimal element itself yields a rather complex isl_pw_aff which
+; looks as follows:
+; { ...
+;   MemRef_B[(100 + p11)] : p2 <= -1 + p1 and p3 <= -1 + p1 and p4 <= -1 + p1
+;                           and p5 <= -1 + p1 and p6 <= -1 + p1 and
+;                           p7 <= -1 + p1 and p8 <= -1 + p1 and p9 <= -1 + p1
+;                           and p10 <= -1 + p1 and p11 >= p1 and
+;                           p12 <= -1 + p11;
+;   MemRef_B[(100 + p12)] : p2 <= -1 + p1 and p3 <= -1 + p1 and p4 <= -1 + p1
+;                           and p5 <= -1 + p1 and p6 <= -1 + p1 and
+;                           p7 <= -1 + p1 and p8 <= -1 + p1 and p9 <= -1 + p1
+;                           and p10 <= -1 + p1 and p11 <= -1 + p1 and p12 >= p1;
+;
+; and this isl_pw_aff is then 1:1 translated into a isl ast expression.
+;
+; In the best case, we would create a run-time check such as:
+;
+; if (B[99 + max(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)] < A[0]
+;     || A[99] B[min(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9]))
+;
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @foo(float* %A, float* %B, i64 %p1, i64 %p2, i64 %p3, i64 %p4, i64 %p5, i64 %p6, i64 %p7, i64 %p8, i64 %p9, i64 %p10, i64 %p11, i64 %p12) #0 {
+entry:
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %i.01 = phi i64 [ 0, %entry.split ], [ %tmp25, %for.body ]
+  %tmp = add i64 %p1, %i.01
+  %arrayidx = getelementptr float* %B, i64 %tmp
+  %tmp2 = add i64 %p2, %i.01
+  %arrayidx2 = getelementptr float* %B, i64 %tmp2
+  %tmp3 = add i64 %p3, %i.01
+  %arrayidx5 = getelementptr float* %B, i64 %tmp3
+  %tmp4 = add i64 %p4, %i.01
+  %arrayidx8 = getelementptr float* %B, i64 %tmp4
+  %tmp5 = add i64 %p5, %i.01
+  %arrayidx11 = getelementptr float* %B, i64 %tmp5
+  %tmp6 = add i64 %p6, %i.01
+  %arrayidx14 = getelementptr float* %B, i64 %tmp6
+  %tmp7 = add i64 %p7, %i.01
+  %arrayidx17 = getelementptr float* %B, i64 %tmp7
+  %tmp8 = add i64 %p8, %i.01
+  %arrayidx20 = getelementptr float* %B, i64 %tmp8
+  %tmp9 = add i64 %p9, %i.01
+  %arrayidx23 = getelementptr float* %B, i64 %tmp9
+  %tmp10 = add i64 %p10, %i.01
+  %arrayidx26 = getelementptr float* %B, i64 %tmp10
+  %tmp11 = add i64 %p11, %i.01
+  %arrayidx29 = getelementptr float* %B, i64 %tmp11
+  %tmp12 = add i64 %p12, %i.01
+  %arrayidx32 = getelementptr float* %B, i64 %tmp12
+  %arrayidx34 = getelementptr float* %A, i64 %i.01
+  %tmp13 = load float* %arrayidx, align 4
+  %tmp14 = load float* %arrayidx2, align 4
+  %add3 = fadd float %tmp13, %tmp14
+  %tmp15 = load float* %arrayidx5, align 4
+  %add6 = fadd float %add3, %tmp15
+  %tmp16 = load float* %arrayidx8, align 4
+  %add9 = fadd float %add6, %tmp16
+  %tmp17 = load float* %arrayidx11, align 4
+  %add12 = fadd float %add9, %tmp17
+  %tmp18 = load float* %arrayidx14, align 4
+  %add15 = fadd float %add12, %tmp18
+  %tmp19 = load float* %arrayidx17, align 4
+  %add18 = fadd float %add15, %tmp19
+  %tmp20 = load float* %arrayidx20, align 4
+  %add21 = fadd float %add18, %tmp20
+  %tmp21 = load float* %arrayidx23, align 4
+  %add24 = fadd float %add21, %tmp21
+  %tmp22 = load float* %arrayidx26, align 4
+  %add27 = fadd float %add24, %tmp22
+  %tmp23 = load float* %arrayidx29, align 4
+  %add30 = fadd float %add27, %tmp23
+  %tmp24 = load float* %arrayidx32, align 4
+  %add33 = fadd float %add30, %tmp24
+  store float %add33, float* %arrayidx34, align 4
+  %tmp25 = add nsw i64 %i.01, 1
+  %exitcond = icmp ne i64 %tmp25, 100
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
diff --git a/final/test/ScopInfo/run-time-check-read-only-arrays.ll b/final/test/ScopInfo/run-time-check-read-only-arrays.ll
new file mode 100644
index 0000000..9d81337
--- /dev/null
+++ b/final/test/ScopInfo/run-time-check-read-only-arrays.ll
@@ -0,0 +1,33 @@
+; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze < %s | FileCheck %s
+;
+; void foo(float *A, float *B, float *C, long N) {
+; 	for (long i = 0; i < N; i++)
+; 		C[i] = A[i] + B[i];
+; }
+;
+; CHECK: Alias Groups (2):
+;
+; This test case verifies that we do not create run-time checks for two
+; read-only arrays.
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo(float* %A, float* %B, float* %C, i64 %N) {
+entry:
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]
+  %arrayidx.A = getelementptr float* %A, i64 %indvar
+  %arrayidx.B = getelementptr float* %B, i64 %indvar
+  %arrayidx.C = getelementptr float* %C, i64 %indvar
+  %val.A = load float* %arrayidx.A
+  %val.B = load float* %arrayidx.B
+  %add = fadd float %val.A, %val.B
+  store float %add, float* %arrayidx.C
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp ne i64 %indvar.next, %N
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
diff --git a/final/test/ScopInfo/scalar.ll b/final/test/ScopInfo/scalar.ll
new file mode 100644
index 0000000..5541b4c
--- /dev/null
+++ b/final/test/ScopInfo/scalar.ll
@@ -0,0 +1,50 @@
+; RUN: opt %loadPolly -polly-scops -analyze -disable-polly-intra-scop-scalar-to-array < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %a, i64 %N) {
+entry:
+  br label %for
+
+for:
+  %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.backedge ]
+  br label %S1
+
+S1:
+  %scevgep1 = getelementptr i64* %a, i64 %indvar
+  %val = load i64* %scevgep1, align 8
+  br label %S2
+
+S2:
+  %scevgep2 = getelementptr i64* %a, i64 %indvar
+  store i64 %val, i64* %scevgep2, align 8
+  br label %for.backedge
+
+for.backedge:
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for
+
+return:
+  ret void
+}
+
+; CHECK: Stmt_S1
+; CHECK:       Domain :=
+; CHECK:           [N] -> { Stmt_S1[i0] : i0 >= 0 and i0 <= -1 + N };
+; CHECK:       Scattering :=
+; CHECK:           [N] -> { Stmt_S1[i0] -> scattering[i0, 0] };
+; CHECK:       ReadAccess :=
+; CHECK:           [N] -> { Stmt_S1[i0] -> MemRef_a[i0] };
+; CHECK:       MustWriteAccess :=
+; CHECK:           [N] -> { Stmt_S1[i0] -> MemRef_val[] };
+; CHECK: Stmt_S2
+; CHECK:       Domain :=
+; CHECK:           [N] -> { Stmt_S2[i0] : i0 >= 0 and i0 <= -1 + N };
+; CHECK:       Scattering :=
+; CHECK:           [N] -> { Stmt_S2[i0] -> scattering[i0, 1] };
+; CHECK:       ReadAccess :=
+; CHECK:           [N] -> { Stmt_S2[i0] -> MemRef_val[] };
+; CHECK:       MustWriteAccess :=
+; CHECK:           [N] -> { Stmt_S2[i0] -> MemRef_a[i0] };
diff --git a/final/test/ScopInfo/simple_loop_1.ll b/final/test/ScopInfo/simple_loop_1.ll
new file mode 100644
index 0000000..10d248b
--- /dev/null
+++ b/final/test/ScopInfo/simple_loop_1.ll
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+; void f(int a[], int N) {
+;   int i;
+;   for (i = 0; i < N; ++i)
+;     a[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* nocapture %a, i64 %N) nounwind {
+entry:
+  br label %bb
+
+bb:                                               ; preds = %bb, %entry
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %bb ]
+  %scevgep = getelementptr i64* %a, i64 %i
+  store i64 %i, i64* %scevgep
+  %i.inc = add nsw i64 %i, 1
+  %exitcond = icmp eq i64 %i.inc, %N
+  br i1 %exitcond, label %return, label %bb
+
+return:                                           ; preds = %bb, %entry
+  ret void
+}
+
+; CHECK: Assumed Context:
+; CHECK:   {  :  }
+
+; CHECK:  Stmt_bb
+; CHECK:        Domain :=
+; CHECK:            [N] -> { Stmt_bb[i0] : i0 >= 0 and i0 <= -1 + N };
+; CHECK:        Scattering :=
+; CHECK:            [N] -> { Stmt_bb[i0] -> scattering[i0] };
+; CHECK:        MustWriteAccess := [Reduction Type: NONE]
+; CHECK:            [N] -> { Stmt_bb[i0] -> MemRef_a[i0] };
diff --git a/final/test/ScopInfo/simple_nonaffine_loop_not.ll b/final/test/ScopInfo/simple_nonaffine_loop_not.ll
new file mode 100644
index 0000000..979eb15
--- /dev/null
+++ b/final/test/ScopInfo/simple_nonaffine_loop_not.ll
@@ -0,0 +1,40 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | not FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.7.2"
+
+@.str = private unnamed_addr constant [17 x i8] c"Random Value: %d\00", align 1
+
+define i32 @main() nounwind uwtable ssp {
+entry:
+  %A = alloca [1048576 x i32], align 16
+  br label %entry.split
+
+entry.split:                                      ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %entry.split, %for.body
+  %0 = phi i32 [ 0, %entry.split ], [ %1, %for.body ]
+  %mul = mul i32 %0, 2
+  %mul1 = mul nsw i32 %0, %0
+  %idxprom1 = zext i32 %mul1 to i64
+  %arrayidx = getelementptr inbounds [1048576 x i32]* %A, i64 0, i64 %idxprom1
+  store i32 %mul, i32* %arrayidx, align 4
+  %1 = add nsw i32 %0, 1
+  %exitcond = icmp ne i32 %1, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  %call = call i32 @rand() nounwind
+  %rem = srem i32 %call, 1024
+  %mul2 = shl nsw i32 %rem, 10
+  %idxprom3 = sext i32 %mul2 to i64
+  %arrayidx4 = getelementptr inbounds [1048576 x i32]* %A, i64 0, i64 %idxprom3
+  %2 = load i32* %arrayidx4, align 16
+  %call5 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str, i64 0, i64 0), i32 %2) nounwind
+  ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+
+declare i32 @rand()
+; CHECK:                { Stmt_for_body[i0] -> MemRef_A[o0] };
diff --git a/final/test/ScopInfo/smax.ll b/final/test/ScopInfo/smax.ll
new file mode 100644
index 0000000..73998df
--- /dev/null
+++ b/final/test/ScopInfo/smax.ll
@@ -0,0 +1,26 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:32-n32-S64"
+target triple = "thumbv7-none-linux-gnueabi"
+
+define void @foo(i32 * noalias %data, i32 * noalias %ptr, i32 %x_pos, i32 %w) {
+entry:
+  br label %for.body
+
+for.body:
+  %x = phi i32 [ 0, %entry ], [ %x.inc, %for.body ]
+  %add = add nsw i32 %x, %x_pos
+  %cmp1 = icmp sgt i32 %add, %w
+  %cond = select i1 %cmp1, i32 %w, i32 %add
+  %arrayidx = getelementptr inbounds i32* %ptr, i32 %cond
+  store i32 1, i32* %arrayidx
+  %x.inc = add nsw i32 %x, 1
+  %cmp = icmp slt i32 %x.inc, 2
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+
+; We check that there are only two parameters, but not a third one that
+; represents the smax() expression. This test case comes from PR 18155.
+; CHECK: [w, x_pos]
diff --git a/final/test/ScopInfo/undef_in_cond.ll b/final/test/ScopInfo/undef_in_cond.ll
new file mode 100644
index 0000000..815968e
--- /dev/null
+++ b/final/test/ScopInfo/undef_in_cond.ll
@@ -0,0 +1,23 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define fastcc void @fix_operands() nounwind {
+entry:
+  br i1 undef, label %bb3, label %bb1
+
+bb1:                                              ; preds = %bb
+  %0 = icmp eq i32 0, undef                       ; <i1> [#uses=1]
+  br i1 %0, label %bb3, label %bb2
+
+bb2:                                              ; preds = %bb1
+  br label %bb3
+
+bb3:                                              ; preds = %bb2, %bb1, %bb
+  br label %bb14
+
+bb14:                                             ; preds = %bb5, %bb4, %bb3, %entry
+  ret void
+}
+
+; CHECK: Invalid Scop!
diff --git a/final/test/ScopInfo/unsigned-condition.ll b/final/test/ScopInfo/unsigned-condition.ll
new file mode 100644
index 0000000..407ede9
--- /dev/null
+++ b/final/test/ScopInfo/unsigned-condition.ll
@@ -0,0 +1,47 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-allow-unsigned < %s | FileCheck %s
+
+; void f(int a[], int N, unsigned P) {
+;   int i;
+;   for (i = 0; i < N; ++i)
+;     if (P > 42)
+;       a[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* nocapture %a, i64 %N, i64 %P) nounwind {
+entry:
+  br label %bb
+
+bb:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %bb.backedge ]
+  %brcond = icmp uge i64 %P, 42
+  br i1 %brcond, label %store, label %bb.backedge
+
+store:
+  %scevgep = getelementptr i64* %a, i64 %i
+  store i64 %i, i64* %scevgep
+  br label %bb.backedge
+
+bb.backedge:
+  %i.inc = add nsw i64 %i, 1
+  %exitcond = icmp eq i64 %i.inc, %N
+  br i1 %exitcond, label %return, label %bb
+
+return:
+  ret void
+}
+
+; CHECK: Assumed Context:
+; CHECK:   {  :  }
+
+; CHECK:  Stmt_store
+; CHECK:        Domain :=
+; CHECK:            [N, P] -> { Stmt_store[i0] :
+; CHECK:              i0 >= 0 and i0 <= -1 + N and P >= 42
+; CHECK:                   };
+; CHECK:        Scattering :=
+; CHECK:            [N, P] -> { Stmt_store[i0] -> scattering[i0] };
+; CHECK:        MustWriteAccess := [Reduction Type: NONE]
+; CHECK:            [N, P] -> { Stmt_store[i0] -> MemRef_a[i0] };
diff --git a/final/test/TempScop/inter_bb_scalar_dep.ll b/final/test/TempScop/inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..4a7ceab
--- /dev/null
+++ b/final/test/TempScop/inter_bb_scalar_dep.ll
@@ -0,0 +1,54 @@
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir  -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     for (i = 0; i < N; ++i) {
+;       A[i] = init + 2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) #0 {
+entry:
+  br label %for.i
+
+for.i:                                            ; preds = %for.i.end, %entry
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:                                       ; preds = %for.i
+  %init = load i64* %init_ptr
+; CHECK: BB: entry.next
+; CHECK: Read init_ptr[0]
+; CHECK: Write init[0]
+  br label %for.j
+
+for.j:                                            ; preds = %for.j, %entry.next
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init_plus_two = add i64 %init, 2
+; CHECK: Read init[0]
+; CHECK: Write A[{0,+,8}<%for.j>]
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_plus_two, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:                                        ; preds = %for.j
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:                                           ; preds = %for.i.end
+  ret void
+}
+
+attributes #0 = { nounwind }
diff --git a/final/test/TempScop/intra_and_inter_bb_scalar_dep.ll b/final/test/TempScop/intra_and_inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..d9c8885
--- /dev/null
+++ b/final/test/TempScop/intra_and_inter_bb_scalar_dep.ll
@@ -0,0 +1,58 @@
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     for (i = 0; i < N; ++i) {
+;       init2 = *init_ptr;
+;       A[i] = init + init2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) #0 {
+entry:
+  br label %for.i
+
+for.i:                                            ; preds = %for.i.end, %entry
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:                                       ; preds = %for.i
+  %init = load i64* %init_ptr
+; CHECK: BB: entry.next
+; CHECK: Read init_ptr[0]
+; CHECK: Write init[0]
+  br label %for.j
+
+for.j:                                            ; preds = %for.j, %entry.next
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init_2 = load i64* %init_ptr
+  %init_sum = add i64 %init, %init_2
+; CHECK: BB: for.j
+; CHECK: Read init[0]
+; CHECK: Read init_ptr[0]
+; CHECK: Write A[{0,+,8}<%for.j>]
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_sum, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:                                        ; preds = %for.j
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:                                           ; preds = %for.i.end
+  ret void
+}
+
+attributes #0 = { nounwind }
diff --git a/final/test/TempScop/intra_bb_scalar_dep.ll b/final/test/TempScop/intra_bb_scalar_dep.ll
new file mode 100644
index 0000000..ce60978
--- /dev/null
+++ b/final/test/TempScop/intra_bb_scalar_dep.ll
@@ -0,0 +1,52 @@
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir  -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     for (i = 0; i < N; ++i) {
+;       init = *init_ptr;
+;       A[i] = init + 2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) #0 {
+entry:
+  br label %for.i
+
+for.i:                                            ; preds = %for.i.end, %entry
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:                                       ; preds = %for.i
+  br label %for.j
+
+for.j:                                            ; preds = %for.j, %entry.next
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %init = load i64* %init_ptr
+  %init_plus_two = add i64 %init, 2
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_plus_two, i64* %scevgep
+; CHECK: BB: for.j
+; CHECK: Read init_ptr[0]
+; CHECK: Write A[{0,+,8}<%for.j>]
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:                                        ; preds = %for.j
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:                                           ; preds = %for.i.end
+  ret void
+}
+
+attributes #0 = { nounwind }
diff --git a/final/test/TempScop/nested-loops.ll b/final/test/TempScop/nested-loops.ll
new file mode 100644
index 0000000..318b5b8
--- /dev/null
+++ b/final/test/TempScop/nested-loops.ll
@@ -0,0 +1,33 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* nocapture %a) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %for.j ]
+  %i.inc = add nsw i64 %i, 1
+  %exitcond.i = icmp sge i64 %i.inc, 2048
+  br i1 %exitcond.i, label %return, label %for.j
+
+for.j:
+  %j = phi i64 [ 0, %for.i ], [ %j.inc, %body ]
+  %j.inc = add nsw i64 %j, 1
+  %exitcond.j = icmp slt i64 %j.inc, 1024
+  br i1 %exitcond.j, label %body, label %for.i
+
+body:
+  %scevgep = getelementptr i64* %a, i64 %j
+  store i64 %j, i64* %scevgep
+  br label %for.j
+
+return:
+  ret void
+}
+
+; CHECK: body
+; CHECK:        Domain :=
+; CHECK:           { Stmt_body[i0, i1] : i0 >= 0 and i0 <= 2046 and i1 >= 0 and i1 <= 1022 }
diff --git a/final/test/TempScop/not-a-reduction.ll b/final/test/TempScop/not-a-reduction.ll
new file mode 100644
index 0000000..1e1e328
--- /dev/null
+++ b/final/test/TempScop/not-a-reduction.ll
@@ -0,0 +1,51 @@
+; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s 2>&1 | not FileCheck %s
+
+;#define TYPE float
+;#define NUM 4
+;
+;TYPE A[NUM];
+;TYPE B[NUM];
+;TYPE C[NUM];
+;
+;void vector_multiply(void) {
+;	int i;
+;	for (i = 0; i < NUM; i++) {
+;		A[i] = B[i] * C[i];
+;	}
+;}
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+@B = common global [4 x float] zeroinitializer, align 16
+@C = common global [4 x float] zeroinitializer, align 16
+@A = common global [4 x float] zeroinitializer, align 16
+
+define void @vector_multiply() nounwind {
+bb:
+  br label %bb3
+
+bb3:                                              ; preds = %bb7, %bb
+  %indvar = phi i64 [ %indvar.next, %bb7 ], [ 0, %bb ]
+  %scevgep = getelementptr [4 x float]* @A, i64 0, i64 %indvar
+  %scevgep1 = getelementptr [4 x float]* @C, i64 0, i64 %indvar
+  %scevgep2 = getelementptr [4 x float]* @B, i64 0, i64 %indvar
+  %exitcond = icmp ne i64 %indvar, 4
+  br i1 %exitcond, label %bb4, label %bb8
+
+bb4:                                              ; preds = %bb3
+  %tmp = load float* %scevgep2, align 4
+  %tmp5 = load float* %scevgep1, align 4
+  %tmp6 = fmul float %tmp, %tmp5
+  store float %tmp6, float* %scevgep, align 4
+  br label %bb7
+
+bb7:                                              ; preds = %bb4
+  %indvar.next = add i64 %indvar, 1
+  br label %bb3
+
+bb8:                                              ; preds = %bb3
+  ret void
+}
+
+; CHECK:     Reduction
diff --git a/final/test/TempScop/scalar_to_array.ll b/final/test/TempScop/scalar_to_array.ll
new file mode 100644
index 0000000..d12b0e6
--- /dev/null
+++ b/final/test/TempScop/scalar_to_array.ll
@@ -0,0 +1,186 @@
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -disable-polly-intra-scop-scalar-to-array -analyze < %s | FileCheck %s
+
+; ModuleID = 'scalar_to_array.ll'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@A = common global [1024 x float] zeroinitializer, align 8
+
+; CHECK: empty
+; Function Attrs: nounwind
+define i32 @empty() #0 {
+entry:
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:                                         ; preds = %for.cond
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:                                           ; preds = %for.cond
+  fence seq_cst
+  ret i32 0
+}
+
+; CHECK: array_access
+; Function Attrs: nounwind
+define i32 @array_access() #0 {
+entry:
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %float = uitofp i64 %indvar to float
+  store float %float, float* %arrayidx
+  br label %for.inc
+; CHECK: BB: for.body
+; CHECK-NOT: Read
+; CHECK: Write A[{0,+,4}<%for.cond>]
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:                                           ; preds = %for.cond
+  fence seq_cst
+  ret i32 0
+}
+
+; Function Attrs: nounwind
+; CHECK: intra_scop_dep
+define i32 @intra_scop_dep() #0 {
+entry:
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body.a, label %return
+
+for.body.a:                                       ; preds = %for.cond
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %scalar = load float* %arrayidx
+  br label %for.body.b
+; CHECK: BB: for.body.a
+; CHECK: Read A[{0,+,4}<%for.cond>]
+; CHECK: Write scalar[0]
+
+for.body.b:                                       ; preds = %for.body.a
+  %arrayidx2 = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %float = uitofp i64 %indvar to float
+  %sum = fadd float %scalar, %float
+  store float %sum, float* %arrayidx2
+  br label %for.inc
+; CHECK: BB: for.body.b
+; CHECK: Read scalar[0]
+; CHECK: Write A[{0,+,4}<%for.cond>]
+
+for.inc:                                          ; preds = %for.body.b
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:                                           ; preds = %for.cond
+  fence seq_cst
+  ret i32 0
+}
+
+; It is not possible to have a scop which accesses a scalar element that is
+; a global variable. All global variables are pointers containing possibly
+; a single element. Hence they do not need to be handled anyways.
+; Please note that this is still required when scalar to array rewritting is
+; disabled.
+
+; CHECK: use_after_scop
+; Function Attrs: nounwind
+define i32 @use_after_scop() #0 {
+entry:
+  %scalar.s2a = alloca float
+  fence seq_cst
+  br label %for.head
+
+for.head:                                         ; preds = %for.inc, %entry
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+  br label %for.body
+
+for.body:                                         ; preds = %for.head
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  %scalar = load float* %arrayidx
+  store float %scalar, float* %scalar.s2a
+; Escaped uses are still required to be rewritten to stack variable.
+; CHECK: BB: for.body
+; CHECK: Read A[{0,+,4}<%for.head>]
+; CHECK: Write scalar.s2a[0]
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.head, label %for.after
+
+for.after:                                        ; preds = %for.inc
+  %scalar.loadoutside = load float* %scalar.s2a
+  fence seq_cst
+  %return_value = fptosi float %scalar.loadoutside to i32
+  br label %return
+
+return:                                           ; preds = %for.after
+  ret i32 %return_value
+}
+
+; We currently do not transform scalar references, that have only read accesses
+; in the scop. There are two reasons for this:
+;
+;  o We don't introduce additional memory references which may yield to compile
+;    time overhead.
+;  o For integer values, such a translation may block the use of scalar
+;    evolution on those values.
+;
+; CHECK: before_scop
+; Function Attrs: nounwind
+define i32 @before_scop() #0 {
+entry:
+  br label %preheader
+
+preheader:                                        ; preds = %entry
+  %scalar = fadd float 4.000000e+00, 5.000000e+00
+  fence seq_cst
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %preheader
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %preheader ]
+  %exitcond = icmp ne i64 %indvar, 1024
+  br i1 %exitcond, label %for.body, label %return
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr [1024 x float]* @A, i64 0, i64 %indvar
+  store float %scalar, float* %arrayidx
+  br label %for.inc
+; CHECK: BB: for.body
+; CHECK: Write A[{0,+,4}<%for.cond>]
+
+for.inc:                                          ; preds = %for.body
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond
+
+return:                                           ; preds = %for.cond
+  fence seq_cst
+  ret i32 0
+}
+
+attributes #0 = { nounwind }
diff --git a/final/test/TempScop/tempscop-printing.ll b/final/test/TempScop/tempscop-printing.ll
new file mode 100644
index 0000000..04b5c67
--- /dev/null
+++ b/final/test/TempScop/tempscop-printing.ll
@@ -0,0 +1,94 @@
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-analyze-ir -analyze -disable-polly-intra-scop-scalar-to-array < %s | FileCheck %s -check-prefix=SCALARACCESS
+
+; void f(long A[], int N, int *init_ptr) {
+;   long i, j;
+;
+;   for (i = 0; i < N; ++i) {
+;     init = *init_ptr;
+;     for (i = 0; i < N; ++i) {
+;       A[i] = init + 2;
+;     }
+;   }
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+; CHECK: BB: entry.next
+; SCALARACCESS: BB: entry.next
+  %init = load i64* %init_ptr
+; CHECK:  Read init_ptr[0]
+; CHECK:  Write init.s2a[0]
+; SCALARACCESS: Read init_ptr[0]
+; SCALARACCESS:  Write init[0]
+  br label %for.j
+
+for.j:
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+; CHECK: BB: for.j
+; CHECK: Read init.s2a[0]
+; CHECK: Write A[{0,+,8}<%for.j>]
+
+; SCALARACCESS: BB: for.j
+; SCALARACCESS: Read init
+; SCALARACCESS: Write A[{0,+,8}<%for.j>]
+  %init_plus_two = add i64 %init, 2
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init_plus_two, i64* %scevgep
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
+
+define void @g(i64* noalias %A, i64 %N, i64* noalias %init_ptr) nounwind {
+entry:
+  br label %for.i
+
+for.i:
+  %indvar.i = phi i64 [ 0, %entry ], [ %indvar.i.next, %for.i.end ]
+  %indvar.i.next = add nsw i64 %indvar.i, 1
+  br label %entry.next
+
+entry.next:
+; SCALARACCESS: BB: entry.next
+  %init = load i64* %init_ptr
+; SCALARACCESS: Read init_ptr[0]
+; SCALARACCESS:  Write init[0]
+  br label %for.j
+
+for.j:
+; SCALARACCESS: BB: for.j
+  %indvar.j = phi i64 [ 0, %entry.next ], [ %indvar.j.next, %for.j ]
+  %scevgep = getelementptr i64* %A, i64 %indvar.j
+  store i64 %init, i64* %scevgep
+; SCALARACCESS: Read init
+; SCALARACCESS: Write A[{0,+,8}<%for.j>]
+  %indvar.j.next = add nsw i64 %indvar.j, 1
+  %exitcond.j = icmp eq i64 %indvar.j.next, %N
+  br i1 %exitcond.j, label %for.i.end, label %for.j
+
+for.i.end:
+  %exitcond.i = icmp eq i64 %indvar.i.next, %N
+  br i1 %exitcond.i, label %return, label %for.i
+
+return:
+  ret void
+}
diff --git a/final/test/create_ll.sh b/final/test/create_ll.sh
new file mode 100755
index 0000000..b0b56be
--- /dev/null
+++ b/final/test/create_ll.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+
+LLFILE=`echo $1 | sed -e 's/\.c/.ll/g'`
+LLFILE_TMP=${LLFILE}.tmp
+
+# The number of lines to cut of the LLVM-IR file clang produces.
+CUT_N_LINES=6
+
+clang -c -S -emit-llvm -O0 $1 -o ${LLFILE}
+
+opt -correlated-propagation -mem2reg -instcombine -loop-simplify -indvars \
+-instnamer ${LLFILE} -S -o ${LLFILE_TMP}
+
+# Insert a header into the new testcase containing a sample RUN line a FIXME and
+# an XFAIL. Then insert the formated C code and finally the LLVM-IR without
+# attributes, the module ID or the target triple.
+echo '; RUN: opt %loadPolly -analyze < %s | FileCheck %s' > ${LLFILE}
+echo ';' >> ${LLFILE}
+echo '; FIXME: Edit the run line and add checks!' >> ${LLFILE}
+echo ';' >> ${LLFILE}
+echo '; XFAIL: *' >> ${LLFILE}
+echo ';' >> ${LLFILE}
+clang-format $1 | sed -e 's/^/;    /' >> ${LLFILE}
+echo ';' >> ${LLFILE}
+
+cat ${LLFILE_TMP} | sed -e 's/ \#0//' >> ${LLFILE}
+sed -i".tmp" '/; Function Attrs:/d' ${LLFILE}
+sed -i".tmp" '/; ModuleID =/d' ${LLFILE}
+sed -i".tmp" '/target triple/d' ${LLFILE}
+
+head --lines=-${CUT_N_LINES} ${LLFILE} > ${LLFILE_TMP}
+
+mv ${LLFILE_TMP} ${LLFILE}
diff --git a/final/test/lit.cfg b/final/test/lit.cfg
new file mode 100644
index 0000000..0d7eb3b
--- /dev/null
+++ b/final/test/lit.cfg
@@ -0,0 +1,126 @@
+# -*clang- Python -*-
+
+import os
+import platform
+import re
+
+import lit.formats
+import lit.util
+
+# Configuration file for the 'lit' test runner.
+
+# name: The name of this test suite.
+config.name = 'Polly'
+
+# testFormat: The test format to use to interpret tests.
+#
+# For now we require '&&' between commands, until they get globally killed and
+# the test runner updated.
+execute_external = platform.system() != 'Windows'
+config.test_format = lit.formats.ShTest(execute_external)
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.ll']
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root path where tests should be run.
+polly_obj_root = getattr(config, 'polly_obj_root', None)
+if polly_obj_root is not None:
+    config.test_exec_root = os.path.join(polly_obj_root, 'test')
+
+# Set llvm_{src,obj}_root for use by others.
+config.llvm_src_root = getattr(config, 'llvm_src_root', None)
+config.llvm_obj_root = getattr(config, 'llvm_obj_root', None)
+
+# Tweak the PATH to include the tools dir and the scripts dir.
+if polly_obj_root is not None:
+    llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
+    if not llvm_tools_dir:
+        lit_config.fatal('No LLVM tools dir set!')
+    path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH']))
+    config.environment['PATH'] = path
+
+    llvm_libs_dir = getattr(config, 'llvm_libs_dir', None)
+    if not llvm_libs_dir:
+        lit_config.fatal('No LLVM libs dir set!')
+    path = os.path.pathsep.join((llvm_libs_dir,
+                                 config.environment.get('LD_LIBRARY_PATH','')))
+    config.environment['LD_LIBRARY_PATH'] = path
+
+###
+
+# Check that the object root is known.
+if config.test_exec_root is None:
+    # Otherwise, we haven't loaded the site specific configuration (the user is
+    # probably trying to run on a test file directly, and either the site
+    # configuration hasn't been created by the build system, or we are in an
+    # out-of-tree build situation).
+
+    # Check for 'polly_site_config' user parameter, and use that if available.
+    site_cfg = lit_config.params.get('polly_site_config', None)
+    if site_cfg and os.path.exists(site_cfg):
+        lit_config.load_config(config, site_cfg)
+        raise SystemExit
+
+    # Try to detect the situation where we are using an out-of-tree build by
+    # looking for 'llvm-config'.
+    #
+    # FIXME: I debated (i.e., wrote and threw away) adding logic to
+    # automagically generate the lit.site.cfg if we are in some kind of fresh
+    # build situation. This means knowing how to invoke the build system though,
+    # and I decided it was too much magic. We should solve this by just having
+    # the .cfg files generated during the configuration step.
+
+    llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
+    if not llvm_config:
+        lit_config.fatal('No site specific configuration available!')
+
+    # Get the source and object roots.
+    llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
+    llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()
+    polly_src_root = os.path.join(llvm_src_root, "tools", "polly")
+    polly_obj_root = os.path.join(llvm_obj_root, "tools", "polly")
+
+    # Validate that we got a tree which points to here, using the standard
+    # tools/polly layout.
+    this_src_root = os.path.dirname(config.test_source_root)
+    if os.path.realpath(polly_src_root) != os.path.realpath(this_src_root):
+        lit_config.fatal('No site specific configuration available!')
+
+    # Check that the site specific configuration exists.
+    site_cfg = os.path.join(polly_obj_root, 'test', 'lit.site.cfg')
+    if not os.path.exists(site_cfg):
+        lit_config.fatal('No site specific configuration available!')
+
+    # Okay, that worked. Notify the user of the automagic, and reconfigure.
+    lit_config.note('using out-of-tree build at %r' % polly_obj_root)
+    lit_config.load_config(config, site_cfg)
+    raise SystemExit
+
+# opt knows whether it is compiled with -DNDEBUG.
+import subprocess
+try:
+    opt_cmd = subprocess.Popen([os.path.join(llvm_tools_dir, 'opt'), '-version'],
+                           stdout = subprocess.PIPE)
+except OSError, why:
+    print "Could not find opt in " + llvm_tools_dir
+    exit(42)
+
+if re.search(r'with assertions', opt_cmd.stdout.read()):
+    config.available_features.add('asserts')
+opt_cmd.wait()
+
+try:
+    llvm_config_cmd = subprocess.Popen([os.path.join(llvm_tools_dir,
+                                                     'llvm-config'),
+                                        '--targets-built'],
+                                       stdout = subprocess.PIPE)
+except OSError, why:
+    print "Could not find llvm-config in " + llvm_tools_dir
+    exit(42)
+
+if re.search(r'NVPTX', llvm_config_cmd.stdout.read()):
+    config.available_features.add('nvptx-registered-target')
+llvm_config_cmd.wait()
diff --git a/final/test/lit.site.cfg.in b/final/test/lit.site.cfg.in
new file mode 100644
index 0000000..768a0e0
--- /dev/null
+++ b/final/test/lit.site.cfg.in
@@ -0,0 +1,45 @@
+## Autogenerated by LLVM/Polly configuration.
+# Do not edit!
+config.llvm_src_root = "@LLVM_SOURCE_DIR@"
+config.llvm_obj_root = "@LLVM_BINARY_DIR@"
+config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
+config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.polly_obj_root = "@POLLY_BINARY_DIR@"
+config.polly_lib_dir = "@POLLY_LIB_DIR@"
+config.target_triple = "@TARGET_TRIPLE@"
+config.enable_gpgpu_codegen = "@CUDALIB_FOUND@"
+config.link_polly_into_tools = "@LINK_POLLY_INTO_TOOLS@"
+
+## Check the current platform with regex
+import re
+EAT_ERR_ON_X86 = ' '
+if (re.match(r'^x86_64*', '@TARGET_TRIPLE@') == None) :
+  EAT_ERR_ON_X86 = '|| echo \"error is eaten\"'
+
+# Support substitution of the tools and libs dirs with user parameters. This is
+# used when we can't determine the tool dir at configuration time.
+try:
+    config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params
+    config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params
+except KeyError,e:
+    key, = e.args
+    lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
+
+if config.link_polly_into_tools == '' or \
+   config.link_polly_into_tools.lower() == '0' or \
+   config.link_polly_into_tools.lower() == 'n' or \
+   config.link_polly_into_tools.lower() == 'no' or \
+   config.link_polly_into_tools.lower() == 'off' or \
+   config.link_polly_into_tools.lower() == 'false' or \
+   config.link_polly_into_tools.lower() == 'notfound' or \
+   config.link_polly_into_tools.lower() == 'link_polly_into_tools-notfound':
+    config.substitutions.append(('%loadPolly', '-load '
+                                 + config.polly_lib_dir + '/LLVMPolly@LLVM_SHLIBEXT@'))
+else:
+    config.substitutions.append(('%loadPolly', ''))
+
+config.substitutions.append(('%polybenchOpts', ' -O3 -loop-simplify -indvars '))
+config.substitutions.append(('%vector-opt', '-polly-vectorizer=polly'))
+
+# Let the main config do the real work.
+lit_config.load_config(config, "@POLLY_SOURCE_DIR@/test/lit.cfg")
diff --git a/final/test/polly.ll b/final/test/polly.ll
new file mode 100644
index 0000000..da2ef0e
--- /dev/null
+++ b/final/test/polly.ll
@@ -0,0 +1,12 @@
+; RUN: opt %loadPolly -polly-scops -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define void @foo() nounwind {
+start:
+  br label %end
+
+end:
+  ret void
+}
+
+; CHECK: foo
diff --git a/final/tools/CMakeLists.txt b/final/tools/CMakeLists.txt
new file mode 100644
index 0000000..4ce60e1
--- /dev/null
+++ b/final/tools/CMakeLists.txt
@@ -0,0 +1,5 @@
+if (CUDALIB_FOUND)
+  add_subdirectory(GPURuntime)
+endif (CUDALIB_FOUND)
+
+set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE)
diff --git a/final/tools/GPURuntime/CMakeLists.txt b/final/tools/GPURuntime/CMakeLists.txt
new file mode 100644
index 0000000..822e4de
--- /dev/null
+++ b/final/tools/GPURuntime/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(MODULE TRUE)
+set(LLVM_NO_RTTI 1)
+
+add_polly_library(GPURuntime
+  GPUJIT.c
+  )
+
+set_target_properties(GPURuntime
+  PROPERTIES
+  LINKER_LANGUAGE C
+  PREFIX "lib"
+  )
diff --git a/final/tools/GPURuntime/GPUJIT.c b/final/tools/GPURuntime/GPUJIT.c
new file mode 100644
index 0000000..a03ebe9
--- /dev/null
+++ b/final/tools/GPURuntime/GPUJIT.c
@@ -0,0 +1,431 @@
+/******************** GPUJIT.cpp - GPUJIT Execution Engine                     \
+ * ********************/
+/*                                                                            */
+/*                     The LLVM Compiler Infrastructure                       */
+/*                                                                            */
+/* This file is dual licensed under the MIT and the University of Illinois    */
+/* Open Source License. See LICENSE.TXT for details.                         */
+/*                                                                            */
+/******************************************************************************/
+/*                                                                            */
+/*  This file implements GPUJIT, a ptx string execution engine for GPU.       */
+/*                                                                            */
+/******************************************************************************/
+
+#include "GPUJIT.h"
+#include <cuda.h>
+#include <cuda_runtime.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+/* Define Polly's GPGPU data types. */
+struct PollyGPUContextT {
+  CUcontext Cuda;
+};
+
+struct PollyGPUModuleT {
+  CUmodule Cuda;
+};
+
+struct PollyGPUFunctionT {
+  CUfunction Cuda;
+};
+
+struct PollyGPUDeviceT {
+  CUdevice Cuda;
+};
+
+struct PollyGPUDevicePtrT {
+  CUdeviceptr Cuda;
+};
+
+struct PollyGPUEventT {
+  cudaEvent_t Cuda;
+};
+
+/* Dynamic library handles for the CUDA and CUDA runtime library. */
+static void *HandleCuda;
+static void *HandleCudaRT;
+
+/* Type-defines of function pointer to CUDA driver APIs. */
+typedef CUresult CUDAAPI CuMemAllocFcnTy(CUdeviceptr *, size_t);
+static CuMemAllocFcnTy *CuMemAllocFcnPtr;
+
+typedef CUresult CUDAAPI CuFuncSetBlockShapeFcnTy(CUfunction, int, int, int);
+static CuFuncSetBlockShapeFcnTy *CuFuncSetBlockShapeFcnPtr;
+
+typedef CUresult CUDAAPI
+CuParamSetvFcnTy(CUfunction, int, void *, unsigned int);
+static CuParamSetvFcnTy *CuParamSetvFcnPtr;
+
+typedef CUresult CUDAAPI CuParamSetSizeFcnTy(CUfunction, unsigned int);
+static CuParamSetSizeFcnTy *CuParamSetSizeFcnPtr;
+
+typedef CUresult CUDAAPI CuLaunchGridFcnTy(CUfunction, int, int);
+static CuLaunchGridFcnTy *CuLaunchGridFcnPtr;
+
+typedef CUresult CUDAAPI CuMemcpyDtoHFcnTy(void *, CUdeviceptr, size_t);
+static CuMemcpyDtoHFcnTy *CuMemcpyDtoHFcnPtr;
+
+typedef CUresult CUDAAPI CuMemcpyHtoDFcnTy(CUdeviceptr, const void *, size_t);
+static CuMemcpyHtoDFcnTy *CuMemcpyHtoDFcnPtr;
+
+typedef CUresult CUDAAPI CuMemFreeFcnTy(CUdeviceptr);
+static CuMemFreeFcnTy *CuMemFreeFcnPtr;
+
+typedef CUresult CUDAAPI CuModuleUnloadFcnTy(CUmodule);
+static CuModuleUnloadFcnTy *CuModuleUnloadFcnPtr;
+
+typedef CUresult CUDAAPI CuCtxDestroyFcnTy(CUcontext);
+static CuCtxDestroyFcnTy *CuCtxDestroyFcnPtr;
+
+typedef CUresult CUDAAPI CuInitFcnTy(unsigned int);
+static CuInitFcnTy *CuInitFcnPtr;
+
+typedef CUresult CUDAAPI CuDeviceGetCountFcnTy(int *);
+static CuDeviceGetCountFcnTy *CuDeviceGetCountFcnPtr;
+
+typedef CUresult CUDAAPI CuCtxCreateFcnTy(CUcontext *, unsigned int, CUdevice);
+static CuCtxCreateFcnTy *CuCtxCreateFcnPtr;
+
+typedef CUresult CUDAAPI CuDeviceGetFcnTy(CUdevice *, int);
+static CuDeviceGetFcnTy *CuDeviceGetFcnPtr;
+
+typedef CUresult CUDAAPI CuModuleLoadDataExFcnTy(
+    CUmodule *, const void *, unsigned int, CUjit_option *, void **);
+static CuModuleLoadDataExFcnTy *CuModuleLoadDataExFcnPtr;
+
+typedef CUresult CUDAAPI
+CuModuleGetFunctionFcnTy(CUfunction *, CUmodule, const char *);
+static CuModuleGetFunctionFcnTy *CuModuleGetFunctionFcnPtr;
+
+typedef CUresult CUDAAPI CuDeviceComputeCapabilityFcnTy(int *, int *, CUdevice);
+static CuDeviceComputeCapabilityFcnTy *CuDeviceComputeCapabilityFcnPtr;
+
+typedef CUresult CUDAAPI CuDeviceGetNameFcnTy(char *, int, CUdevice);
+static CuDeviceGetNameFcnTy *CuDeviceGetNameFcnPtr;
+
+/* Type-defines of function pointer ot CUDA runtime APIs. */
+typedef cudaError_t CUDARTAPI CudaEventCreateFcnTy(cudaEvent_t *);
+static CudaEventCreateFcnTy *CudaEventCreateFcnPtr;
+
+typedef cudaError_t CUDARTAPI CudaEventRecordFcnTy(cudaEvent_t, cudaStream_t);
+static CudaEventRecordFcnTy *CudaEventRecordFcnPtr;
+
+typedef cudaError_t CUDARTAPI CudaEventSynchronizeFcnTy(cudaEvent_t);
+static CudaEventSynchronizeFcnTy *CudaEventSynchronizeFcnPtr;
+
+typedef cudaError_t CUDARTAPI
+CudaEventElapsedTimeFcnTy(float *, cudaEvent_t, cudaEvent_t);
+static CudaEventElapsedTimeFcnTy *CudaEventElapsedTimeFcnPtr;
+
+typedef cudaError_t CUDARTAPI CudaEventDestroyFcnTy(cudaEvent_t);
+static CudaEventDestroyFcnTy *CudaEventDestroyFcnPtr;
+
+typedef cudaError_t CUDARTAPI CudaThreadSynchronizeFcnTy(void);
+static CudaThreadSynchronizeFcnTy *CudaThreadSynchronizeFcnPtr;
+
+static void *getAPIHandle(void *Handle, const char *FuncName) {
+  char *Err;
+  void *FuncPtr;
+  dlerror();
+  FuncPtr = dlsym(Handle, FuncName);
+  if ((Err = dlerror()) != 0) {
+    fprintf(stdout, "Load CUDA driver API failed: %s. \n", Err);
+    return 0;
+  }
+  return FuncPtr;
+}
+
+static int initialDeviceAPILibraries() {
+  HandleCuda = dlopen("libcuda.so", RTLD_LAZY);
+  if (!HandleCuda) {
+    printf("Cannot open library: %s. \n", dlerror());
+    return 0;
+  }
+
+  HandleCudaRT = dlopen("libcudart.so", RTLD_LAZY);
+  if (!HandleCudaRT) {
+    printf("Cannot open library: %s. \n", dlerror());
+    return 0;
+  }
+
+  return 1;
+}
+
+static int initialDeviceAPIs() {
+  if (initialDeviceAPILibraries() == 0)
+    return 0;
+
+  /* Get function pointer to CUDA Driver APIs.
+   *
+   * Note that compilers conforming to the ISO C standard are required to
+   * generate a warning if a conversion from a void * pointer to a function
+   * pointer is attempted as in the following statements. The warning
+   * of this kind of cast may not be emitted by clang and new versions of gcc
+   * as it is valid on POSIX 2008.
+   */
+  CuFuncSetBlockShapeFcnPtr = (CuFuncSetBlockShapeFcnTy *)getAPIHandle(
+      HandleCuda, "cuFuncSetBlockShape");
+
+  CuParamSetvFcnPtr =
+      (CuParamSetvFcnTy *)getAPIHandle(HandleCuda, "cuParamSetv");
+
+  CuParamSetSizeFcnPtr =
+      (CuParamSetSizeFcnTy *)getAPIHandle(HandleCuda, "cuParamSetSize");
+
+  CuLaunchGridFcnPtr =
+      (CuLaunchGridFcnTy *)getAPIHandle(HandleCuda, "cuLaunchGrid");
+
+  CuMemAllocFcnPtr =
+      (CuMemAllocFcnTy *)getAPIHandle(HandleCuda, "cuMemAlloc_v2");
+
+  CuMemFreeFcnPtr = (CuMemFreeFcnTy *)getAPIHandle(HandleCuda, "cuMemFree_v2");
+
+  CuMemcpyDtoHFcnPtr =
+      (CuMemcpyDtoHFcnTy *)getAPIHandle(HandleCuda, "cuMemcpyDtoH_v2");
+
+  CuMemcpyHtoDFcnPtr =
+      (CuMemcpyHtoDFcnTy *)getAPIHandle(HandleCuda, "cuMemcpyHtoD_v2");
+
+  CuModuleUnloadFcnPtr =
+      (CuModuleUnloadFcnTy *)getAPIHandle(HandleCuda, "cuModuleUnload");
+
+  CuCtxDestroyFcnPtr =
+      (CuCtxDestroyFcnTy *)getAPIHandle(HandleCuda, "cuCtxDestroy");
+
+  CuInitFcnPtr = (CuInitFcnTy *)getAPIHandle(HandleCuda, "cuInit");
+
+  CuDeviceGetCountFcnPtr =
+      (CuDeviceGetCountFcnTy *)getAPIHandle(HandleCuda, "cuDeviceGetCount");
+
+  CuDeviceGetFcnPtr =
+      (CuDeviceGetFcnTy *)getAPIHandle(HandleCuda, "cuDeviceGet");
+
+  CuCtxCreateFcnPtr =
+      (CuCtxCreateFcnTy *)getAPIHandle(HandleCuda, "cuCtxCreate_v2");
+
+  CuModuleLoadDataExFcnPtr =
+      (CuModuleLoadDataExFcnTy *)getAPIHandle(HandleCuda, "cuModuleLoadDataEx");
+
+  CuModuleGetFunctionFcnPtr = (CuModuleGetFunctionFcnTy *)getAPIHandle(
+      HandleCuda, "cuModuleGetFunction");
+
+  CuDeviceComputeCapabilityFcnPtr =
+      (CuDeviceComputeCapabilityFcnTy *)getAPIHandle(
+          HandleCuda, "cuDeviceComputeCapability");
+
+  CuDeviceGetNameFcnPtr =
+      (CuDeviceGetNameFcnTy *)getAPIHandle(HandleCuda, "cuDeviceGetName");
+
+  /* Get function pointer to CUDA Runtime APIs. */
+  CudaEventCreateFcnPtr =
+      (CudaEventCreateFcnTy *)getAPIHandle(HandleCudaRT, "cudaEventCreate");
+
+  CudaEventRecordFcnPtr =
+      (CudaEventRecordFcnTy *)getAPIHandle(HandleCudaRT, "cudaEventRecord");
+
+  CudaEventSynchronizeFcnPtr = (CudaEventSynchronizeFcnTy *)getAPIHandle(
+      HandleCudaRT, "cudaEventSynchronize");
+
+  CudaEventElapsedTimeFcnPtr = (CudaEventElapsedTimeFcnTy *)getAPIHandle(
+      HandleCudaRT, "cudaEventElapsedTime");
+
+  CudaEventDestroyFcnPtr =
+      (CudaEventDestroyFcnTy *)getAPIHandle(HandleCudaRT, "cudaEventDestroy");
+
+  CudaThreadSynchronizeFcnPtr = (CudaThreadSynchronizeFcnTy *)getAPIHandle(
+      HandleCudaRT, "cudaThreadSynchronize");
+
+  return 1;
+}
+
+void polly_initDevice(PollyGPUContext **Context, PollyGPUDevice **Device) {
+  int Major = 0, Minor = 0, DeviceID = 0;
+  char DeviceName[256];
+  int DeviceCount = 0;
+
+  /* Get API handles. */
+  if (initialDeviceAPIs() == 0) {
+    fprintf(stdout, "Getting the \"handle\" for the CUDA driver API failed.\n");
+    exit(-1);
+  }
+
+  if (CuInitFcnPtr(0) != CUDA_SUCCESS) {
+    fprintf(stdout, "Initializing the CUDA driver API failed.\n");
+    exit(-1);
+  }
+
+  /* Get number of devices that supports CUDA. */
+  CuDeviceGetCountFcnPtr(&DeviceCount);
+  if (DeviceCount == 0) {
+    fprintf(stdout, "There is no device supporting CUDA.\n");
+    exit(-1);
+  }
+
+  /* We select the 1st device as default. */
+  *Device = malloc(sizeof(PollyGPUDevice));
+  if (*Device == 0) {
+    fprintf(stdout, "Allocate memory for Polly GPU device failed.\n");
+    exit(-1);
+  }
+  CuDeviceGetFcnPtr(&((*Device)->Cuda), 0);
+
+  /* Get compute capabilities and the device name. */
+  CuDeviceComputeCapabilityFcnPtr(&Major, &Minor, (*Device)->Cuda);
+  CuDeviceGetNameFcnPtr(DeviceName, 256, (*Device)->Cuda);
+  fprintf(stderr, "> Running on GPU device %d : %s.\n", DeviceID, DeviceName);
+
+  /* Create context on the device. */
+  *Context = malloc(sizeof(PollyGPUContext));
+  if (*Context == 0) {
+    fprintf(stdout, "Allocate memory for Polly GPU context failed.\n");
+    exit(-1);
+  }
+  CuCtxCreateFcnPtr(&((*Context)->Cuda), 0, (*Device)->Cuda);
+}
+
+void polly_getPTXModule(void *PTXBuffer, PollyGPUModule **Module) {
+  *Module = malloc(sizeof(PollyGPUModule));
+  if (*Module == 0) {
+    fprintf(stdout, "Allocate memory for Polly GPU module failed.\n");
+    exit(-1);
+  }
+
+  if (CuModuleLoadDataExFcnPtr(&((*Module)->Cuda), PTXBuffer, 0, 0, 0) !=
+          CUDA_SUCCESS) {
+    fprintf(stdout, "Loading ptx assembly text failed.\n");
+    exit(-1);
+  }
+}
+
+void polly_getPTXKernelEntry(const char *KernelName, PollyGPUModule *Module,
+                             PollyGPUFunction **Kernel) {
+  *Kernel = malloc(sizeof(PollyGPUFunction));
+  if (*Kernel == 0) {
+    fprintf(stdout, "Allocate memory for Polly GPU kernel failed.\n");
+    exit(-1);
+  }
+
+  /* Locate the kernel entry point. */
+  if (CuModuleGetFunctionFcnPtr(&((*Kernel)->Cuda), Module->Cuda, KernelName) !=
+          CUDA_SUCCESS) {
+    fprintf(stdout, "Loading kernel function failed.\n");
+    exit(-1);
+  }
+}
+
+void polly_startTimerByCudaEvent(PollyGPUEvent **Start, PollyGPUEvent **Stop) {
+  *Start = malloc(sizeof(PollyGPUEvent));
+  if (*Start == 0) {
+    fprintf(stdout, "Allocate memory for Polly GPU start timer failed.\n");
+    exit(-1);
+  }
+  CudaEventCreateFcnPtr(&((*Start)->Cuda));
+
+  *Stop = malloc(sizeof(PollyGPUEvent));
+  if (*Stop == 0) {
+    fprintf(stdout, "Allocate memory for Polly GPU stop timer failed.\n");
+    exit(-1);
+  }
+  CudaEventCreateFcnPtr(&((*Stop)->Cuda));
+
+  /* Record the start time. */
+  CudaEventRecordFcnPtr((*Start)->Cuda, 0);
+}
+
+void polly_stopTimerByCudaEvent(PollyGPUEvent *Start, PollyGPUEvent *Stop,
+                                float *ElapsedTimes) {
+  /* Record the end time. */
+  CudaEventRecordFcnPtr(Stop->Cuda, 0);
+  CudaEventSynchronizeFcnPtr(Start->Cuda);
+  CudaEventSynchronizeFcnPtr(Stop->Cuda);
+  CudaEventElapsedTimeFcnPtr(ElapsedTimes, Start->Cuda, Stop->Cuda);
+  CudaEventDestroyFcnPtr(Start->Cuda);
+  CudaEventDestroyFcnPtr(Stop->Cuda);
+  fprintf(stderr, "Processing time: %f (ms).\n", *ElapsedTimes);
+
+  free(Start);
+  free(Stop);
+}
+
+void polly_allocateMemoryForHostAndDevice(
+    void **HostData, PollyGPUDevicePtr **DevData, int MemSize) {
+  if ((*HostData = (int *)malloc(MemSize)) == 0) {
+    fprintf(stdout, "Could not allocate host memory.\n");
+    exit(-1);
+  }
+
+  *DevData = malloc(sizeof(PollyGPUDevicePtr));
+  if (*DevData == 0) {
+    fprintf(stdout, "Allocate memory for GPU device memory pointer failed.\n");
+    exit(-1);
+  }
+  CuMemAllocFcnPtr(&((*DevData)->Cuda), MemSize);
+}
+
+void polly_copyFromHostToDevice(PollyGPUDevicePtr *DevData, void *HostData,
+                                int MemSize) {
+  CUdeviceptr CuDevData = DevData->Cuda;
+  CuMemcpyHtoDFcnPtr(CuDevData, HostData, MemSize);
+}
+
+void polly_copyFromDeviceToHost(void *HostData, PollyGPUDevicePtr *DevData,
+                                int MemSize) {
+  if (CuMemcpyDtoHFcnPtr(HostData, DevData->Cuda, MemSize) != CUDA_SUCCESS) {
+    fprintf(stdout, "Copying results from device to host memory failed.\n");
+    exit(-1);
+  }
+}
+
+void polly_setKernelParameters(PollyGPUFunction *Kernel, int BlockWidth,
+                               int BlockHeight, PollyGPUDevicePtr *DevData) {
+  int ParamOffset = 0;
+
+  CuFuncSetBlockShapeFcnPtr(Kernel->Cuda, BlockWidth, BlockHeight, 1);
+  CuParamSetvFcnPtr(Kernel->Cuda, ParamOffset, &(DevData->Cuda),
+                    sizeof(DevData->Cuda));
+  ParamOffset += sizeof(DevData->Cuda);
+  CuParamSetSizeFcnPtr(Kernel->Cuda, ParamOffset);
+}
+
+void polly_launchKernel(PollyGPUFunction *Kernel, int GridWidth,
+                        int GridHeight) {
+  if (CuLaunchGridFcnPtr(Kernel->Cuda, GridWidth, GridHeight) != CUDA_SUCCESS) {
+    fprintf(stdout, "Launching CUDA kernel failed.\n");
+    exit(-1);
+  }
+  CudaThreadSynchronizeFcnPtr();
+  fprintf(stdout, "CUDA kernel launched.\n");
+}
+
+void polly_cleanupGPGPUResources(
+    void *HostData, PollyGPUDevicePtr *DevData, PollyGPUModule *Module,
+    PollyGPUContext *Context, PollyGPUFunction *Kernel) {
+  if (HostData) {
+    free(HostData);
+    HostData = 0;
+  }
+
+  if (DevData->Cuda) {
+    CuMemFreeFcnPtr(DevData->Cuda);
+    free(DevData);
+  }
+
+  if (Module->Cuda) {
+    CuModuleUnloadFcnPtr(Module->Cuda);
+    free(Module);
+  }
+
+  if (Context->Cuda) {
+    CuCtxDestroyFcnPtr(Context->Cuda);
+    free(Context);
+  }
+
+  if (Kernel) {
+    free(Kernel);
+  }
+
+  dlclose(HandleCuda);
+  dlclose(HandleCudaRT);
+}
diff --git a/final/tools/GPURuntime/GPUJIT.h b/final/tools/GPURuntime/GPUJIT.h
new file mode 100644
index 0000000..5ed41ce
--- /dev/null
+++ b/final/tools/GPURuntime/GPUJIT.h
@@ -0,0 +1,106 @@
+/******************************************************************************/
+/*                                                                            */
+/*                     The LLVM Compiler Infrastructure                       */
+/*                                                                            */
+/* This file is dual licensed under the MIT and the University of Illinois    */
+/* Open Source License. See LICENSE.TXT for details.                          */
+/*                                                                            */
+/******************************************************************************/
+/*                                                                            */
+/*  This file defines GPUJIT.                                                 */
+/*                                                                            */
+/******************************************************************************/
+
+#ifndef GPUJIT_H_
+#define GPUJIT_H_
+
+/*
+ * The following demostrates how we can use the GPURuntime library to
+ * execute a GPU kernel.
+ *
+ * char KernelString[] = "\n\
+ *   .version 1.4\n\
+ *   .target sm_10, map_f64_to_f32\n\
+ *   .entry _Z8myKernelPi (\n\
+ *   .param .u64 __cudaparm__Z8myKernelPi_data)\n\
+ *   {\n\
+ *     .reg .u16 %rh<4>;\n\
+ *     .reg .u32 %r<5>;\n\
+ *     .reg .u64 %rd<6>;\n\
+ *     cvt.u32.u16     %r1, %tid.x;\n\
+ *     mov.u16         %rh1, %ctaid.x;\n\
+ *     mov.u16         %rh2, %ntid.x;\n\
+ *     mul.wide.u16    %r2, %rh1, %rh2;\n\
+ *     add.u32         %r3, %r1, %r2;\n\
+ *     ld.param.u64    %rd1, [__cudaparm__Z8myKernelPi_data];\n\
+ *     cvt.s64.s32     %rd2, %r3;\n\
+ *     mul.wide.s32    %rd3, %r3, 4;\n\
+ *     add.u64         %rd4, %rd1, %rd3;\n\
+ *     st.global.s32   [%rd4+0], %r3;\n\
+ *     exit;\n\
+ *   }\n\
+ * ";
+ *
+ * const char *Entry = "_Z8myKernelPi";
+ *
+ * int main() {
+ *   PollyGPUContext *Context;
+ *   PollyGPUModule *Module;
+ *   PollyGPUFunction *Kernel;
+ *   PollyGPUDevice *Device;
+ *   PollyGPUDevicePtr *PtrDevData;
+ *   int *HostData;
+ *   PollyGPUEvent *Start;
+ *   PollyGPUEvent *Stop;
+ *   float *ElapsedTime;
+ *   int MemSize;
+ *   int BlockWidth = 16;
+ *   int BlockHeight = 16;
+ *   int GridWidth = 8;
+ *   int GridHeight = 8;
+ *
+ *   MemSize = 256*64*sizeof(int);
+ *   polly_initDevice(&Context, &Device);
+ *   polly_getPTXModule(KernelString, &Module);
+ *   polly_getPTXKernelEntry(Entry, Module, &Kernel);
+ *   polly_allocateMemoryForHostAndDevice(&HostData, &DevData, MemSize);
+ *   polly_setKernelParameters(Kernel, BlockWidth, BlockHeight, DevData);
+ *   polly_startTimerByCudaEvent(&Start, &Stop);
+ *   polly_launchKernel(Kernel, GridWidth, GridHeight);
+ *   polly_copyFromDeviceToHost(HostData, DevData, MemSize);
+ *   polly_stopTimerByCudaEvent(Start, Stop, ElapsedTime);
+ *   polly_cleanupGPGPUResources(HostData, DevData, Module, Context, Kernel);
+ * }
+ *
+ */
+
+typedef struct PollyGPUContextT PollyGPUContext;
+typedef struct PollyGPUModuleT PollyGPUModule;
+typedef struct PollyGPUFunctionT PollyGPUFunction;
+typedef struct PollyGPUDeviceT PollyGPUDevice;
+typedef struct PollyGPUDevicePtrT PollyGPUDevicePtr;
+typedef struct PollyGPUEventT PollyGPUEvent;
+
+void polly_initDevice(PollyGPUContext **Context, PollyGPUDevice **Device);
+void polly_getPTXModule(void *PTXBuffer, PollyGPUModule **Module);
+void polly_getPTXKernelEntry(const char *KernelName, PollyGPUModule *Module,
+                             PollyGPUFunction **Kernel);
+void polly_startTimerByCudaEvent(PollyGPUEvent **Start, PollyGPUEvent **Stop);
+void polly_stopTimerByCudaEvent(PollyGPUEvent *Start, PollyGPUEvent *Stop,
+                                float *ElapsedTimes);
+void polly_copyFromHostToDevice(PollyGPUDevicePtr *DevData, void *HostData,
+                                int MemSize);
+void polly_copyFromDeviceToHost(void *HostData, PollyGPUDevicePtr *DevData,
+                                int MemSize);
+void polly_allocateMemoryForHostAndDevice(void **HostData,
+                                          PollyGPUDevicePtr **DevData,
+                                          int MemSize);
+void polly_setKernelParameters(PollyGPUFunction *Kernel, int BlockWidth,
+                               int BlockHeight, PollyGPUDevicePtr *DevData);
+void polly_launchKernel(PollyGPUFunction *Kernel, int GridWidth,
+                        int GridHeight);
+void polly_cleanupGPGPUResources(void *HostData, PollyGPUDevicePtr *DevData,
+                                 PollyGPUModule *Module,
+                                 PollyGPUContext *Context,
+                                 PollyGPUFunction *Kernel);
+#endif /* GPUJIT_H_ */
diff --git a/final/tools/GPURuntime/LICENSE.TXT b/final/tools/GPURuntime/LICENSE.TXT
new file mode 100644
index 0000000..e2461ab
--- /dev/null
+++ b/final/tools/GPURuntime/LICENSE.TXT
@@ -0,0 +1,75 @@
+==============================================================================
+GPURuntime License
+==============================================================================
+
+The GPURuntime library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license.  As a user of this code you may choose
+to use it under either license.  As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+    Polly Team
+
+    http://polly.llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/final/tools/GPURuntime/Makefile b/final/tools/GPURuntime/Makefile
new file mode 100644
index 0000000..4822f70
--- /dev/null
+++ b/final/tools/GPURuntime/Makefile
@@ -0,0 +1,16 @@
+##===- polly/lib/GPURuntime/Makefile -----------------------*- Makefile -*-===##
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+LIBRARYNAME = libGPURuntime
+LOADABLE_MODULE = 1
+
+include $(LEVEL)/Makefile.config
+CPP.Flags += $(POLLY_INC)
+include $(LEVEL)/Makefile.common
diff --git a/final/tools/Makefile b/final/tools/Makefile
new file mode 100644
index 0000000..21b6a42
--- /dev/null
+++ b/final/tools/Makefile
@@ -0,0 +1,20 @@
+##===- tools/Makefile --------------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ..
+DIRS :=
+
+include $(LEVEL)/Makefile.config
+
+# GPU Runtime Support
+ifeq ($(CUDALIB_FOUND), yes)
+ DIRS += GPURuntime
+endif
+
+include $(LEVEL)/Makefile.common
diff --git a/final/utils/arcanist/LitTestEngine/__phutil_library_init__.php b/final/utils/arcanist/LitTestEngine/__phutil_library_init__.php
new file mode 100644
index 0000000..72dd4a7
--- /dev/null
+++ b/final/utils/arcanist/LitTestEngine/__phutil_library_init__.php
@@ -0,0 +1,3 @@
+<?php
+
+phutil_register_library('lit-test-engine', __FILE__);
diff --git a/final/utils/arcanist/LitTestEngine/__phutil_library_map__.php b/final/utils/arcanist/LitTestEngine/__phutil_library_map__.php
new file mode 100644
index 0000000..6607226
--- /dev/null
+++ b/final/utils/arcanist/LitTestEngine/__phutil_library_map__.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is automatically generated. Use 'arc liberate' to rebuild it.
+ * @generated
+ * @phutil-library-version 2
+ */
+
+phutil_register_library_map(array(
+  '__library_version__' => 2,
+  'class' =>
+  array(
+    'LitTestEngine' => 'src/LitTestEngine.php',
+  ),
+  'function' =>
+  array(
+  ),
+  'xmap' =>
+  array(
+    'LitTestEngine' => 'ArcanistBaseUnitTestEngine',
+  ),
+));
diff --git a/final/utils/arcanist/LitTestEngine/src/LitTestEngine.php b/final/utils/arcanist/LitTestEngine/src/LitTestEngine.php
new file mode 100644
index 0000000..eb495be
--- /dev/null
+++ b/final/utils/arcanist/LitTestEngine/src/LitTestEngine.php
@@ -0,0 +1,268 @@
+<?php
+
+/**
+ * llvm-lit wrapper
+ *
+ * To use, set unit.engine in .arcconfig, or use --engine flag
+ * with arc unit.
+ *
+ * This file was authored by Clemens Hammacher <hammacher@cs.uni-saarland.de>
+ * and initially used in the Sambamba project (www.sambamba.org).
+ *
+ * @group unitrun
+ */
+final class LitTestEngine extends ArcanistUnitTestEngine {
+
+    protected function supportsRunAllTests() {
+        return true;
+    }
+
+    private function progress($results, $numTests) {
+        static $colors = array(
+            ArcanistUnitTestResult::RESULT_PASS => 'green',
+            ArcanistUnitTestResult::RESULT_FAIL => 'red',
+            ArcanistUnitTestResult::RESULT_SKIP => 'yellow',
+            ArcanistUnitTestResult::RESULT_BROKEN => 'red',
+            ArcanistUnitTestResult::RESULT_UNSOUND => 'yellow',
+            ArcanistUnitTestResult::RESULT_POSTPONED => 'yellow'
+        );
+
+        $s = "\t[\033[0;30m";
+        $number = -1;
+        $lastColor = "";
+        $lastResult = "";
+        $lastNumber = "";
+        foreach ($results as $result) {
+            $color = $colors[$result->getResult()];
+            if (!$color && $lastColor)
+                $s .= "</bg>";
+            elseif (!$lastColor && $color)
+                $s .= "<bg:$color>";
+            elseif ($lastColor !== $color)
+                $s .= "</bg><bg:$color>";
+            if ($number <= 0)
+              $number = 1;
+            elseif ($lastResult == $result->getResult())
+              $number += 1;
+            else
+              $number = 1;
+            if ($number > 1 && $number <= 10)
+              $s = substr($s, 0, -1);
+            elseif ($number > 10 && $number <= 100)
+              $s = substr($s, 0, -2);
+            elseif ($number > 100 && $number <= 1000)
+              $s = substr($s, 0, -3);
+            $s .= "$number";
+            $lastNumber = $number;
+            $lastResult = $result->getResult();
+            $lastColor = $color;
+        }
+        if ($lastColor)
+            $s .= "</bg>";
+        $s .= "\033[0m";
+        $c = count($results);
+        if ($numTests)
+          $s .=  " $c/$numTests]";
+        else
+            $s .= " $c]";
+        return phutil_console_format($s);
+    }
+
+    public function run() {
+
+        $projectRoot = $this->getWorkingCopy()->getProjectRoot();
+        $cwd = getcwd();
+        $buildDir = $this->findBuildDirectory($projectRoot, $cwd);
+        print "Using build directory '$buildDir'\n";
+        $makeVars = $this->getMakeVars($buildDir);
+        $lit = $this->findLitExecutable($makeVars);
+        print "Using lit executable '$lit'\n";
+
+        // We have to modify the format string, because llvm-lit does not like a '' argument
+        $cmd = '%s ' . ($this->getEnableAsyncTests() ? '' : '-j1 ') .'%s 2>&1';
+        $litFuture = new ExecFuture($cmd, $lit, $buildDir."/test");
+        $out = "";
+        $results = array();
+        $lastTime = microtime(true);
+        $ready = false;
+        $dots = "";
+        $numTests = 0;
+        while (!$ready) {
+            $ready = $litFuture->isReady();
+            $newout = $litFuture->readStdout();
+            if (strlen($newout) == 0) {
+                usleep(100);
+                continue;
+            }
+            $out .= $newout;
+            if ($ready && strlen($out) > 0 && substr($out, -1) != "\n")
+                $out .= "\n";
+
+            while (($nlPos = strpos($out, "\n")) !== FALSE) {
+                $line = substr($out, 0, $nlPos+1);
+                $out = substr($out, $nlPos+1);
+
+                $res = ArcanistUnitTestResult::RESULT_UNSOUND;
+                if (substr($line, 0, 6) == "PASS: ") {
+                    $res = ArcanistUnitTestResult::RESULT_PASS;
+                } elseif (substr($line, 0, 6) == "FAIL: ") {
+                    $res = ArcanistUnitTestResult::RESULT_FAIL;
+                } elseif (substr($line, 0, 7) == "XPASS: ") {
+                    $res = ArcanistUnitTestResult::RESULT_FAIL;
+                } elseif (substr($line, 0, 7) == "XFAIL: ") {
+                    $res = ArcanistUnitTestResult::RESULT_PASS;
+                } elseif (substr($line, 0, 13) == "UNSUPPORTED: ") {
+                    $res = ArcanistUnitTestResult::RESULT_SKIP;
+                } elseif (!$numTests && preg_match('/Testing: ([0-9]+) tests/', $line, $matches)) {
+                    $numTests = (int)$matches[1];
+                }
+                if ($res == ArcanistUnitTestResult::RESULT_FAIL)
+                    print "\033[0A";
+                if ($res != ArcanistUnitTestResult::RESULT_SKIP && $res != ArcanistUnitTestResult::RESULT_PASS)
+                    print "\r\033[K\033[0A".$line.self::progress($results, $numTests);
+                if ($res == ArcanistUnitTestResult::RESULT_UNSOUND)
+                    continue;
+                $result = new ArcanistUnitTestResult();
+                $result->setName(trim(substr($line, strpos($line, ':') + 1)));
+                $result->setResult($res);
+                $newTime = microtime(true);
+                $result->setDuration($newTime - $lastTime);
+                $lastTime = $newTime;
+                $results[] = $result;
+                $dots .= ".";
+                print "\r\033[K\033[0A".self::progress($results, $numTests);
+            }
+        }
+        list ($out1,$out2) = $litFuture->read();
+        print $out1;
+        if ($out2) {
+            throw new Exception('There was error output, even though it should have been redirected to stdout.');
+        }
+        print "\n";
+
+        $timeThreshold = 0.050;
+        $interestingTests = array();
+        foreach ($results as $result) {
+          if ($result->getResult() != "pass")
+            $interestingTests[] = $result;
+          if ($result->getDuration() > $timeThreshold)
+            $interestingTests[] = $result;
+        }
+        return $interestingTests;
+    }
+
+    /**
+     * Try to find the build directory of the project, starting from the
+     * project root, and the current working directory.
+     * Also, the environment variable POLLY_BIN_DIR is read to determine the
+     * correct location.
+     *
+     * Search locations are:
+     * $POLLY_BIN_DIR (environment variable)
+     * <root>/build
+     * <root>.build
+     * <root>-build
+     * <root:s/src/build>
+     * <cwd>
+     *
+     * This list might be extended in the future according to other common
+     * setup.
+     *
+     * @param   projectRoot   Directory of the project root
+     * @param   cwd           Current working directory
+     * @return  string        Presumable build directory
+     */
+    public static function findBuildDirectory($projectRoot, $cwd) {
+
+        $projectRoot = rtrim($projectRoot, DIRECTORY_SEPARATOR);
+        $cwd = rtrim($cwd, DIRECTORY_SEPARATOR);
+
+        $tries = array();
+
+        $smbbin_env = getenv("POLLY_BIN_DIR");
+        if ($smbbin_env)
+            $tries[] = $smbbin_env;
+
+        $tries[] = $projectRoot.DIRECTORY_SEPARATOR."build";
+        $tries[] = $projectRoot.".build";
+        $tries[] = $projectRoot."-build";
+
+        // Try to replace each occurence of "src" by "build" (also within path components, like llvm-src)
+        $srcPos = 0;
+        while (($srcPos = strpos($projectRoot, "src", $srcPos)) !== FALSE) {
+            $tries[] = substr($projectRoot, 0, $srcPos)."build".substr($projectRoot, $srcPos+3);
+            $srcPos += 3;
+        }
+
+        $tries[] = $cwd;
+
+        foreach ($tries as $try) {
+            if (is_dir($try) &&
+                file_exists($try.DIRECTORY_SEPARATOR."Makefile") &&
+                (file_exists($try.DIRECTORY_SEPARATOR."test".DIRECTORY_SEPARATOR."lit.site.cfg") ||
+                file_exists($try.DIRECTORY_SEPARATOR."test".DIRECTORY_SEPARATOR."lit.cfg")))
+                return Filesystem::resolvePath($try);
+        }
+
+        throw new Exception("Did not find a build directory for project '$projectRoot', cwd '$cwd'.\n" .
+            "Make sure to have a 'test' directory inside build, which contains lit.cfg or lit.site.cfg.\n" .
+            "You might have to run 'make test' once in the build directory.");
+    }
+
+    /**
+     * Try to find the llvm build directory, based on the make variables
+     * as determined by getMakeVars().
+     *
+     * @param   makeVars      The determined make variables
+     * @return  string        Presumable llvm build directory
+     */
+    public static function getLLVMObjDir($makeVars) {
+        if (!array_key_exists('LLVM_OBJ_ROOT', $makeVars))
+            throw new Exception("Make variables (determined by 'make printvars') does not contain LLVM_OBJ_ROOT.");
+        $llvmObjDir = $makeVars['LLVM_OBJ_ROOT'];
+        if (!is_dir($llvmObjDir))
+            throw new Exception("LLVM_OBJ_ROOT ('$llvmObjDir') is no directory.");
+        return $llvmObjDir;
+    }
+
+    /**
+     * Determine the make variables, by calling 'make printvars' in the
+     * build directory.
+     *
+     * @param   buildDir      The determined build directory
+     * @return  map<str,str>  Map of printed make variables to values
+     */
+    public static function getMakeVars($buildDir) {
+        $litFuture = new ExecFuture('make -C %s printvars', $buildDir);
+        list($stdout, $stderr) = $litFuture->resolvex(10);
+        print $stderr;
+        $makeVars = array();
+
+        foreach (explode("\n", $stdout) as $line) {
+            $components = explode(':', $line);
+            if (count($components) == 3)
+                $makeVars[trim($components[1])] = trim($components[2]);
+        }
+
+        return $makeVars;
+    }
+
+    /**
+     * Return full path to the llvm-lit executable.
+     *
+     * @param   llvmObjDir    The determined llvm build directory
+     * @return  string        Full path to the llvm-lit executable
+     */
+    public static function findLitExecutable($makeVars) {
+        $llvmObjDir = self::getLLVMObjDir($makeVars);
+        $buildMode = array_key_exists('BuildMode', $makeVars) ? $makeVars['BuildMode'] : '';
+
+        if (!$buildMode)
+            throw new Exception("Make variables (determined by 'make printvars') does not contain BuildMode.");
+
+        $lit = $llvmObjDir.DIRECTORY_SEPARATOR.$buildMode.DIRECTORY_SEPARATOR.'bin'.DIRECTORY_SEPARATOR.'llvm-lit';
+        if (!is_executable($lit))
+            throw new Exception("File does not exists or is not executable: $lit");
+        return $lit;
+    }
+}
diff --git a/final/utils/argparse.py b/final/utils/argparse.py
new file mode 100644
index 0000000..a060129
--- /dev/null
+++ b/final/utils/argparse.py
@@ -0,0 +1,2353 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy
+# of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Command-line parsing library
+
+This module is an optparse-inspired command-line parsing library that:
+
+    - handles both optional and positional arguments
+    - produces highly informative usage messages
+    - supports parsers that dispatch to sub-parsers
+
+The following is a simple usage example that sums integers from the
+command-line and writes the result to a file::
+
+    parser = argparse.ArgumentParser(
+        description='sum the integers at the command line')
+    parser.add_argument(
+        'integers', metavar='int', nargs='+', type=int,
+        help='an integer to be summed')
+    parser.add_argument(
+        '--log', default=sys.stdout, type=argparse.FileType('w'),
+        help='the file where the sum should be written')
+    args = parser.parse_args()
+    args.log.write('%s' % sum(args.integers))
+    args.log.close()
+
+The module contains the following public classes:
+
+    - ArgumentParser -- The main entry point for command-line parsing. As the
+        example above shows, the add_argument() method is used to populate
+        the parser with actions for optional and positional arguments. Then
+        the parse_args() method is invoked to convert the args at the
+        command-line into an object with attributes.
+
+    - ArgumentError -- The exception raised by ArgumentParser objects when
+        there are errors with the parser's actions. Errors raised while
+        parsing the command-line are caught by ArgumentParser and emitted
+        as command-line messages.
+
+    - FileType -- A factory for defining types of files to be created. As the
+        example above shows, instances of FileType are typically passed as
+        the type= argument of add_argument() calls.
+
+    - Action -- The base class for parser actions. Typically actions are
+        selected by passing strings like 'store_true' or 'append_const' to
+        the action= argument of add_argument(). However, for greater
+        customization of ArgumentParser actions, subclasses of Action may
+        be defined and passed as the action= argument.
+
+    - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
+        ArgumentDefaultsHelpFormatter -- Formatter classes which
+        may be passed as the formatter_class= argument to the
+        ArgumentParser constructor. HelpFormatter is the default,
+        RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
+        not to change the formatting for help text, and
+        ArgumentDefaultsHelpFormatter adds information about argument defaults
+        to the help.
+
+All other classes in this module are considered implementation details.
+(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
+considered public as object names -- the API of the formatter objects is
+still considered an implementation detail.)
+"""
+
+__version__ = '1.1'
+__all__ = [
+    'ArgumentParser',
+    'ArgumentError',
+    'Namespace',
+    'Action',
+    'FileType',
+    'HelpFormatter',
+    'RawDescriptionHelpFormatter',
+    'RawTextHelpFormatter',
+    'ArgumentDefaultsHelpFormatter',
+]
+
+
+import copy as _copy
+import os as _os
+import re as _re
+import sys as _sys
+import textwrap as _textwrap
+
+from gettext import gettext as _
+
+try:
+    _set = set
+except NameError:
+    from sets import Set as _set
+
+try:
+    _basestring = basestring
+except NameError:
+    _basestring = str
+
+try:
+    _sorted = sorted
+except NameError:
+
+    def _sorted(iterable, reverse=False):
+        result = list(iterable)
+        result.sort()
+        if reverse:
+            result.reverse()
+        return result
+
+
+def _callable(obj):
+    return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
+
+# silence Python 2.6 buggy warnings about Exception.message
+if _sys.version_info[:2] == (2, 6):
+    import warnings
+    warnings.filterwarnings(
+        action='ignore',
+        message='BaseException.message has been deprecated as of Python 2.6',
+        category=DeprecationWarning,
+        module='argparse')
+
+
+SUPPRESS = '==SUPPRESS=='
+
+OPTIONAL = '?'
+ZERO_OR_MORE = '*'
+ONE_OR_MORE = '+'
+PARSER = 'A...'
+REMAINDER = '...'
+
+# =============================
+# Utility functions and classes
+# =============================
+
+class _AttributeHolder(object):
+    """Abstract base class that provides __repr__.
+
+    The __repr__ method returns a string in the format::
+        ClassName(attr=name, attr=name, ...)
+    The attributes are determined either by a class-level attribute,
+    '_kwarg_names', or by inspecting the instance __dict__.
+    """
+
+    def __repr__(self):
+        type_name = type(self).__name__
+        arg_strings = []
+        for arg in self._get_args():
+            arg_strings.append(repr(arg))
+        for name, value in self._get_kwargs():
+            arg_strings.append('%s=%r' % (name, value))
+        return '%s(%s)' % (type_name, ', '.join(arg_strings))
+
+    def _get_kwargs(self):
+        return _sorted(self.__dict__.items())
+
+    def _get_args(self):
+        return []
+
+
+def _ensure_value(namespace, name, value):
+    if getattr(namespace, name, None) is None:
+        setattr(namespace, name, value)
+    return getattr(namespace, name)
+
+
+# ===============
+# Formatting Help
+# ===============
+
+class HelpFormatter(object):
+    """Formatter for generating usage messages and argument help strings.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def __init__(self,
+                 prog,
+                 indent_increment=2,
+                 max_help_position=24,
+                 width=None):
+
+        # default setting for width
+        if width is None:
+            try:
+                width = int(_os.environ['COLUMNS'])
+            except (KeyError, ValueError):
+                width = 80
+            width -= 2
+
+        self._prog = prog
+        self._indent_increment = indent_increment
+        self._max_help_position = max_help_position
+        self._width = width
+
+        self._current_indent = 0
+        self._level = 0
+        self._action_max_length = 0
+
+        self._root_section = self._Section(self, None)
+        self._current_section = self._root_section
+
+        self._whitespace_matcher = _re.compile(r'\s+')
+        self._long_break_matcher = _re.compile(r'\n\n\n+')
+
+    # ===============================
+    # Section and indentation methods
+    # ===============================
+    def _indent(self):
+        self._current_indent += self._indent_increment
+        self._level += 1
+
+    def _dedent(self):
+        self._current_indent -= self._indent_increment
+        assert self._current_indent >= 0, 'Indent decreased below 0.'
+        self._level -= 1
+
+    class _Section(object):
+
+        def __init__(self, formatter, parent, heading=None):
+            self.formatter = formatter
+            self.parent = parent
+            self.heading = heading
+            self.items = []
+
+        def format_help(self):
+            # format the indented section
+            if self.parent is not None:
+                self.formatter._indent()
+            join = self.formatter._join_parts
+            for func, args in self.items:
+                func(*args)
+            item_help = join([func(*args) for func, args in self.items])
+            if self.parent is not None:
+                self.formatter._dedent()
+
+            # return nothing if the section was empty
+            if not item_help:
+                return ''
+
+            # add the heading if the section was non-empty
+            if self.heading is not SUPPRESS and self.heading is not None:
+                current_indent = self.formatter._current_indent
+                heading = '%*s%s:\n' % (current_indent, '', self.heading)
+            else:
+                heading = ''
+
+            # join the section-initial newline, the heading and the help
+            return join(['\n', heading, item_help, '\n'])
+
+    def _add_item(self, func, args):
+        self._current_section.items.append((func, args))
+
+    # ========================
+    # Message building methods
+    # ========================
+    def start_section(self, heading):
+        self._indent()
+        section = self._Section(self, self._current_section, heading)
+        self._add_item(section.format_help, [])
+        self._current_section = section
+
+    def end_section(self):
+        self._current_section = self._current_section.parent
+        self._dedent()
+
+    def add_text(self, text):
+        if text is not SUPPRESS and text is not None:
+            self._add_item(self._format_text, [text])
+
+    def add_usage(self, usage, actions, groups, prefix=None):
+        if usage is not SUPPRESS:
+            args = usage, actions, groups, prefix
+            self._add_item(self._format_usage, args)
+
+    def add_argument(self, action):
+        if action.help is not SUPPRESS:
+
+            # find all invocations
+            get_invocation = self._format_action_invocation
+            invocations = [get_invocation(action)]
+            for subaction in self._iter_indented_subactions(action):
+                invocations.append(get_invocation(subaction))
+
+            # update the maximum item length
+            invocation_length = max([len(s) for s in invocations])
+            action_length = invocation_length + self._current_indent
+            self._action_max_length = max(self._action_max_length,
+                                          action_length)
+
+            # add the item to the list
+            self._add_item(self._format_action, [action])
+
+    def add_arguments(self, actions):
+        for action in actions:
+            self.add_argument(action)
+
+    # =======================
+    # Help-formatting methods
+    # =======================
+    def format_help(self):
+        help = self._root_section.format_help()
+        if help:
+            help = self._long_break_matcher.sub('\n\n', help)
+            help = help.strip('\n') + '\n'
+        return help
+
+    def _join_parts(self, part_strings):
+        return ''.join([part
+                        for part in part_strings
+                        if part and part is not SUPPRESS])
+
+    def _format_usage(self, usage, actions, groups, prefix):
+        if prefix is None:
+            prefix = _('usage: ')
+
+        # if usage is specified, use that
+        if usage is not None:
+            usage = usage % dict(prog=self._prog)
+
+        # if no optionals or positionals are available, usage is just prog
+        elif usage is None and not actions:
+            usage = '%(prog)s' % dict(prog=self._prog)
+
+        # if optionals and positionals are available, calculate usage
+        elif usage is None:
+            prog = '%(prog)s' % dict(prog=self._prog)
+
+            # split optionals from positionals
+            optionals = []
+            positionals = []
+            for action in actions:
+                if action.option_strings:
+                    optionals.append(action)
+                else:
+                    positionals.append(action)
+
+            # build full usage string
+            format = self._format_actions_usage
+            action_usage = format(optionals + positionals, groups)
+            usage = ' '.join([s for s in [prog, action_usage] if s])
+
+            # wrap the usage parts if it's too long
+            text_width = self._width - self._current_indent
+            if len(prefix) + len(usage) > text_width:
+
+                # break usage into wrappable parts
+                part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
+                opt_usage = format(optionals, groups)
+                pos_usage = format(positionals, groups)
+                opt_parts = _re.findall(part_regexp, opt_usage)
+                pos_parts = _re.findall(part_regexp, pos_usage)
+                assert ' '.join(opt_parts) == opt_usage
+                assert ' '.join(pos_parts) == pos_usage
+
+                # helper for wrapping lines
+                def get_lines(parts, indent, prefix=None):
+                    lines = []
+                    line = []
+                    if prefix is not None:
+                        line_len = len(prefix) - 1
+                    else:
+                        line_len = len(indent) - 1
+                    for part in parts:
+                        if line_len + 1 + len(part) > text_width:
+                            lines.append(indent + ' '.join(line))
+                            line = []
+                            line_len = len(indent) - 1
+                        line.append(part)
+                        line_len += len(part) + 1
+                    if line:
+                        lines.append(indent + ' '.join(line))
+                    if prefix is not None:
+                        lines[0] = lines[0][len(indent):]
+                    return lines
+
+                # if prog is short, follow it with optionals or positionals
+                if len(prefix) + len(prog) <= 0.75 * text_width:
+                    indent = ' ' * (len(prefix) + len(prog) + 1)
+                    if opt_parts:
+                        lines = get_lines([prog] + opt_parts, indent, prefix)
+                        lines.extend(get_lines(pos_parts, indent))
+                    elif pos_parts:
+                        lines = get_lines([prog] + pos_parts, indent, prefix)
+                    else:
+                        lines = [prog]
+
+                # if prog is long, put it on its own line
+                else:
+                    indent = ' ' * len(prefix)
+                    parts = opt_parts + pos_parts
+                    lines = get_lines(parts, indent)
+                    if len(lines) > 1:
+                        lines = []
+                        lines.extend(get_lines(opt_parts, indent))
+                        lines.extend(get_lines(pos_parts, indent))
+                    lines = [prog] + lines
+
+                # join lines into usage
+                usage = '\n'.join(lines)
+
+        # prefix with 'usage:'
+        return '%s%s\n\n' % (prefix, usage)
+
+    def _format_actions_usage(self, actions, groups):
+        # find group indices and identify actions in groups
+        group_actions = _set()
+        inserts = {}
+        for group in groups:
+            try:
+                start = actions.index(group._group_actions[0])
+            except ValueError:
+                continue
+            else:
+                end = start + len(group._group_actions)
+                if actions[start:end] == group._group_actions:
+                    for action in group._group_actions:
+                        group_actions.add(action)
+                    if not group.required:
+                        inserts[start] = '['
+                        inserts[end] = ']'
+                    else:
+                        inserts[start] = '('
+                        inserts[end] = ')'
+                    for i in range(start + 1, end):
+                        inserts[i] = '|'
+
+        # collect all actions format strings
+        parts = []
+        for i, action in enumerate(actions):
+
+            # suppressed arguments are marked with None
+            # remove | separators for suppressed arguments
+            if action.help is SUPPRESS:
+                parts.append(None)
+                if inserts.get(i) == '|':
+                    inserts.pop(i)
+                elif inserts.get(i + 1) == '|':
+                    inserts.pop(i + 1)
+
+            # produce all arg strings
+            elif not action.option_strings:
+                part = self._format_args(action, action.dest)
+
+                # if it's in a group, strip the outer []
+                if action in group_actions:
+                    if part[0] == '[' and part[-1] == ']':
+                        part = part[1:-1]
+
+                # add the action string to the list
+                parts.append(part)
+
+            # produce the first way to invoke the option in brackets
+            else:
+                option_string = action.option_strings[0]
+
+                # if the Optional doesn't take a value, format is:
+                #    -s or --long
+                if action.nargs == 0:
+                    part = '%s' % option_string
+
+                # if the Optional takes a value, format is:
+                #    -s ARGS or --long ARGS
+                else:
+                    default = action.dest.upper()
+                    args_string = self._format_args(action, default)
+                    part = '%s %s' % (option_string, args_string)
+
+                # make it look optional if it's not required or in a group
+                if not action.required and action not in group_actions:
+                    part = '[%s]' % part
+
+                # add the action string to the list
+                parts.append(part)
+
+        # insert things at the necessary indices
+        for i in _sorted(inserts, reverse=True):
+            parts[i:i] = [inserts[i]]
+
+        # join all the action items with spaces
+        text = ' '.join([item for item in parts if item is not None])
+
+        # clean up separators for mutually exclusive groups
+        open = r'[\[(]'
+        close = r'[\])]'
+        text = _re.sub(r'(%s) ' % open, r'\1', text)
+        text = _re.sub(r' (%s)' % close, r'\1', text)
+        text = _re.sub(r'%s *%s' % (open, close), r'', text)
+        text = _re.sub(r'\(([^|]*)\)', r'\1', text)
+        text = text.strip()
+
+        # return the text
+        return text
+
+    def _format_text(self, text):
+        if '%(prog)' in text:
+            text = text % dict(prog=self._prog)
+        text_width = self._width - self._current_indent
+        indent = ' ' * self._current_indent
+        return self._fill_text(text, text_width, indent) + '\n\n'
+
+    def _format_action(self, action):
+        # determine the required width and the entry label
+        help_position = min(self._action_max_length + 2,
+                            self._max_help_position)
+        help_width = self._width - help_position
+        action_width = help_position - self._current_indent - 2
+        action_header = self._format_action_invocation(action)
+
+        # ho nelp; start on same line and add a final newline
+        if not action.help:
+            tup = self._current_indent, '', action_header
+            action_header = '%*s%s\n' % tup
+
+        # short action name; start on the same line and pad two spaces
+        elif len(action_header) <= action_width:
+            tup = self._current_indent, '', action_width, action_header
+            action_header = '%*s%-*s  ' % tup
+            indent_first = 0
+
+        # long action name; start on the next line
+        else:
+            tup = self._current_indent, '', action_header
+            action_header = '%*s%s\n' % tup
+            indent_first = help_position
+
+        # collect the pieces of the action help
+        parts = [action_header]
+
+        # if there was help for the action, add lines of help text
+        if action.help:
+            help_text = self._expand_help(action)
+            help_lines = self._split_lines(help_text, help_width)
+            parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
+            for line in help_lines[1:]:
+                parts.append('%*s%s\n' % (help_position, '', line))
+
+        # or add a newline if the description doesn't end with one
+        elif not action_header.endswith('\n'):
+            parts.append('\n')
+
+        # if there are any sub-actions, add their help as well
+        for subaction in self._iter_indented_subactions(action):
+            parts.append(self._format_action(subaction))
+
+        # return a single string
+        return self._join_parts(parts)
+
+    def _format_action_invocation(self, action):
+        if not action.option_strings:
+            metavar, = self._metavar_formatter(action, action.dest)(1)
+            return metavar
+
+        else:
+            parts = []
+
+            # if the Optional doesn't take a value, format is:
+            #    -s, --long
+            if action.nargs == 0:
+                parts.extend(action.option_strings)
+
+            # if the Optional takes a value, format is:
+            #    -s ARGS, --long ARGS
+            else:
+                default = action.dest.upper()
+                args_string = self._format_args(action, default)
+                for option_string in action.option_strings:
+                    parts.append('%s %s' % (option_string, args_string))
+
+            return ', '.join(parts)
+
+    def _metavar_formatter(self, action, default_metavar):
+        if action.metavar is not None:
+            result = action.metavar
+        elif action.choices is not None:
+            choice_strs = [str(choice) for choice in action.choices]
+            result = '{%s}' % ','.join(choice_strs)
+        else:
+            result = default_metavar
+
+        def format(tuple_size):
+            if isinstance(result, tuple):
+                return result
+            else:
+                return (result, ) * tuple_size
+        return format
+
+    def _format_args(self, action, default_metavar):
+        get_metavar = self._metavar_formatter(action, default_metavar)
+        if action.nargs is None:
+            result = '%s' % get_metavar(1)
+        elif action.nargs == OPTIONAL:
+            result = '[%s]' % get_metavar(1)
+        elif action.nargs == ZERO_OR_MORE:
+            result = '[%s [%s ...]]' % get_metavar(2)
+        elif action.nargs == ONE_OR_MORE:
+            result = '%s [%s ...]' % get_metavar(2)
+        elif action.nargs == REMAINDER:
+            result = '...'
+        elif action.nargs == PARSER:
+            result = '%s ...' % get_metavar(1)
+        else:
+            formats = ['%s' for _ in range(action.nargs)]
+            result = ' '.join(formats) % get_metavar(action.nargs)
+        return result
+
+    def _expand_help(self, action):
+        params = dict(vars(action), prog=self._prog)
+        for name in list(params):
+            if params[name] is SUPPRESS:
+                del params[name]
+        for name in list(params):
+            if hasattr(params[name], '__name__'):
+                params[name] = params[name].__name__
+        if params.get('choices') is not None:
+            choices_str = ', '.join([str(c) for c in params['choices']])
+            params['choices'] = choices_str
+        return self._get_help_string(action) % params
+
+    def _iter_indented_subactions(self, action):
+        try:
+            get_subactions = action._get_subactions
+        except AttributeError:
+            pass
+        else:
+            self._indent()
+            for subaction in get_subactions():
+                yield subaction
+            self._dedent()
+
+    def _split_lines(self, text, width):
+        text = self._whitespace_matcher.sub(' ', text).strip()
+        return _textwrap.wrap(text, width)
+
+    def _fill_text(self, text, width, indent):
+        text = self._whitespace_matcher.sub(' ', text).strip()
+        return _textwrap.fill(text, width, initial_indent=indent,
+                                           subsequent_indent=indent)
+
+    def _get_help_string(self, action):
+        return action.help
+
+
+class RawDescriptionHelpFormatter(HelpFormatter):
+    """Help message formatter which retains any formatting in descriptions.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def _fill_text(self, text, width, indent):
+        return ''.join([indent + line for line in text.splitlines(True)])
+
+
+class RawTextHelpFormatter(RawDescriptionHelpFormatter):
+    """Help message formatter which retains formatting of all help text.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def _split_lines(self, text, width):
+        return text.splitlines()
+
+
+class ArgumentDefaultsHelpFormatter(HelpFormatter):
+    """Help message formatter which adds default values to argument help.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def _get_help_string(self, action):
+        help = action.help
+        if '%(default)' not in action.help:
+            if action.default is not SUPPRESS:
+                defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
+                if action.option_strings or action.nargs in defaulting_nargs:
+                    help += ' (default: %(default)s)'
+        return help
+
+
+# =====================
+# Options and Arguments
+# =====================
+
+def _get_action_name(argument):
+    if argument is None:
+        return None
+    elif argument.option_strings:
+        return  '/'.join(argument.option_strings)
+    elif argument.metavar not in (None, SUPPRESS):
+        return argument.metavar
+    elif argument.dest not in (None, SUPPRESS):
+        return argument.dest
+    else:
+        return None
+
+
+class ArgumentError(Exception):
+    """An error from creating or using an argument (optional or positional).
+
+    The string value of this exception is the message, augmented with
+    information about the argument that caused it.
+    """
+
+    def __init__(self, argument, message):
+        self.argument_name = _get_action_name(argument)
+        self.message = message
+
+    def __str__(self):
+        if self.argument_name is None:
+            format = '%(message)s'
+        else:
+            format = 'argument %(argument_name)s: %(message)s'
+        return format % dict(message=self.message,
+                             argument_name=self.argument_name)
+
+
+class ArgumentTypeError(Exception):
+    """An error from trying to convert a command line string to a type."""
+    pass
+
+
+# ==============
+# Action classes
+# ==============
+
+class Action(_AttributeHolder):
+    """Information about how to convert command line strings to Python objects.
+
+    Action objects are used by an ArgumentParser to represent the information
+    needed to parse a single argument from one or more strings from the
+    command line. The keyword arguments to the Action constructor are also
+    all attributes of Action instances.
+
+    Keyword Arguments:
+
+        - option_strings -- A list of command-line option strings which
+            should be associated with this action.
+
+        - dest -- The name of the attribute to hold the created object(s)
+
+        - nargs -- The number of command-line arguments that should be
+            consumed. By default, one argument will be consumed and a single
+            value will be produced.  Other values include:
+                - N (an integer) consumes N arguments (and produces a list)
+                - '?' consumes zero or one arguments
+                - '*' consumes zero or more arguments (and produces a list)
+                - '+' consumes one or more arguments (and produces a list)
+            Note that the difference between the default and nargs=1 is that
+            with the default, a single value will be produced, while with
+            nargs=1, a list containing a single value will be produced.
+
+        - const -- The value to be produced if the option is specified and the
+            option uses an action that takes no values.
+
+        - default -- The value to be produced if the option is not specified.
+
+        - type -- The type which the command-line arguments should be converted
+            to, should be one of 'string', 'int', 'float', 'complex' or a
+            callable object that accepts a single string argument. If None,
+            'string' is assumed.
+
+        - choices -- A container of values that should be allowed. If not None,
+            after a command-line argument has been converted to the appropriate
+            type, an exception will be raised if it is not a member of this
+            collection.
+
+        - required -- True if the action must always be specified at the
+            command line. This is only meaningful for optional command-line
+            arguments.
+
+        - help -- The help string describing the argument.
+
+        - metavar -- The name to be used for the option's argument with the
+            help string. If None, the 'dest' value will be used as the name.
+    """
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 nargs=None,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        self.option_strings = option_strings
+        self.dest = dest
+        self.nargs = nargs
+        self.const = const
+        self.default = default
+        self.type = type
+        self.choices = choices
+        self.required = required
+        self.help = help
+        self.metavar = metavar
+
+    def _get_kwargs(self):
+        names = [
+            'option_strings',
+            'dest',
+            'nargs',
+            'const',
+            'default',
+            'type',
+            'choices',
+            'help',
+            'metavar',
+        ]
+        return [(name, getattr(self, name)) for name in names]
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        raise NotImplementedError(_('.__call__() not defined'))
+
+
+class _StoreAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 nargs=None,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        if nargs == 0:
+            raise ValueError('nargs for store actions must be > 0; if you '
+                             'have nothing to store, actions such as store '
+                             'true or store const may be more appropriate')
+        if const is not None and nargs != OPTIONAL:
+            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+        super(_StoreAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=nargs,
+            const=const,
+            default=default,
+            type=type,
+            choices=choices,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        setattr(namespace, self.dest, values)
+
+
+class _StoreConstAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 const,
+                 default=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        super(_StoreConstAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=0,
+            const=const,
+            default=default,
+            required=required,
+            help=help)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        setattr(namespace, self.dest, self.const)
+
+
+class _StoreTrueAction(_StoreConstAction):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 default=False,
+                 required=False,
+                 help=None):
+        super(_StoreTrueAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            const=True,
+            default=default,
+            required=required,
+            help=help)
+
+
+class _StoreFalseAction(_StoreConstAction):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 default=True,
+                 required=False,
+                 help=None):
+        super(_StoreFalseAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            const=False,
+            default=default,
+            required=required,
+            help=help)
+
+
+class _AppendAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 nargs=None,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        if nargs == 0:
+            raise ValueError('nargs for append actions must be > 0; if arg '
+                             'strings are not supplying the value to append, '
+                             'the append const action may be more appropriate')
+        if const is not None and nargs != OPTIONAL:
+            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+        super(_AppendAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=nargs,
+            const=const,
+            default=default,
+            type=type,
+            choices=choices,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        items = _copy.copy(_ensure_value(namespace, self.dest, []))
+        items.append(values)
+        setattr(namespace, self.dest, items)
+
+
+class _AppendConstAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 const,
+                 default=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        super(_AppendConstAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=0,
+            const=const,
+            default=default,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        items = _copy.copy(_ensure_value(namespace, self.dest, []))
+        items.append(self.const)
+        setattr(namespace, self.dest, items)
+
+
+class _CountAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 default=None,
+                 required=False,
+                 help=None):
+        super(_CountAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=0,
+            default=default,
+            required=required,
+            help=help)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        new_count = _ensure_value(namespace, self.dest, 0) + 1
+        setattr(namespace, self.dest, new_count)
+
+
+class _HelpAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest=SUPPRESS,
+                 default=SUPPRESS,
+                 help=None):
+        super(_HelpAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            default=default,
+            nargs=0,
+            help=help)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        parser.print_help()
+        parser.exit()
+
+
+class _VersionAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 version=None,
+                 dest=SUPPRESS,
+                 default=SUPPRESS,
+                 help=None):
+        super(_VersionAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            default=default,
+            nargs=0,
+            help=help)
+        self.version = version
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        version = self.version
+        if version is None:
+            version = parser.version
+        formatter = parser._get_formatter()
+        formatter.add_text(version)
+        parser.exit(message=formatter.format_help())
+
+
+class _SubParsersAction(Action):
+
+    class _ChoicesPseudoAction(Action):
+
+        def __init__(self, name, help):
+            sup = super(_SubParsersAction._ChoicesPseudoAction, self)
+            sup.__init__(option_strings=[], dest=name, help=help)
+
+    def __init__(self,
+                 option_strings,
+                 prog,
+                 parser_class,
+                 dest=SUPPRESS,
+                 help=None,
+                 metavar=None):
+
+        self._prog_prefix = prog
+        self._parser_class = parser_class
+        self._name_parser_map = {}
+        self._choices_actions = []
+
+        super(_SubParsersAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=PARSER,
+            choices=self._name_parser_map,
+            help=help,
+            metavar=metavar)
+
+    def add_parser(self, name, **kwargs):
+        # set prog from the existing prefix
+        if kwargs.get('prog') is None:
+            kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
+
+        # create a pseudo-action to hold the choice help
+        if 'help' in kwargs:
+            help = kwargs.pop('help')
+            choice_action = self._ChoicesPseudoAction(name, help)
+            self._choices_actions.append(choice_action)
+
+        # create the parser and add it to the map
+        parser = self._parser_class(**kwargs)
+        self._name_parser_map[name] = parser
+        return parser
+
+    def _get_subactions(self):
+        return self._choices_actions
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        parser_name = values[0]
+        arg_strings = values[1:]
+
+        # set the parser name if requested
+        if self.dest is not SUPPRESS:
+            setattr(namespace, self.dest, parser_name)
+
+        # select the parser
+        try:
+            parser = self._name_parser_map[parser_name]
+        except KeyError:
+            tup = parser_name, ', '.join(self._name_parser_map)
+            msg = _('unknown parser %r (choices: %s)' % tup)
+            raise ArgumentError(self, msg)
+
+        # parse all the remaining options into the namespace
+        parser.parse_args(arg_strings, namespace)
+
+
+# ==============
+# Type classes
+# ==============
+
+class FileType(object):
+    """Factory for creating file object types
+
+    Instances of FileType are typically passed as type= arguments to the
+    ArgumentParser add_argument() method.
+
+    Keyword Arguments:
+        - mode -- A string indicating how the file is to be opened. Accepts the
+            same values as the builtin open() function.
+        - bufsize -- The file's desired buffer size. Accepts the same values as
+            the builtin open() function.
+    """
+
+    def __init__(self, mode='r', bufsize=None):
+        self._mode = mode
+        self._bufsize = bufsize
+
+    def __call__(self, string):
+        # the special argument "-" means sys.std{in,out}
+        if string == '-':
+            if 'r' in self._mode:
+                return _sys.stdin
+            elif 'w' in self._mode:
+                return _sys.stdout
+            else:
+                msg = _('argument "-" with mode %r' % self._mode)
+                raise ValueError(msg)
+
+        # all other arguments are used as file names
+        if self._bufsize:
+            return open(string, self._mode, self._bufsize)
+        else:
+            return open(string, self._mode)
+
+    def __repr__(self):
+        args = [self._mode, self._bufsize]
+        args_str = ', '.join([repr(arg) for arg in args if arg is not None])
+        return '%s(%s)' % (type(self).__name__, args_str)
+
+# ===========================
+# Optional and Positional Parsing
+# ===========================
+
+class Namespace(_AttributeHolder):
+    """Simple object for storing attributes.
+
+    Implements equality by attribute names and values, and provides a simple
+    string representation.
+    """
+
+    def __init__(self, **kwargs):
+        for name in kwargs:
+            setattr(self, name, kwargs[name])
+
+    def __eq__(self, other):
+        return vars(self) == vars(other)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __contains__(self, key):
+        return key in self.__dict__
+
+
+class _ActionsContainer(object):
+
+    def __init__(self,
+                 description,
+                 prefix_chars,
+                 argument_default,
+                 conflict_handler):
+        super(_ActionsContainer, self).__init__()
+
+        self.description = description
+        self.argument_default = argument_default
+        self.prefix_chars = prefix_chars
+        self.conflict_handler = conflict_handler
+
+        # set up registries
+        self._registries = {}
+
+        # register actions
+        self.register('action', None, _StoreAction)
+        self.register('action', 'store', _StoreAction)
+        self.register('action', 'store_const', _StoreConstAction)
+        self.register('action', 'store_true', _StoreTrueAction)
+        self.register('action', 'store_false', _StoreFalseAction)
+        self.register('action', 'append', _AppendAction)
+        self.register('action', 'append_const', _AppendConstAction)
+        self.register('action', 'count', _CountAction)
+        self.register('action', 'help', _HelpAction)
+        self.register('action', 'version', _VersionAction)
+        self.register('action', 'parsers', _SubParsersAction)
+
+        # raise an exception if the conflict handler is invalid
+        self._get_handler()
+
+        # action storage
+        self._actions = []
+        self._option_string_actions = {}
+
+        # groups
+        self._action_groups = []
+        self._mutually_exclusive_groups = []
+
+        # defaults storage
+        self._defaults = {}
+
+        # determines whether an "option" looks like a negative number
+        self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
+
+        # whether or not there are any optionals that look like negative
+        # numbers -- uses a list so it can be shared and edited
+        self._has_negative_number_optionals = []
+
+    # ====================
+    # Registration methods
+    # ====================
+    def register(self, registry_name, value, object):
+        registry = self._registries.setdefault(registry_name, {})
+        registry[value] = object
+
+    def _registry_get(self, registry_name, value, default=None):
+        return self._registries[registry_name].get(value, default)
+
+    # ==================================
+    # Namespace default accessor methods
+    # ==================================
+    def set_defaults(self, **kwargs):
+        self._defaults.update(kwargs)
+
+        # if these defaults match any existing arguments, replace
+        # the previous default on the object with the new one
+        for action in self._actions:
+            if action.dest in kwargs:
+                action.default = kwargs[action.dest]
+
+    def get_default(self, dest):
+        for action in self._actions:
+            if action.dest == dest and action.default is not None:
+                return action.default
+        return self._defaults.get(dest, None)
+
+
+    # =======================
+    # Adding argument actions
+    # =======================
+    def add_argument(self, *args, **kwargs):
+        """
+        add_argument(dest, ..., name=value, ...)
+        add_argument(option_string, option_string, ..., name=value, ...)
+        """
+
+        # if no positional args are supplied or only one is supplied and
+        # it doesn't look like an option string, parse a positional
+        # argument
+        chars = self.prefix_chars
+        if not args or len(args) == 1 and args[0][0] not in chars:
+            if args and 'dest' in kwargs:
+                raise ValueError('dest supplied twice for positional argument')
+            kwargs = self._get_positional_kwargs(*args, **kwargs)
+
+        # otherwise, we're adding an optional argument
+        else:
+            kwargs = self._get_optional_kwargs(*args, **kwargs)
+
+        # if no default was supplied, use the parser-level default
+        if 'default' not in kwargs:
+            dest = kwargs['dest']
+            if dest in self._defaults:
+                kwargs['default'] = self._defaults[dest]
+            elif self.argument_default is not None:
+                kwargs['default'] = self.argument_default
+
+        # create the action object, and add it to the parser
+        action_class = self._pop_action_class(kwargs)
+        if not _callable(action_class):
+            raise ValueError('unknown action "%s"' % action_class)
+        action = action_class(**kwargs)
+
+        # raise an error if the action type is not callable
+        type_func = self._registry_get('type', action.type, action.type)
+        if not _callable(type_func):
+            raise ValueError('%r is not callable' % type_func)
+
+        return self._add_action(action)
+
+    def add_argument_group(self, *args, **kwargs):
+        group = _ArgumentGroup(self, *args, **kwargs)
+        self._action_groups.append(group)
+        return group
+
+    def add_mutually_exclusive_group(self, **kwargs):
+        group = _MutuallyExclusiveGroup(self, **kwargs)
+        self._mutually_exclusive_groups.append(group)
+        return group
+
+    def _add_action(self, action):
+        # resolve any conflicts
+        self._check_conflict(action)
+
+        # add to actions list
+        self._actions.append(action)
+        action.container = self
+
+        # index the action by any option strings it has
+        for option_string in action.option_strings:
+            self._option_string_actions[option_string] = action
+
+        # set the flag if any option strings look like negative numbers
+        for option_string in action.option_strings:
+            if self._negative_number_matcher.match(option_string):
+                if not self._has_negative_number_optionals:
+                    self._has_negative_number_optionals.append(True)
+
+        # return the created action
+        return action
+
+    def _remove_action(self, action):
+        self._actions.remove(action)
+
+    def _add_container_actions(self, container):
+        # collect groups by titles
+        title_group_map = {}
+        for group in self._action_groups:
+            if group.title in title_group_map:
+                msg = _('cannot merge actions - two groups are named %r')
+                raise ValueError(msg % (group.title))
+            title_group_map[group.title] = group
+
+        # map each action to its group
+        group_map = {}
+        for group in container._action_groups:
+
+            # if a group with the title exists, use that, otherwise
+            # create a new group matching the container's group
+            if group.title not in title_group_map:
+                title_group_map[group.title] = self.add_argument_group(
+                    title=group.title,
+                    description=group.description,
+                    conflict_handler=group.conflict_handler)
+
+            # map the actions to their new group
+            for action in group._group_actions:
+                group_map[action] = title_group_map[group.title]
+
+        # add container's mutually exclusive groups
+        # NOTE: if add_mutually_exclusive_group ever gains title= and
+        # description= then this code will need to be expanded as above
+        for group in container._mutually_exclusive_groups:
+            mutex_group = self.add_mutually_exclusive_group(
+                required=group.required)
+
+            # map the actions to their new mutex group
+            for action in group._group_actions:
+                group_map[action] = mutex_group
+
+        # add all actions to this container or their group
+        for action in container._actions:
+            group_map.get(action, self)._add_action(action)
+
+    def _get_positional_kwargs(self, dest, **kwargs):
+        # make sure required is not specified
+        if 'required' in kwargs:
+            msg = _("'required' is an invalid argument for positionals")
+            raise TypeError(msg)
+
+        # mark positional arguments as required if at least one is
+        # always required
+        if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
+            kwargs['required'] = True
+        if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
+            kwargs['required'] = True
+
+        # return the keyword arguments with no option strings
+        return dict(kwargs, dest=dest, option_strings=[])
+
+    def _get_optional_kwargs(self, *args, **kwargs):
+        # determine short and long option strings
+        option_strings = []
+        long_option_strings = []
+        for option_string in args:
+            # error on strings that don't start with an appropriate prefix
+            if not option_string[0] in self.prefix_chars:
+                msg = _('invalid option string %r: '
+                        'must start with a character %r')
+                tup = option_string, self.prefix_chars
+                raise ValueError(msg % tup)
+
+            # strings starting with two prefix characters are long options
+            option_strings.append(option_string)
+            if option_string[0] in self.prefix_chars:
+                if len(option_string) > 1:
+                    if option_string[1] in self.prefix_chars:
+                        long_option_strings.append(option_string)
+
+        # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
+        dest = kwargs.pop('dest', None)
+        if dest is None:
+            if long_option_strings:
+                dest_option_string = long_option_strings[0]
+            else:
+                dest_option_string = option_strings[0]
+            dest = dest_option_string.lstrip(self.prefix_chars)
+            if not dest:
+                msg = _('dest= is required for options like %r')
+                raise ValueError(msg % option_string)
+            dest = dest.replace('-', '_')
+
+        # return the updated keyword arguments
+        return dict(kwargs, dest=dest, option_strings=option_strings)
+
+    def _pop_action_class(self, kwargs, default=None):
+        action = kwargs.pop('action', default)
+        return self._registry_get('action', action, action)
+
+    def _get_handler(self):
+        # determine function from conflict handler string
+        handler_func_name = '_handle_conflict_%s' % self.conflict_handler
+        try:
+            return getattr(self, handler_func_name)
+        except AttributeError:
+            msg = _('invalid conflict_resolution value: %r')
+            raise ValueError(msg % self.conflict_handler)
+
+    def _check_conflict(self, action):
+
+        # find all options that conflict with this option
+        confl_optionals = []
+        for option_string in action.option_strings:
+            if option_string in self._option_string_actions:
+                confl_optional = self._option_string_actions[option_string]
+                confl_optionals.append((option_string, confl_optional))
+
+        # resolve any conflicts
+        if confl_optionals:
+            conflict_handler = self._get_handler()
+            conflict_handler(action, confl_optionals)
+
+    def _handle_conflict_error(self, action, conflicting_actions):
+        message = _('conflicting option string(s): %s')
+        conflict_string = ', '.join([option_string
+                                     for option_string, action
+                                     in conflicting_actions])
+        raise ArgumentError(action, message % conflict_string)
+
+    def _handle_conflict_resolve(self, action, conflicting_actions):
+
+        # remove all conflicting options
+        for option_string, action in conflicting_actions:
+
+            # remove the conflicting option
+            action.option_strings.remove(option_string)
+            self._option_string_actions.pop(option_string, None)
+
+            # if the option now has no option string, remove it from the
+            # container holding it
+            if not action.option_strings:
+                action.container._remove_action(action)
+
+
+class _ArgumentGroup(_ActionsContainer):
+
+    def __init__(self, container, title=None, description=None, **kwargs):
+        # add any missing keyword arguments by checking the container
+        update = kwargs.setdefault
+        update('conflict_handler', container.conflict_handler)
+        update('prefix_chars', container.prefix_chars)
+        update('argument_default', container.argument_default)
+        super_init = super(_ArgumentGroup, self).__init__
+        super_init(description=description, **kwargs)
+
+        # group attributes
+        self.title = title
+        self._group_actions = []
+
+        # share most attributes with the container
+        self._registries = container._registries
+        self._actions = container._actions
+        self._option_string_actions = container._option_string_actions
+        self._defaults = container._defaults
+        self._has_negative_number_optionals = \
+            container._has_negative_number_optionals
+
+    def _add_action(self, action):
+        action = super(_ArgumentGroup, self)._add_action(action)
+        self._group_actions.append(action)
+        return action
+
+    def _remove_action(self, action):
+        super(_ArgumentGroup, self)._remove_action(action)
+        self._group_actions.remove(action)
+
+
+class _MutuallyExclusiveGroup(_ArgumentGroup):
+
+    def __init__(self, container, required=False):
+        super(_MutuallyExclusiveGroup, self).__init__(container)
+        self.required = required
+        self._container = container
+
+    def _add_action(self, action):
+        if action.required:
+            msg = _('mutually exclusive arguments must be optional')
+            raise ValueError(msg)
+        action = self._container._add_action(action)
+        self._group_actions.append(action)
+        return action
+
+    def _remove_action(self, action):
+        self._container._remove_action(action)
+        self._group_actions.remove(action)
+
+
+class ArgumentParser(_AttributeHolder, _ActionsContainer):
+    """Object for parsing command line strings into Python objects.
+
+    Keyword Arguments:
+        - prog -- The name of the program (default: sys.argv[0])
+        - usage -- A usage message (default: auto-generated from arguments)
+        - description -- A description of what the program does
+        - epilog -- Text following the argument descriptions
+        - parents -- Parsers whose arguments should be copied into this one
+        - formatter_class -- HelpFormatter class for printing help messages
+        - prefix_chars -- Characters that prefix optional arguments
+        - fromfile_prefix_chars -- Characters that prefix files containing
+            additional arguments
+        - argument_default -- The default value for all arguments
+        - conflict_handler -- String indicating how to handle conflicts
+        - add_help -- Add a -h/-help option
+    """
+
+    def __init__(self,
+                 prog=None,
+                 usage=None,
+                 description=None,
+                 epilog=None,
+                 version=None,
+                 parents=[],
+                 formatter_class=HelpFormatter,
+                 prefix_chars='-',
+                 fromfile_prefix_chars=None,
+                 argument_default=None,
+                 conflict_handler='error',
+                 add_help=True):
+
+        if version is not None:
+            import warnings
+            warnings.warn(
+                """The "version" argument to ArgumentParser is deprecated. """
+                """Please use """
+                """"add_argument(..., action='version', version="N", ...)" """
+                """instead""", DeprecationWarning)
+
+        superinit = super(ArgumentParser, self).__init__
+        superinit(description=description,
+                  prefix_chars=prefix_chars,
+                  argument_default=argument_default,
+                  conflict_handler=conflict_handler)
+
+        # default setting for prog
+        if prog is None:
+            prog = _os.path.basename(_sys.argv[0])
+
+        self.prog = prog
+        self.usage = usage
+        self.epilog = epilog
+        self.version = version
+        self.formatter_class = formatter_class
+        self.fromfile_prefix_chars = fromfile_prefix_chars
+        self.add_help = add_help
+
+        add_group = self.add_argument_group
+        self._positionals = add_group(_('positional arguments'))
+        self._optionals = add_group(_('optional arguments'))
+        self._subparsers = None
+
+        # register types
+        def identity(string):
+            return string
+        self.register('type', None, identity)
+
+        # add help and version arguments if necessary
+        # (using explicit default to override global argument_default)
+        if self.add_help:
+            self.add_argument(
+                '-h', '--help', action='help', default=SUPPRESS,
+                help=_('show this help message and exit'))
+        if self.version:
+            self.add_argument(
+                '-v', '--version', action='version', default=SUPPRESS,
+                version=self.version,
+                help=_("show program's version number and exit"))
+
+        # add parent arguments and defaults
+        for parent in parents:
+            self._add_container_actions(parent)
+            try:
+                defaults = parent._defaults
+            except AttributeError:
+                pass
+            else:
+                self._defaults.update(defaults)
+
+    # =======================
+    # Pretty __repr__ methods
+    # =======================
+    def _get_kwargs(self):
+        names = [
+            'prog',
+            'usage',
+            'description',
+            'version',
+            'formatter_class',
+            'conflict_handler',
+            'add_help',
+        ]
+        return [(name, getattr(self, name)) for name in names]
+
+    # ==================================
+    # Optional/Positional adding methods
+    # ==================================
+    def add_subparsers(self, **kwargs):
+        if self._subparsers is not None:
+            self.error(_('cannot have multiple subparser arguments'))
+
+        # add the parser class to the arguments if it's not present
+        kwargs.setdefault('parser_class', type(self))
+
+        if 'title' in kwargs or 'description' in kwargs:
+            title = _(kwargs.pop('title', 'subcommands'))
+            description = _(kwargs.pop('description', None))
+            self._subparsers = self.add_argument_group(title, description)
+        else:
+            self._subparsers = self._positionals
+
+        # prog defaults to the usage message of this parser, skipping
+        # optional arguments and with no "usage:" prefix
+        if kwargs.get('prog') is None:
+            formatter = self._get_formatter()
+            positionals = self._get_positional_actions()
+            groups = self._mutually_exclusive_groups
+            formatter.add_usage(self.usage, positionals, groups, '')
+            kwargs['prog'] = formatter.format_help().strip()
+
+        # create the parsers action and add it to the positionals list
+        parsers_class = self._pop_action_class(kwargs, 'parsers')
+        action = parsers_class(option_strings=[], **kwargs)
+        self._subparsers._add_action(action)
+
+        # return the created parsers action
+        return action
+
+    def _add_action(self, action):
+        if action.option_strings:
+            self._optionals._add_action(action)
+        else:
+            self._positionals._add_action(action)
+        return action
+
+    def _get_optional_actions(self):
+        return [action
+                for action in self._actions
+                if action.option_strings]
+
+    def _get_positional_actions(self):
+        return [action
+                for action in self._actions
+                if not action.option_strings]
+
+    # =====================================
+    # Command line argument parsing methods
+    # =====================================
+    def parse_args(self, args=None, namespace=None):
+        args, argv = self.parse_known_args(args, namespace)
+        if argv:
+            msg = _('unrecognized arguments: %s')
+            self.error(msg % ' '.join(argv))
+        return args
+
+    def parse_known_args(self, args=None, namespace=None):
+        # args default to the system args
+        if args is None:
+            args = _sys.argv[1:]
+
+        # default Namespace built from parser defaults
+        if namespace is None:
+            namespace = Namespace()
+
+        # add any action defaults that aren't present
+        for action in self._actions:
+            if action.dest is not SUPPRESS:
+                if not hasattr(namespace, action.dest):
+                    if action.default is not SUPPRESS:
+                        default = action.default
+                        if isinstance(action.default, _basestring):
+                            default = self._get_value(action, default)
+                        setattr(namespace, action.dest, default)
+
+        # add any parser defaults that aren't present
+        for dest in self._defaults:
+            if not hasattr(namespace, dest):
+                setattr(namespace, dest, self._defaults[dest])
+
+        # parse the arguments and exit if there are any errors
+        try:
+            return self._parse_known_args(args, namespace)
+        except ArgumentError:
+            err = _sys.exc_info()[1]
+            self.error(str(err))
+
+    def _parse_known_args(self, arg_strings, namespace):
+        # replace arg strings that are file references
+        if self.fromfile_prefix_chars is not None:
+            arg_strings = self._read_args_from_files(arg_strings)
+
+        # map all mutually exclusive arguments to the other arguments
+        # they can't occur with
+        action_conflicts = {}
+        for mutex_group in self._mutually_exclusive_groups:
+            group_actions = mutex_group._group_actions
+            for i, mutex_action in enumerate(mutex_group._group_actions):
+                conflicts = action_conflicts.setdefault(mutex_action, [])
+                conflicts.extend(group_actions[:i])
+                conflicts.extend(group_actions[i + 1:])
+
+        # find all option indices, and determine the arg_string_pattern
+        # which has an 'O' if there is an option at an index,
+        # an 'A' if there is an argument, or a '-' if there is a '--'
+        option_string_indices = {}
+        arg_string_pattern_parts = []
+        arg_strings_iter = iter(arg_strings)
+        for i, arg_string in enumerate(arg_strings_iter):
+
+            # all args after -- are non-options
+            if arg_string == '--':
+                arg_string_pattern_parts.append('-')
+                for arg_string in arg_strings_iter:
+                    arg_string_pattern_parts.append('A')
+
+            # otherwise, add the arg to the arg strings
+            # and note the index if it was an option
+            else:
+                option_tuple = self._parse_optional(arg_string)
+                if option_tuple is None:
+                    pattern = 'A'
+                else:
+                    option_string_indices[i] = option_tuple
+                    pattern = 'O'
+                arg_string_pattern_parts.append(pattern)
+
+        # join the pieces together to form the pattern
+        arg_strings_pattern = ''.join(arg_string_pattern_parts)
+
+        # converts arg strings to the appropriate and then takes the action
+        seen_actions = _set()
+        seen_non_default_actions = _set()
+
+        def take_action(action, argument_strings, option_string=None):
+            seen_actions.add(action)
+            argument_values = self._get_values(action, argument_strings)
+
+            # error if this argument is not allowed with other previously
+            # seen arguments, assuming that actions that use the default
+            # value don't really count as "present"
+            if argument_values is not action.default:
+                seen_non_default_actions.add(action)
+                for conflict_action in action_conflicts.get(action, []):
+                    if conflict_action in seen_non_default_actions:
+                        msg = _('not allowed with argument %s')
+                        action_name = _get_action_name(conflict_action)
+                        raise ArgumentError(action, msg % action_name)
+
+            # take the action if we didn't receive a SUPPRESS value
+            # (e.g. from a default)
+            if argument_values is not SUPPRESS:
+                action(self, namespace, argument_values, option_string)
+
+        # function to convert arg_strings into an optional action
+        def consume_optional(start_index):
+
+            # get the optional identified at this index
+            option_tuple = option_string_indices[start_index]
+            action, option_string, explicit_arg = option_tuple
+
+            # identify additional optionals in the same arg string
+            # (e.g. -xyz is the same as -x -y -z if no args are required)
+            match_argument = self._match_argument
+            action_tuples = []
+            while True:
+
+                # if we found no optional action, skip it
+                if action is None:
+                    extras.append(arg_strings[start_index])
+                    return start_index + 1
+
+                # if there is an explicit argument, try to match the
+                # optional's string arguments to only this
+                if explicit_arg is not None:
+                    arg_count = match_argument(action, 'A')
+
+                    # if the action is a single-dash option and takes no
+                    # arguments, try to parse more single-dash options out
+                    # of the tail of the option string
+                    chars = self.prefix_chars
+                    if arg_count == 0 and option_string[1] not in chars:
+                        action_tuples.append((action, [], option_string))
+                        for char in self.prefix_chars:
+                            option_string = char + explicit_arg[0]
+                            explicit_arg = explicit_arg[1:] or None
+                            optionals_map = self._option_string_actions
+                            if option_string in optionals_map:
+                                action = optionals_map[option_string]
+                                break
+                        else:
+                            msg = _('ignored explicit argument %r')
+                            raise ArgumentError(action, msg % explicit_arg)
+
+                    # if the action expect exactly one argument, we've
+                    # successfully matched the option; exit the loop
+                    elif arg_count == 1:
+                        stop = start_index + 1
+                        args = [explicit_arg]
+                        action_tuples.append((action, args, option_string))
+                        break
+
+                    # error if a double-dash option did not use the
+                    # explicit argument
+                    else:
+                        msg = _('ignored explicit argument %r')
+                        raise ArgumentError(action, msg % explicit_arg)
+
+                # if there is no explicit argument, try to match the
+                # optional's string arguments with the following strings
+                # if successful, exit the loop
+                else:
+                    start = start_index + 1
+                    selected_patterns = arg_strings_pattern[start:]
+                    arg_count = match_argument(action, selected_patterns)
+                    stop = start + arg_count
+                    args = arg_strings[start:stop]
+                    action_tuples.append((action, args, option_string))
+                    break
+
+            # add the Optional to the list and return the index at which
+            # the Optional's string args stopped
+            assert action_tuples
+            for action, args, option_string in action_tuples:
+                take_action(action, args, option_string)
+            return stop
+
+        # the list of Positionals left to be parsed; this is modified
+        # by consume_positionals()
+        positionals = self._get_positional_actions()
+
+        # function to convert arg_strings into positional actions
+        def consume_positionals(start_index):
+            # match as many Positionals as possible
+            match_partial = self._match_arguments_partial
+            selected_pattern = arg_strings_pattern[start_index:]
+            arg_counts = match_partial(positionals, selected_pattern)
+
+            # slice off the appropriate arg strings for each Positional
+            # and add the Positional and its args to the list
+            for action, arg_count in zip(positionals, arg_counts):
+                args = arg_strings[start_index: start_index + arg_count]
+                start_index += arg_count
+                take_action(action, args)
+
+            # slice off the Positionals that we just parsed and return the
+            # index at which the Positionals' string args stopped
+            positionals[:] = positionals[len(arg_counts):]
+            return start_index
+
+        # consume Positionals and Optionals alternately, until we have
+        # passed the last option string
+        extras = []
+        start_index = 0
+        if option_string_indices:
+            max_option_string_index = max(option_string_indices)
+        else:
+            max_option_string_index = -1
+        while start_index <= max_option_string_index:
+
+            # consume any Positionals preceding the next option
+            next_option_string_index = min([
+                index
+                for index in option_string_indices
+                if index >= start_index])
+            if start_index != next_option_string_index:
+                positionals_end_index = consume_positionals(start_index)
+
+                # only try to parse the next optional if we didn't consume
+                # the option string during the positionals parsing
+                if positionals_end_index > start_index:
+                    start_index = positionals_end_index
+                    continue
+                else:
+                    start_index = positionals_end_index
+
+            # if we consumed all the positionals we could and we're not
+            # at the index of an option string, there were extra arguments
+            if start_index not in option_string_indices:
+                strings = arg_strings[start_index:next_option_string_index]
+                extras.extend(strings)
+                start_index = next_option_string_index
+
+            # consume the next optional and any arguments for it
+            start_index = consume_optional(start_index)
+
+        # consume any positionals following the last Optional
+        stop_index = consume_positionals(start_index)
+
+        # if we didn't consume all the argument strings, there were extras
+        extras.extend(arg_strings[stop_index:])
+
+        # if we didn't use all the Positional objects, there were too few
+        # arg strings supplied.
+        if positionals:
+            self.error(_('too few arguments'))
+
+        # make sure all required actions were present
+        for action in self._actions:
+            if action.required:
+                if action not in seen_actions:
+                    name = _get_action_name(action)
+                    self.error(_('argument %s is required') % name)
+
+        # make sure all required groups had one option present
+        for group in self._mutually_exclusive_groups:
+            if group.required:
+                for action in group._group_actions:
+                    if action in seen_non_default_actions:
+                        break
+
+                # if no actions were used, report the error
+                else:
+                    names = [_get_action_name(action)
+                             for action in group._group_actions
+                             if action.help is not SUPPRESS]
+                    msg = _('one of the arguments %s is required')
+                    self.error(msg % ' '.join(names))
+
+        # return the updated namespace and the extra arguments
+        return namespace, extras
+
+    def _read_args_from_files(self, arg_strings):
+        # expand arguments referencing files
+        new_arg_strings = []
+        for arg_string in arg_strings:
+
+            # for regular arguments, just add them back into the list
+            if arg_string[0] not in self.fromfile_prefix_chars:
+                new_arg_strings.append(arg_string)
+
+            # replace arguments referencing files with the file content
+            else:
+                try:
+                    args_file = open(arg_string[1:])
+                    try:
+                        arg_strings = []
+                        for arg_line in args_file.read().splitlines():
+                            for arg in self.convert_arg_line_to_args(arg_line):
+                                arg_strings.append(arg)
+                        arg_strings = self._read_args_from_files(arg_strings)
+                        new_arg_strings.extend(arg_strings)
+                    finally:
+                        args_file.close()
+                except IOError:
+                    err = _sys.exc_info()[1]
+                    self.error(str(err))
+
+        # return the modified argument list
+        return new_arg_strings
+
+    def convert_arg_line_to_args(self, arg_line):
+        return [arg_line]
+
+    def _match_argument(self, action, arg_strings_pattern):
+        # match the pattern for this action to the arg strings
+        nargs_pattern = self._get_nargs_pattern(action)
+        match = _re.match(nargs_pattern, arg_strings_pattern)
+
+        # raise an exception if we weren't able to find a match
+        if match is None:
+            nargs_errors = {
+                None: _('expected one argument'),
+                OPTIONAL: _('expected at most one argument'),
+                ONE_OR_MORE: _('expected at least one argument'),
+            }
+            default = _('expected %s argument(s)') % action.nargs
+            msg = nargs_errors.get(action.nargs, default)
+            raise ArgumentError(action, msg)
+
+        # return the number of arguments matched
+        return len(match.group(1))
+
+    def _match_arguments_partial(self, actions, arg_strings_pattern):
+        # progressively shorten the actions list by slicing off the
+        # final actions until we find a match
+        result = []
+        for i in range(len(actions), 0, -1):
+            actions_slice = actions[:i]
+            pattern = ''.join([self._get_nargs_pattern(action)
+                               for action in actions_slice])
+            match = _re.match(pattern, arg_strings_pattern)
+            if match is not None:
+                result.extend([len(string) for string in match.groups()])
+                break
+
+        # return the list of arg string counts
+        return result
+
+    def _parse_optional(self, arg_string):
+        # if it's an empty string, it was meant to be a positional
+        if not arg_string:
+            return None
+
+        # if it doesn't start with a prefix, it was meant to be positional
+        if not arg_string[0] in self.prefix_chars:
+            return None
+
+        # if the option string is present in the parser, return the action
+        if arg_string in self._option_string_actions:
+            action = self._option_string_actions[arg_string]
+            return action, arg_string, None
+
+        # if it's just a single character, it was meant to be positional
+        if len(arg_string) == 1:
+            return None
+
+        # if the option string before the "=" is present, return the action
+        if '=' in arg_string:
+            option_string, explicit_arg = arg_string.split('=', 1)
+            if option_string in self._option_string_actions:
+                action = self._option_string_actions[option_string]
+                return action, option_string, explicit_arg
+
+        # search through all possible prefixes of the option string
+        # and all actions in the parser for possible interpretations
+        option_tuples = self._get_option_tuples(arg_string)
+
+        # if multiple actions match, the option string was ambiguous
+        if len(option_tuples) > 1:
+            options = ', '.join([option_string
+                for action, option_string, explicit_arg in option_tuples])
+            tup = arg_string, options
+            self.error(_('ambiguous option: %s could match %s') % tup)
+
+        # if exactly one action matched, this segmentation is good,
+        # so return the parsed action
+        elif len(option_tuples) == 1:
+            option_tuple, = option_tuples
+            return option_tuple
+
+        # if it was not found as an option, but it looks like a negative
+        # number, it was meant to be positional
+        # unless there are negative-number-like options
+        if self._negative_number_matcher.match(arg_string):
+            if not self._has_negative_number_optionals:
+                return None
+
+        # if it contains a space, it was meant to be a positional
+        if ' ' in arg_string:
+            return None
+
+        # it was meant to be an optional but there is no such option
+        # in this parser (though it might be a valid option in a subparser)
+        return None, arg_string, None
+
+    def _get_option_tuples(self, option_string):
+        result = []
+
+        # option strings starting with two prefix characters are only
+        # split at the '='
+        chars = self.prefix_chars
+        if option_string[0] in chars and option_string[1] in chars:
+            if '=' in option_string:
+                option_prefix, explicit_arg = option_string.split('=', 1)
+            else:
+                option_prefix = option_string
+                explicit_arg = None
+            for option_string in self._option_string_actions:
+                if option_string.startswith(option_prefix):
+                    action = self._option_string_actions[option_string]
+                    tup = action, option_string, explicit_arg
+                    result.append(tup)
+
+        # single character options can be concatenated with their arguments
+        # but multiple character options always have to have their argument
+        # separate
+        elif option_string[0] in chars and option_string[1] not in chars:
+            option_prefix = option_string
+            explicit_arg = None
+            short_option_prefix = option_string[:2]
+            short_explicit_arg = option_string[2:]
+
+            for option_string in self._option_string_actions:
+                if option_string == short_option_prefix:
+                    action = self._option_string_actions[option_string]
+                    tup = action, option_string, short_explicit_arg
+                    result.append(tup)
+                elif option_string.startswith(option_prefix):
+                    action = self._option_string_actions[option_string]
+                    tup = action, option_string, explicit_arg
+                    result.append(tup)
+
+        # shouldn't ever get here
+        else:
+            self.error(_('unexpected option string: %s') % option_string)
+
+        # return the collected option tuples
+        return result
+
+    def _get_nargs_pattern(self, action):
+        # in all examples below, we have to allow for '--' args
+        # which are represented as '-' in the pattern
+        nargs = action.nargs
+
+        # the default (None) is assumed to be a single argument
+        if nargs is None:
+            nargs_pattern = '(-*A-*)'
+
+        # allow zero or one arguments
+        elif nargs == OPTIONAL:
+            nargs_pattern = '(-*A?-*)'
+
+        # allow zero or more arguments
+        elif nargs == ZERO_OR_MORE:
+            nargs_pattern = '(-*[A-]*)'
+
+        # allow one or more arguments
+        elif nargs == ONE_OR_MORE:
+            nargs_pattern = '(-*A[A-]*)'
+
+        # allow any number of options or arguments
+        elif nargs == REMAINDER:
+            nargs_pattern = '([-AO]*)'
+
+        # allow one argument followed by any number of options or arguments
+        elif nargs == PARSER:
+            nargs_pattern = '(-*A[-AO]*)'
+
+        # all others should be integers
+        else:
+            nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
+
+        # if this is an optional action, -- is not allowed
+        if action.option_strings:
+            nargs_pattern = nargs_pattern.replace('-*', '')
+            nargs_pattern = nargs_pattern.replace('-', '')
+
+        # return the pattern
+        return nargs_pattern
+
+    # ========================
+    # Value conversion methods
+    # ========================
+    def _get_values(self, action, arg_strings):
+        # for everything but PARSER args, strip out '--'
+        if action.nargs not in [PARSER, REMAINDER]:
+            arg_strings = [s for s in arg_strings if s != '--']
+
+        # optional argument produces a default when not present
+        if not arg_strings and action.nargs == OPTIONAL:
+            if action.option_strings:
+                value = action.const
+            else:
+                value = action.default
+            if isinstance(value, _basestring):
+                value = self._get_value(action, value)
+                self._check_value(action, value)
+
+        # when nargs='*' on a positional, if there were no command-line
+        # args, use the default if it is anything other than None
+        elif (not arg_strings and action.nargs == ZERO_OR_MORE and
+              not action.option_strings):
+            if action.default is not None:
+                value = action.default
+            else:
+                value = arg_strings
+            self._check_value(action, value)
+
+        # single argument or optional argument produces a single value
+        elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
+            arg_string, = arg_strings
+            value = self._get_value(action, arg_string)
+            self._check_value(action, value)
+
+        # REMAINDER arguments convert all values, checking none
+        elif action.nargs == REMAINDER:
+            value = [self._get_value(action, v) for v in arg_strings]
+
+        # PARSER arguments convert all values, but check only the first
+        elif action.nargs == PARSER:
+            value = [self._get_value(action, v) for v in arg_strings]
+            self._check_value(action, value[0])
+
+        # all other types of nargs produce a list
+        else:
+            value = [self._get_value(action, v) for v in arg_strings]
+            for v in value:
+                self._check_value(action, v)
+
+        # return the converted value
+        return value
+
+    def _get_value(self, action, arg_string):
+        type_func = self._registry_get('type', action.type, action.type)
+        if not _callable(type_func):
+            msg = _('%r is not callable')
+            raise ArgumentError(action, msg % type_func)
+
+        # convert the value to the appropriate type
+        try:
+            result = type_func(arg_string)
+
+        # ArgumentTypeErrors indicate errors
+        except ArgumentTypeError:
+            name = getattr(action.type, '__name__', repr(action.type))
+            msg = str(_sys.exc_info()[1])
+            raise ArgumentError(action, msg)
+
+        # TypeErrors or ValueErrors also indicate errors
+        except (TypeError, ValueError):
+            name = getattr(action.type, '__name__', repr(action.type))
+            msg = _('invalid %s value: %r')
+            raise ArgumentError(action, msg % (name, arg_string))
+
+        # return the converted value
+        return result
+
+    def _check_value(self, action, value):
+        # converted value must be one of the choices (if specified)
+        if action.choices is not None and value not in action.choices:
+            tup = value, ', '.join(map(repr, action.choices))
+            msg = _('invalid choice: %r (choose from %s)') % tup
+            raise ArgumentError(action, msg)
+
+    # =======================
+    # Help-formatting methods
+    # =======================
+    def format_usage(self):
+        formatter = self._get_formatter()
+        formatter.add_usage(self.usage, self._actions,
+                            self._mutually_exclusive_groups)
+        return formatter.format_help()
+
+    def format_help(self):
+        formatter = self._get_formatter()
+
+        # usage
+        formatter.add_usage(self.usage, self._actions,
+                            self._mutually_exclusive_groups)
+
+        # description
+        formatter.add_text(self.description)
+
+        # positionals, optionals and user-defined groups
+        for action_group in self._action_groups:
+            formatter.start_section(action_group.title)
+            formatter.add_text(action_group.description)
+            formatter.add_arguments(action_group._group_actions)
+            formatter.end_section()
+
+        # epilog
+        formatter.add_text(self.epilog)
+
+        # determine help from format above
+        return formatter.format_help()
+
+    def format_version(self):
+        import warnings
+        warnings.warn(
+            'The format_version method is deprecated -- the "version" '
+            'argument to ArgumentParser is no longer supported.',
+            DeprecationWarning)
+        formatter = self._get_formatter()
+        formatter.add_text(self.version)
+        return formatter.format_help()
+
+    def _get_formatter(self):
+        return self.formatter_class(prog=self.prog)
+
+    # =====================
+    # Help-printing methods
+    # =====================
+    def print_usage(self, file=None):
+        if file is None:
+            file = _sys.stdout
+        self._print_message(self.format_usage(), file)
+
+    def print_help(self, file=None):
+        if file is None:
+            file = _sys.stdout
+        self._print_message(self.format_help(), file)
+
+    def print_version(self, file=None):
+        import warnings
+        warnings.warn(
+            'The print_version method is deprecated -- the "version" '
+            'argument to ArgumentParser is no longer supported.',
+            DeprecationWarning)
+        self._print_message(self.format_version(), file)
+
+    def _print_message(self, message, file=None):
+        if message:
+            if file is None:
+                file = _sys.stderr
+            file.write(message)
+
+    # ===============
+    # Exiting methods
+    # ===============
+    def exit(self, status=0, message=None):
+        if message:
+            self._print_message(message, _sys.stderr)
+        _sys.exit(status)
+
+    def error(self, message):
+        """error(message: string)
+
+        Prints a usage message incorporating the message to stderr and
+        exits.
+
+        If you override this in a subclass, it should not return -- it
+        should either exit or raise an exception.
+        """
+        self.print_usage(_sys.stderr)
+        self.exit(2, _('%s: error: %s\n') % (self.prog, message))
diff --git a/final/utils/check_format.sh b/final/utils/check_format.sh
new file mode 100755
index 0000000..4d7b033
--- /dev/null
+++ b/final/utils/check_format.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+CLANG_FORMAT=${CLANG_FORMAT}
+
+if [ "${CLANG_FORMAT}x" = "x" ]; then
+  CLANG_FORMAT=`which clang-format`
+  if [ "${CLANG_FORMAT}x" = "x" ]; then
+     echo "Error: cannot find clang-format in your path"
+     exit 1
+  fi
+fi
+
+OK=0
+
+for ARG in "$@"
+  do
+    ${CLANG_FORMAT} -style=llvm $ARG | diff -u $ARG - >&2
+
+    if [[ $? -eq 1 ]]; then
+      OK=1
+    fi
+  done
+
+if [[ $OK -eq "1" ]]; then
+  echo "Error: clang-format reported formatting differences"
+  exit 1
+else
+  echo "OK: clang-format reported no formatting differences"
+  exit 0
+fi
+
diff --git a/final/utils/checkout_cloog.sh b/final/utils/checkout_cloog.sh
new file mode 120000
index 0000000..40ad1b8
--- /dev/null
+++ b/final/utils/checkout_cloog.sh
@@ -0,0 +1 @@
+checkout_isl.sh
\ No newline at end of file
diff --git a/final/utils/checkout_isl.sh b/final/utils/checkout_isl.sh
new file mode 100755
index 0000000..ac7dc6f
--- /dev/null
+++ b/final/utils/checkout_isl.sh
@@ -0,0 +1,97 @@
+#!/bin/sh
+
+ISL_HASH="0698f8436c523ecc742b13a9b3aa337cc2421fa2"
+
+PWD=`pwd`
+
+check_command_line() {
+  if [ $# -eq 1 ]
+  then
+    ISL_DIR="${1}"
+  else
+      echo "Usage: " ${0} '<Directory to checkout isl>'
+      exit 1
+  fi
+}
+
+check_isl_directory() {
+  if ! [ -e ${ISL_DIR} ]
+  then
+    echo :: Directory "'${ISL_DIR}'" does not exists. Trying to create it.
+    if ! mkdir -p "${ISL_DIR}"
+    then exit 1
+    fi
+  fi
+
+  if ! [ -d ${ISL_DIR} ]
+  then
+    echo "'${ISL_DIR}'" is not a directory
+    exit 1
+  fi
+
+  # Make it absolute
+  cd ${ISL_DIR}
+  ISL_DIR=`pwd`
+
+  if ! [ -e "${ISL_DIR}/.git" ]
+  then
+    echo ":: No git checkout found"
+    IS_GIT=0
+  else
+    echo ":: Existing git repo found"
+
+    git log cc726006058136865f8c2f496d3df57b9f937ea5 2> /dev/null > /dev/null
+    OUT=$?
+    if [ $OUT -eq 0 ];then
+         echo ":: ISL repository found!"
+         IS_GIT=1
+    else
+         echo ":: Unknown repository found (CLooG?)!"
+         echo ":: Moving it to ${ISL_DIR}_old"
+         run mv ${ISL_DIR} ${ISL_DIR}_old
+         run mkdir ${ISL_DIR}
+         IS_GIT=0
+    fi
+  fi
+}
+
+complain() {
+  echo "$@"
+  exit 1
+}
+
+run() {
+  $cmdPre $*
+  if [ $? != 0 ]
+    then
+    complain $* failed
+  fi
+}
+
+check_command_line $@
+check_isl_directory
+
+if [ ${IS_GIT} -eq 0 ]
+then
+  echo :: Performing initial checkout
+  # Remove the existing CLooG and ISL dirs to avoid crashing older git versions.
+  cd ${ISL_DIR}/..
+  run rmdir "${ISL_DIR}"
+  run git clone http://repo.or.cz/r/isl.git ${ISL_DIR}
+fi
+
+echo :: Fetch version required by Polly
+run cd ${ISL_DIR}
+run git remote update
+
+echo :: Setting isl version
+run cd ${ISL_DIR}
+run git reset --hard "${ISL_HASH}"
+
+echo :: Generating configure
+run cd ${ISL_DIR}
+run ./autogen.sh
+
+echo :: If you install isl the first time run "'./configure'" followed by
+echo :: "'make'" and "'make install'", otherwise, just call "'make'" and
+echo :: "'make'" install.
diff --git a/final/utils/jscop2cloog.py b/final/utils/jscop2cloog.py
new file mode 100755
index 0000000..668f085
--- /dev/null
+++ b/final/utils/jscop2cloog.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+import argparse, os
+import json
+
+def getDomains(scop):
+  statements = scop['statements'];
+  numStatements = len(statements)
+
+  output = "%s\n\n" % str(numStatements)
+
+  for statement in scop['statements']:
+    output += "%s\n\n" % statement['domain']
+    output += "0  0  0               # for future options\n\n"
+
+
+  return output
+
+def getSchedules(scop):
+  statements = scop['statements'];
+  numStatements = len(statements)
+
+  output = "%s\n\n" % str(numStatements)
+
+  for statement in scop['statements']:
+    output += "%s\n\n" % statement['schedule']
+
+  return output
+
+def writeCloog(scop):
+  template = """
+# ---------------------- CONTEXT ----------------------
+c # language is C
+
+# Context (no constraints on two parameters)
+%s
+
+0 # We do not want to set manually the parameter names
+
+# --------------------- STATEMENTS --------------------
+%s
+
+0 # We do not want to set manually the iterator names
+
+# --------------------- SCATTERING --------------------
+%s
+
+0 # We do not want to set manually the scattering dimension names
+"""
+
+  context = scop['context']
+  domains = getDomains(scop)
+  schedules = getSchedules(scop)
+  print template % (context, domains, schedules)
+
+def __main__():
+  description = 'Translate JSCoP into iscc input'
+  parser = argparse.ArgumentParser(description)
+  parser.add_argument('inputFile', metavar='N', type=file,
+                      help='The JSCoP file')
+
+  args = parser.parse_args()
+  inputFile = args.inputFile
+  scop = json.load(inputFile)
+
+  writeCloog(scop)
+
+__main__()
+
diff --git a/final/utils/pyscop/isl.py b/final/utils/pyscop/isl.py
new file mode 100644
index 0000000..0c8de2f
--- /dev/null
+++ b/final/utils/pyscop/isl.py
@@ -0,0 +1,578 @@
+from ctypes import *
+
+isl = cdll.LoadLibrary("libisl.so")
+
+class Context:
+  defaultInstance = None
+  instances = {}
+
+  def __init__(self):
+    ptr = isl.isl_ctx_alloc()
+    self.ptr = ptr
+    Context.instances[ptr] = self
+
+  def __del__(self):
+    isl.isl_ctx_free(self)
+
+  def from_param(self):
+    return self.ptr
+
+  @staticmethod
+  def from_ptr(ptr):
+    return Context.instances[ptr]
+
+  @staticmethod
+  def getDefaultInstance():
+    if Context.defaultInstance == None:
+      Context.defaultInstance = Context()
+
+    return Context.defaultInstance
+
+class IslObject:
+  def __init__(self, string = "", ctx = None, ptr = None):
+    self.initialize_isl_methods()
+    if ptr != None:
+      self.ptr = ptr
+      self.ctx = self.get_isl_method("get_ctx")(self)
+      return
+
+    if ctx == None:
+      ctx = Context.getDefaultInstance()
+
+    self.ctx = ctx
+    self.ptr = self.get_isl_method("read_from_str")(ctx, string, -1)
+
+  def __del__(self):
+    self.get_isl_method("free")(self)
+
+  def from_param(self):
+    return self.ptr
+
+  @property
+  def context(self):
+    return self.ctx
+
+  def __repr__(self):
+    p = Printer(self.ctx)
+    self.to_printer(p)
+    return p.getString();
+
+  def __str__(self):
+    p = Printer(self.ctx)
+    self.to_printer(p)
+    return p.getString();
+
+  @staticmethod
+  def isl_name():
+    return "No isl name available"
+
+  def initialize_isl_methods(self):
+    if hasattr(self.__class__, "initialized"):
+      return
+
+    self.__class__.initalized = True
+    self.get_isl_method("read_from_str").argtypes = [Context, c_char_p, c_int]
+    self.get_isl_method("copy").argtypes = [self.__class__]
+    self.get_isl_method("copy").restype = c_int
+    self.get_isl_method("free").argtypes = [self.__class__]
+    self.get_isl_method("get_ctx").argtypes = [self.__class__]
+    self.get_isl_method("get_ctx").restype = Context.from_ptr 
+    getattr(isl, "isl_printer_print_" + self.isl_name()).argtypes = [Printer, self.__class__]
+
+  def get_isl_method(self, name):
+    return getattr(isl, "isl_" + self.isl_name() + "_" + name)
+
+  def to_printer(self, printer):
+    getattr(isl, "isl_printer_print_" + self.isl_name())(printer, self)
+
+class BSet(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return BSet(ptr = ptr)
+
+  @staticmethod
+  def isl_name():
+    return "basic_set"
+
+class Set(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return Set(ptr = ptr)
+
+  @staticmethod
+  def isl_name():
+    return "set"
+
+class USet(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return USet(ptr = ptr)
+
+  @staticmethod
+  def isl_name():
+    return "union_set"
+
+
+class BMap(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return BMap(ptr = ptr)
+
+  def __mul__(self, set):
+    return self.intersect_domain(set)
+
+  @staticmethod
+  def isl_name():
+    return "basic_map"
+
+class Map(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return Map(ptr = ptr)
+
+  def __mul__(self, set):
+    return self.intersect_domain(set)
+
+  @staticmethod
+  def isl_name():
+    return "map"
+
+  @staticmethod
+  def lex_lt(dim):
+    dim = isl.isl_dim_copy(dim)
+    return isl.isl_map_lex_lt(dim)
+
+  @staticmethod
+  def lex_le(dim):
+    dim = isl.isl_dim_copy(dim)
+    return isl.isl_map_lex_le(dim)
+
+  @staticmethod
+  def lex_gt(dim):
+    dim = isl.isl_dim_copy(dim)
+    return isl.isl_map_lex_gt(dim)
+
+  @staticmethod
+  def lex_ge(dim):
+    dim = isl.isl_dim_copy(dim)
+    return isl.isl_map_lex_ge(dim)
+
+class UMap(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return UMap(ptr = ptr)
+
+  @staticmethod
+  def isl_name():
+    return "union_map"
+
+class Dim(IslObject):
+  @staticmethod
+  def from_ptr(ptr):
+    if not ptr:
+      return
+    return Dim(ptr = ptr)
+
+  @staticmethod
+  def isl_name():
+    return "dim"
+
+  def initialize_isl_methods(self):
+    if hasattr(self.__class__, "initialized"):
+      return
+
+    self.__class__.initalized = True
+    self.get_isl_method("copy").argtypes = [self.__class__]
+    self.get_isl_method("copy").restype = c_int
+    self.get_isl_method("free").argtypes = [self.__class__]
+    self.get_isl_method("get_ctx").argtypes = [self.__class__]
+    self.get_isl_method("get_ctx").restype = Context.from_ptr 
+
+  def __repr__(self):
+    return str(self)
+
+  def __str__(self):
+
+    dimParam = isl.isl_dim_size(self, 1)
+    dimIn = isl.isl_dim_size(self, 2)
+    dimOut = isl.isl_dim_size(self, 3)
+
+    if dimIn:
+      return "<dim In:%s, Out:%s, Param:%s>" % (dimIn, dimOut, dimParam)
+
+    return "<dim Set:%s, Param:%s>" % (dimOut, dimParam)
+
+class Printer:
+  FORMAT_ISL = 0
+  FORMAT_POLYLIB = 1
+  FORMAT_POLYLIB_CONSTRAINTS = 2
+  FORMAT_OMEGA = 3
+  FORMAT_C = 4
+  FORMAT_LATEX = 5
+  FORMAT_EXT_POLYLIB = 6
+
+  def __init__(self, ctx = None):
+    if ctx == None:
+      ctx = Context.getDefaultInstance()
+
+    self.ctx = ctx
+    self.ptr = isl.isl_printer_to_str(ctx)
+
+  def setFormat(self, format):
+    self.ptr = isl.isl_printer_set_output_format(self, format);
+
+  def from_param(self):
+    return self.ptr
+
+  def __del__(self):
+    isl.isl_printer_free(self)
+
+  def getString(self):
+    return isl.isl_printer_get_str(self)
+
+functions = [
+             # Unary properties
+             ("is_empty", BSet, [BSet], c_int),
+             ("is_empty", Set, [Set], c_int),
+             ("is_empty", USet, [USet], c_int),
+             ("is_empty", BMap, [BMap], c_int),
+             ("is_empty", Map, [Map], c_int),
+             ("is_empty", UMap, [UMap], c_int),
+
+    #         ("is_universe", Set, [Set], c_int),
+    #         ("is_universe", Map, [Map], c_int),
+
+             ("is_single_valued", Map, [Map], c_int),
+
+             ("is_bijective", Map, [Map], c_int),
+
+             ("is_wrapping", BSet, [BSet], c_int),
+             ("is_wrapping", Set, [Set], c_int),
+
+             # Binary properties
+             ("is_equal", BSet, [BSet, BSet], c_int),
+             ("is_equal", Set, [Set, Set], c_int),
+             ("is_equal", USet, [USet, USet], c_int),
+             ("is_equal", BMap, [BMap, BMap], c_int),
+             ("is_equal", Map, [Map, Map], c_int),
+             ("is_equal", UMap, [UMap, UMap], c_int),
+
+             # is_disjoint missing
+
+             # ("is_subset", BSet, [BSet, BSet], c_int),
+             ("is_subset", Set, [Set, Set], c_int),
+             ("is_subset", USet, [USet, USet], c_int),
+             ("is_subset", BMap, [BMap, BMap], c_int),
+             ("is_subset", Map, [Map, Map], c_int),
+             ("is_subset", UMap, [UMap, UMap], c_int),
+             #("is_strict_subset", BSet, [BSet, BSet], c_int),
+             ("is_strict_subset", Set, [Set, Set], c_int),
+             ("is_strict_subset", USet, [USet, USet], c_int),
+             ("is_strict_subset", BMap, [BMap, BMap], c_int),
+             ("is_strict_subset", Map, [Map, Map], c_int),
+             ("is_strict_subset", UMap, [UMap, UMap], c_int),
+
+             # Unary Operations
+             ("complement", Set, [Set], Set),
+             ("reverse", BMap, [BMap], BMap),
+             ("reverse", Map, [Map], Map),
+             ("reverse", UMap, [UMap], UMap),
+
+             # Projection missing
+             ("range", BMap, [BMap], BSet),
+             ("range", Map, [Map], Set),
+             ("range", UMap, [UMap], USet),
+             ("domain", BMap, [BMap], BSet),
+             ("domain", Map, [Map], Set),
+             ("domain", UMap, [UMap], USet),
+
+             ("identity", Set, [Set], Map),
+             ("identity", USet, [USet], UMap),
+
+             ("deltas", BMap, [BMap], BSet),
+             ("deltas", Map, [Map], Set),
+             ("deltas", UMap, [UMap], USet),
+
+             ("coalesce", Set, [Set], Set),
+             ("coalesce", USet, [USet], USet),
+             ("coalesce", Map, [Map], Map),
+             ("coalesce", UMap, [UMap], UMap),
+
+             ("detect_equalities", BSet, [BSet], BSet),
+             ("detect_equalities", Set, [Set], Set),
+             ("detect_equalities", USet, [USet], USet),
+             ("detect_equalities", BMap, [BMap], BMap),
+             ("detect_equalities", Map, [Map], Map),
+             ("detect_equalities", UMap, [UMap], UMap),
+
+             ("convex_hull", Set, [Set], Set),
+             ("convex_hull", Map, [Map], Map),
+
+             ("simple_hull", Set, [Set], Set),
+             ("simple_hull", Map, [Map], Map),
+
+             ("affine_hull", BSet, [BSet], BSet),
+             ("affine_hull", Set, [Set], BSet),
+             ("affine_hull", USet, [USet], USet),
+             ("affine_hull", BMap, [BMap], BMap),
+             ("affine_hull", Map, [Map], BMap),
+             ("affine_hull", UMap, [UMap], UMap),
+
+             ("polyhedral_hull", Set, [Set], Set),
+             ("polyhedral_hull", USet, [USet], USet),
+             ("polyhedral_hull", Map, [Map], Map),
+             ("polyhedral_hull", UMap, [UMap], UMap),
+
+             # Power missing
+             # Transitive closure missing
+             # Reaching path lengths missing
+
+             ("wrap", BMap, [BMap], BSet),
+             ("wrap", Map, [Map], Set),
+             ("wrap", UMap, [UMap], USet),
+             ("unwrap", BSet, [BMap], BMap),
+             ("unwrap", Set, [Map], Map),
+             ("unwrap", USet, [UMap], UMap),
+
+             ("flatten", Set, [Set], Set),
+             ("flatten", Map, [Map], Map),
+             ("flatten_map", Set, [Set], Map),
+
+             # Dimension manipulation missing
+
+             # Binary Operations
+             ("intersect", BSet, [BSet, BSet], BSet),
+             ("intersect", Set, [Set, Set], Set),
+             ("intersect", USet, [USet, USet], USet),
+             ("intersect", BMap, [BMap, BMap], BMap),
+             ("intersect", Map, [Map, Map], Map),
+             ("intersect", UMap, [UMap, UMap], UMap),
+             ("intersect_domain", BMap, [BMap, BSet], BMap),
+             ("intersect_domain", Map, [Map, Set], Map),
+             ("intersect_domain", UMap, [UMap, USet], UMap),
+             ("intersect_range", BMap, [BMap, BSet], BMap),
+             ("intersect_range", Map, [Map, Set], Map),
+             ("intersect_range", UMap, [UMap, USet], UMap),
+
+             ("union", BSet, [BSet, BSet], Set),
+             ("union", Set, [Set, Set], Set),
+             ("union", USet, [USet, USet], USet),
+             ("union", BMap, [BMap, BMap], Map),
+             ("union", Map, [Map, Map], Map),
+             ("union", UMap, [UMap, UMap], UMap),
+
+             ("subtract", Set, [Set, Set], Set),
+             ("subtract", Map, [Map, Map], Map),
+             ("subtract", USet, [USet, USet], USet),
+             ("subtract", UMap, [UMap, UMap], UMap),
+
+             ("apply", BSet, [BSet, BMap], BSet),
+             ("apply", Set, [Set, Map], Set),
+             ("apply", USet, [USet, UMap], USet),
+             ("apply_domain", BMap, [BMap, BMap], BMap),
+             ("apply_domain", Map, [Map, Map], Map),
+             ("apply_domain", UMap, [UMap, UMap], UMap),
+             ("apply_range", BMap, [BMap, BMap], BMap),
+             ("apply_range", Map, [Map, Map], Map),
+             ("apply_range", UMap, [UMap, UMap], UMap),
+
+             ("gist", BSet, [BSet, BSet], BSet),
+             ("gist", Set, [Set, Set], Set),
+             ("gist", USet, [USet, USet], USet),
+             ("gist", BMap, [BMap, BMap], BMap),
+             ("gist", Map, [Map, Map], Map),
+             ("gist", UMap, [UMap, UMap], UMap),
+
+             # Lexicographic Optimizations
+             # partial_lexmin missing
+             ("lexmin", BSet, [BSet], BSet),
+             ("lexmin", Set, [Set], Set),
+             ("lexmin", USet, [USet], USet),
+             ("lexmin", BMap, [BMap], BMap),
+             ("lexmin", Map, [Map], Map),
+             ("lexmin", UMap, [UMap], UMap),
+
+             ("lexmax", BSet, [BSet], BSet),
+             ("lexmax", Set, [Set], Set),
+             ("lexmax", USet, [USet], USet),
+             ("lexmax", BMap, [BMap], BMap),
+             ("lexmax", Map, [Map], Map),
+             ("lexmax", UMap, [UMap], UMap),
+
+              # Undocumented
+             ("lex_lt_union_set", USet, [USet, USet], UMap),
+             ("lex_le_union_set", USet, [USet, USet], UMap),
+             ("lex_gt_union_set", USet, [USet, USet], UMap),
+             ("lex_ge_union_set", USet, [USet, USet], UMap),
+
+             ]
+keep_functions = [
+             # Unary properties
+             ("get_dim", BSet, [BSet], Dim),
+             ("get_dim", Set, [Set], Dim),
+             ("get_dim", USet, [USet], Dim),
+             ("get_dim", BMap, [BMap], Dim),
+             ("get_dim", Map, [Map], Dim),
+             ("get_dim", UMap, [UMap], Dim)
+             ]
+
+def addIslFunction(object, name):
+    functionName = "isl_" + object.isl_name() + "_" + name
+    islFunction = getattr(isl, functionName)
+    if len(islFunction.argtypes) == 1:
+      f = lambda a: islFunctionOneOp(islFunction, a)
+    elif len(islFunction.argtypes) == 2:
+      f = lambda a, b: islFunctionTwoOp(islFunction, a, b)
+    object.__dict__[name] = f
+
+
+def islFunctionOneOp(islFunction, ops):
+  ops = getattr(isl, "isl_" + ops.isl_name() + "_copy")(ops)
+  return islFunction(ops)
+
+def islFunctionTwoOp(islFunction, opOne, opTwo):
+  opOne = getattr(isl, "isl_" + opOne.isl_name() + "_copy")(opOne)
+  opTwo = getattr(isl, "isl_" + opTwo.isl_name() + "_copy")(opTwo)
+  return islFunction(opOne, opTwo)
+
+for (operation, base, operands, ret) in functions:
+  functionName = "isl_" + base.isl_name() + "_" + operation
+  islFunction = getattr(isl, functionName)
+  if len(operands) == 1:
+    islFunction.argtypes = [c_int]
+  elif len(operands) == 2:
+    islFunction.argtypes = [c_int, c_int]
+
+  if ret == c_int:
+    islFunction.restype = ret
+  else:
+    islFunction.restype = ret.from_ptr
+
+  addIslFunction(base, operation)
+
+def addIslFunctionKeep(object, name):
+    functionName = "isl_" + object.isl_name() + "_" + name
+    islFunction = getattr(isl, functionName)
+    if len(islFunction.argtypes) == 1:
+      f = lambda a: islFunctionOneOpKeep(islFunction, a)
+    elif len(islFunction.argtypes) == 2:
+      f = lambda a, b: islFunctionTwoOpKeep(islFunction, a, b)
+    object.__dict__[name] = f
+
+def islFunctionOneOpKeep(islFunction, ops):
+  return islFunction(ops)
+
+def islFunctionTwoOpKeep(islFunction, opOne, opTwo):
+  return islFunction(opOne, opTwo)
+
+for (operation, base, operands, ret) in keep_functions:
+  functionName = "isl_" + base.isl_name() + "_" + operation
+  islFunction = getattr(isl, functionName)
+  if len(operands) == 1:
+    islFunction.argtypes = [c_int]
+  elif len(operands) == 2:
+    islFunction.argtypes = [c_int, c_int]
+
+  if ret == c_int:
+    islFunction.restype = ret
+  else:
+    islFunction.restype = ret.from_ptr
+
+  addIslFunctionKeep(base, operation)
+
+isl.isl_ctx_free.argtypes = [Context]
+isl.isl_basic_set_read_from_str.argtypes = [Context, c_char_p, c_int]
+isl.isl_set_read_from_str.argtypes = [Context, c_char_p, c_int]
+isl.isl_basic_set_copy.argtypes = [BSet]
+isl.isl_basic_set_copy.restype = c_int
+isl.isl_set_copy.argtypes = [Set]
+isl.isl_set_copy.restype = c_int
+isl.isl_set_copy.argtypes = [Set]
+isl.isl_set_copy.restype = c_int
+isl.isl_set_free.argtypes = [Set]
+isl.isl_basic_set_get_ctx.argtypes = [BSet]
+isl.isl_basic_set_get_ctx.restype = Context.from_ptr
+isl.isl_set_get_ctx.argtypes = [Set]
+isl.isl_set_get_ctx.restype = Context.from_ptr
+isl.isl_basic_set_get_dim.argtypes = [BSet]
+isl.isl_basic_set_get_dim.restype = Dim.from_ptr
+isl.isl_set_get_dim.argtypes = [Set]
+isl.isl_set_get_dim.restype = Dim.from_ptr
+isl.isl_union_set_get_dim.argtypes = [USet]
+isl.isl_union_set_get_dim.restype = Dim.from_ptr
+
+isl.isl_basic_map_read_from_str.argtypes = [Context, c_char_p, c_int]
+isl.isl_map_read_from_str.argtypes = [Context, c_char_p, c_int]
+isl.isl_basic_map_free.argtypes = [BMap]
+isl.isl_map_free.argtypes = [Map]
+isl.isl_basic_map_copy.argtypes = [BMap]
+isl.isl_basic_map_copy.restype = c_int
+isl.isl_map_copy.argtypes = [Map]
+isl.isl_map_copy.restype = c_int
+isl.isl_map_get_ctx.argtypes = [Map]
+isl.isl_basic_map_get_ctx.argtypes = [BMap]
+isl.isl_basic_map_get_ctx.restype = Context.from_ptr
+isl.isl_map_get_ctx.argtypes = [Map]
+isl.isl_map_get_ctx.restype = Context.from_ptr
+isl.isl_basic_map_get_dim.argtypes = [BMap]
+isl.isl_basic_map_get_dim.restype = Dim.from_ptr
+isl.isl_map_get_dim.argtypes = [Map]
+isl.isl_map_get_dim.restype = Dim.from_ptr
+isl.isl_union_map_get_dim.argtypes = [UMap]
+isl.isl_union_map_get_dim.restype = Dim.from_ptr
+isl.isl_printer_free.argtypes = [Printer]
+isl.isl_printer_to_str.argtypes = [Context]
+isl.isl_printer_print_basic_set.argtypes = [Printer, BSet]
+isl.isl_printer_print_set.argtypes = [Printer, Set]
+isl.isl_printer_print_basic_map.argtypes = [Printer, BMap]
+isl.isl_printer_print_map.argtypes = [Printer, Map]
+isl.isl_printer_get_str.argtypes = [Printer]
+isl.isl_printer_get_str.restype = c_char_p
+isl.isl_printer_set_output_format.argtypes = [Printer, c_int]
+isl.isl_printer_set_output_format.restype = c_int
+isl.isl_dim_size.argtypes = [Dim, c_int]
+isl.isl_dim_size.restype = c_int
+
+isl.isl_map_lex_lt.argtypes = [c_int]
+isl.isl_map_lex_lt.restype = Map.from_ptr
+isl.isl_map_lex_le.argtypes = [c_int]
+isl.isl_map_lex_le.restype = Map.from_ptr
+isl.isl_map_lex_gt.argtypes = [c_int]
+isl.isl_map_lex_gt.restype = Map.from_ptr
+isl.isl_map_lex_ge.argtypes = [c_int]
+isl.isl_map_lex_ge.restype = Map.from_ptr
+
+isl.isl_union_map_compute_flow.argtypes = [c_int, c_int, c_int, c_int, c_void_p,
+                                           c_void_p, c_void_p, c_void_p]
+
+def dependences(sink, must_source, may_source, schedule):
+  sink = getattr(isl, "isl_" + sink.isl_name() + "_copy")(sink)
+  must_source = getattr(isl, "isl_" + must_source.isl_name() + "_copy")(must_source)
+  may_source = getattr(isl, "isl_" + may_source.isl_name() + "_copy")(may_source)
+  schedule = getattr(isl, "isl_" + schedule.isl_name() + "_copy")(schedule)
+  must_dep = c_int()
+  may_dep = c_int()
+  must_no_source = c_int()
+  may_no_source = c_int()
+  isl.isl_union_map_compute_flow(sink, must_source, may_source, schedule, \
+                                 byref(must_dep), byref(may_dep),
+                                 byref(must_no_source),
+                                 byref(may_no_source))
+
+  return (UMap.from_ptr(must_dep), UMap.from_ptr(may_dep), \
+          USet.from_ptr(must_no_source), USet.from_ptr(may_no_source))
+
+
+__all__ = ['Set', 'Map', 'Printer', 'Context']
diff --git a/final/utils/pyscop/jscop2iscc.py b/final/utils/pyscop/jscop2iscc.py
new file mode 100755
index 0000000..3267e8e
--- /dev/null
+++ b/final/utils/pyscop/jscop2iscc.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+import argparse, isl, os
+import json
+
+def printDomain(scop):
+
+  domain = isl.USet('{}')
+
+  for statement in scop['statements']:
+    domain = domain.union(isl.USet(statement['domain']))
+
+  print "D :=",
+  print str(domain) + ";"
+
+def printAccesses(scop):
+
+  read = isl.UMap('{}')
+
+  for statement in scop['statements']:
+    for access in statement['accesses']:
+      if access['kind'] == 'read':
+        read = read.union(isl.UMap(access['relation']))
+
+  print "R :=",
+  print str(read) + ";"
+
+  write = isl.UMap('{}')
+
+  for statement in scop['statements']:
+    for access in statement['accesses']:
+      if access['kind'] == 'write':
+        write = write.union(isl.UMap(access['relation']))
+
+  print "W :=",
+  print str(write) + ";"
+
+def printSchedule(scop):
+
+  schedule = isl.UMap('{}')
+
+  for statement in scop['statements']:
+    schedule = schedule.union(isl.UMap(statement['schedule']))
+
+  print "S :=",
+  print str(schedule) + ";"
+
+def __main__():
+  description = 'Translate JSCoP into iscc input'
+  parser = argparse.ArgumentParser(description)
+  parser.add_argument('inputFile', metavar='N', type=file,
+                      help='The JSCoP file')
+
+  args = parser.parse_args()
+  inputFile = args.inputFile
+  scop = json.load(inputFile)
+
+  printDomain(scop)
+  printAccesses(scop)
+  printSchedule(scop)
+
+  print 'R := R * D;'
+  print 'W := W * D;'
+  print 'Dep := (last W before R under S)[0];'
+  print 'schedule D respecting Dep minimizing Dep;'
+
+
+__main__()
+
diff --git a/final/utils/pyscop/pyscop.py b/final/utils/pyscop/pyscop.py
new file mode 100644
index 0000000..a7c3481
--- /dev/null
+++ b/final/utils/pyscop/pyscop.py
@@ -0,0 +1,68 @@
+import json
+from isl import *
+
+class Scop:
+  def __init__(self, filename):
+    f = open(filename, 'r')
+    self.json = json.load(f)
+    return
+
+  def __str__(self):
+    return json.dumps(self.json, indent=2)
+
+  def __repr__(self):
+    return str(self)
+
+  @property
+  def statements(self):
+    return self.json['statements']
+
+class Transforms:
+  """
+  Create a map that interchanges two dimensions 'A' and 'B'
+
+  numberDimensions: The overall number of dimensions
+  dimensionA: The dimension of dimension 'A'
+  dimensionB: The dimension of dimension 'B'
+
+  getInterchange(2, 0, 1):
+  {[d0, d1] -> [d1, d0]}
+  """
+  @staticmethod
+  def getInterchange(numberDimensions, dimensionA, dimensionB):
+
+    dims = ['d' + str(i) for i in range(numberDimensions)]
+    dimString = ",".join(dims)
+
+    changedDims = dims
+    first = dims[dimensionA]
+    second = dims[dimensionB]
+    changedDims[dimensionA] = second
+    changedDims[dimensionB] = first
+    changedDimString = ",".join(changedDims)
+
+    return Map("{[%s] -> [%s]}" % (dimString, changedDimString))
+
+  """
+  Create a map that strip mines one dimension
+
+  numberDimensions: The overall number of dimensions
+  stripMineDim: The dimension to strip mine
+  factor: The strip mining factor
+
+  getStripMine(2, 1, 64):
+  {[d0, d1] -> [d0, o, d1] : o % 64 = 0 and o <= d1 <= d1 + 63}
+  """
+  @staticmethod
+  def getStripMine(numberDimensions, stripMineDim, factor):
+
+    dims = ['d' + str(i) for i in range(numberDimensions)]
+    dimString = ",".join(dims)
+
+    changedDims = dims
+    smd = dims[stripMineDim]
+    changedDims[stripMineDim] = "o,%s" % smd
+    changedDimString = ",".join(changedDims)
+    string = "{[%s] -> [%s]: o %% %i = 0 and o <= %s <= o + %i}" % \
+          (dimString, changedDimString, factor, smd, factor - 1)
+    return Map(string)
diff --git a/final/utils/update_format.sh b/final/utils/update_format.sh
new file mode 100755
index 0000000..9226fc6
--- /dev/null
+++ b/final/utils/update_format.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+CLANG_FORMAT=${CLANG_FORMAT}
+
+if [ "${CLANG_FORMAT}x" = "x" ]; then
+  CLANG_FORMAT=`which clang-format`
+  if [ "${CLANG_FORMAT}x" = "x" ]; then
+     echo "Error: cannot find clang-format in your path"
+     exit 1
+  fi
+fi
+
+for ARG in "$@"
+  do
+    ${CLANG_FORMAT} -i $ARG
+  done
diff --git a/final/www/.htaccess b/final/www/.htaccess
new file mode 100644
index 0000000..bfd0afc
--- /dev/null
+++ b/final/www/.htaccess
@@ -0,0 +1 @@
+AddHandler server-parsed .html 
diff --git a/final/www/bugs.html b/final/www/bugs.html
new file mode 100644
index 0000000..87254a8
--- /dev/null
+++ b/final/www/bugs.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+  "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+  <title>Polly - Bugs</title>
+  <link type="text/css" rel="stylesheet" href="menu.css" />
+  <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Bug Reports</h1>
+
+Polly uses the LLVM bug tracking system.
+
+<h3>File a  Bug</h3>
+
+If a problem appears, please <a
+href="http://llvm.org/bugs/enter_bug.cgi?product=Projects&component=Polly">
+report a bug</a> to the LLVM bugzilla. Polly bugs are tracked under product
+'Projects' and component 'Polly'.
+
+
+<h3>Open Bugs</h3>
+A list of the <a
+href="http://llvm.org/bugs/buglist.cgi?query_format=advanced&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&component=Polly&product=Projects">open
+bugs</a> in Polly is also available.
+
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/changelog.html b/final/www/changelog.html
new file mode 100644
index 0000000..f9d1530
--- /dev/null
+++ b/final/www/changelog.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head> <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - ChangeLog</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<h1> ChangeLog </h1>
+
+<h2> 3.6 - Upcoming release</h2>
+
+<ul>
+<li>Switch to the new isl AST generator (replacing CLooG)</li>
+<li>Run-time alias checks</li>
+<li>Computation of no-alias information for later LLVM optimizations
+(vectorizer, LICM, ...)</li>
+<li>Support for multi-dimensional arrays of parameteric size (still tested)</li>
+<li>New assumption tracking framework</li>
+<ul>
+<li>Accesses to multi-dimensional arrays of fixed size are within bounds</li>
+</ul>
+<li>Compile-time reduction</li>
+</ul>
+
+<h2> Older releases</h2>
+
+No changelog available. Please look at the <a
+href="http://repo.or.cz/w/polly-mirror.git">commit history</a>.
+
+</html>
+</div>
+</body>
+</html>
diff --git a/final/www/content.css b/final/www/content.css
new file mode 100644
index 0000000..549b2a9
--- /dev/null
+++ b/final/www/content.css
@@ -0,0 +1,139 @@
+html { margin: 0px; } body { margin: 8px; }
+
+html, body {
+  padding:0px;
+  font-family:"Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, Helvetica, sans-serif; background-color: #fff; color: #222;
+}
+
+#box {
+  margin-left: auto;
+  margin-right: auto;
+  max-width: 67em;
+}
+[id=content] {
+	/* *****  EDIT THIS VALUE IF CONTENT OVERLAPS MENU ***** */
+        margin-left: 21em;
+	padding-left: 3em;
+}
+
+a:visited {
+  color: #931e24;
+}
+
+h1, h2, h3, tt { color: #000 }
+
+h1 { padding-top:0px; margin-top:0px;}
+h2 { color:#333333; padding-top:0.5em; }
+h3 { padding-top: 0.5em; margin-bottom: -0.25em; color:#2d58b7}
+li { padding-bottom: 0.5em; }
+ul { padding-left:1.5em; }
+
+TD.done {background-color: #88ff99; text-align: center}
+TD.inprogress{background-color: #ffce00; text-align: center}
+TD.open{background-color: #e6705f; text-align: center}
+TD.nice{background-color: #5555df; text-align: center}
+TD.niceinprogress{background-color: #8888ff; text-align: center}
+
+PRE.code {padding-left: 0.5em; background-color: #eeeeee}
+PRE {padding-left: 0.5em}
+
+/* Slides */
+IMG.img_slide {
+    display: block;
+    margin-left: auto;
+    margin-right: auto
+}
+
+.itemTitle { color:#2d58b7 }
+
+span.error { color:red }
+span.caret { color:green; font-weight:bold }
+
+/* Tables */
+tr { vertical-align:top }
+#news P {padding: 0px; margin: 0px; border: 0px}
+
+#head {
+    min-height: 15em;
+    background-image:url(images/header-background.png);
+    background-repeat:no-repeat;
+    background-position: right;
+    max-width: 70em;
+    margin-bottom: 1em
+
+
+}
+
+#head h1 {
+  padding-bottom: 0em;
+  margin-bottom: 0em;
+  padding-top: 1em;
+  padding-left: 2em;
+  font-size: 3em;
+}
+
+#head h1 span {
+  background: white;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  background: white;
+  box-shadow: 1px 2px 5px 1px rgba(0, 0, 0, 0.7),
+              -1px 2px 20px rgba(255, 255, 255, 0.6) inset; 
+}
+
+#head h1 span a {
+  text-decoration: none;
+  color: #3b4567;
+}
+#head h1 span:before {
+  content: "\00a0 ";
+}
+#head h1 span:after {
+  content: "\00a0 ";
+}
+
+#head h2 {
+  color: #3b4567;
+  text-align: center;
+  padding-top: 0em;
+  margin-top: 0em;
+  padding-left: .5em;
+  padding-bottom: .5em;
+}
+
+#head h2 span {
+  background: white;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  background: white;
+  box-shadow: 1px 2px 5px 1px rgba(0, 0, 0, 0.7),
+              -1px 2px 20px rgba(255, 255, 255, 0.6) inset; 
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
+}
+
+#head h2 span:before {
+  content: "\00a0\00a0\00a0";
+}
+#head h2 span:after {
+  content: "\00a0\00a0\00a0";
+}
+
+#head p:before {
+  content: "\00a0\00a0\00a0";
+}
+#head p:after {
+  content: "\00a0\00a0\00a0";
+}
+
+#head p {
+  padding:0.1em;
+  background: rgba(0,0,0,0.3);
+  color: white;
+  position: absolute;
+  top: -1em; right: 0.5em;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+}
diff --git a/final/www/contributors.html b/final/www/contributors.html
new file mode 100644
index 0000000..83c64f5
--- /dev/null
+++ b/final/www/contributors.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+  <title>Polly - Contributors</title>
+  <link type="text/css" rel="stylesheet" href="menu.css" />
+  <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Contributors</h1>
+
+Polly is developed by a team of students supported by different universities.
+
+<h2>People</h2>
+<h3>Raghesh Aloor</h3>
+<p>Raghesh works on OpenMP code generation. He is funded as Google Summer of Code
+Student 2011.</p>
+
+<h3>Tobias Grosser</h3>
+<p>Tobias is one of the two Co-founders of Polly. He designed the overall
+architecture and contributed to almost every part of Polly. Polly was started
+during his diploma studies at University of Passau. Furthermore, he spent 6
+months at Ohio State University (funded by the U.S. National Science Foundation
+through awards 0811781 and 0926688). From August 2011 he works on Polly,
+during his PhD with INRIA/UMPC/ENS (funded through a
+<a href="http://research.google.com/university/relations/fellowship_recipients.html">
+Google Europe Fellowship in Efficient Computing</a>).</p>
+
+<p>Website: <a href="http://www.grosser.es">www.grosser.es</a></p>
+
+
+<h3>Andreas Simb&uuml;rger</h3>
+<p>
+Andreas works on the profiling infrastructure during his PhD at University of
+Passau.
+</p>
+<p>Website: <a href="http://www.infosun.fim.uni-passau.de/cl/staff/simbuerger/">
+http://www.infosun.fim.uni-passau.de/cl/staff/simbuerger/</a></p>
+<h3>Hongbin Zheng</h3>
+<p>Hongbin Zheng is one of the two Co-founders of Polly. He was funded as a
+Google Summer of Code Student 2010 and implemented parts of the Polly frontends
+as well as the automake/cmake infrastructure.</p>
+
+<h2> Universities</h2>
+
+<p>Polly is supported by the following Universities.</p>
+<img src="images/iit-madras.png" style="padding:1em" />
+<img src="images/uni-passau.png" style="padding: 1em; padding-bottom:2em;"/>
+<img src="images/osu.png" style="padding:1em"/>
+<img src="images/sys-uni.png" style="padding:1em"/>
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/documentation.html b/final/www/documentation.html
new file mode 100644
index 0000000..eddf1cf
--- /dev/null
+++ b/final/www/documentation.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Documentation</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>Documentation</h1>
+  <!--*********************************************************************-->
+
+<ul>
+<li><a href="documentation/architecture.html">The Architecture of Polly</a></li>
+<li><a href="example_load_Polly_into_clang.html">Use Polly in clang/clang++</a>
+
+</li>
+<li><a href="example_load_Polly_into_dragonegg.html">Use Polly in dragonegg</a>
+</li>
+
+<li>
+<a href="example_manual_matmul.html">Inside Polly - How to manually use the
+individual pieces of Polly</a>
+
+</li>
+<li><a href="documentation/passes.html">A list of the LLVM passes available
+in Polly</a></li>
+<li><a href="documentation/memaccess.html">Polly - Memory access optimizations
+</a></li>
+</ul>
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/documentation/architecture.html b/final/www/documentation/architecture.html
new file mode 100644
index 0000000..aa1c80f
--- /dev/null
+++ b/final/www/documentation/architecture.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - The architecture</title>
+  <link type="text/css" rel="stylesheet" href="../menu.css">
+  <link type="text/css" rel="stylesheet" href="../content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="../menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>The Architecture Diagram of Polly</h1>
+  <!--*********************************************************************-->
+  <img src='../images/architecture.png' />
+</div>
+</div>
+</body>
+</html>
+
diff --git a/final/www/documentation/gpgpucodegen.html b/final/www/documentation/gpgpucodegen.html
new file mode 100644
index 0000000..7118171
--- /dev/null
+++ b/final/www/documentation/gpgpucodegen.html
@@ -0,0 +1,229 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - GPGPU Code Generation</title>
+  <link type="text/css" rel="stylesheet" href="../menu.css">
+  <link type="text/css" rel="stylesheet" href="../content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="../menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>Polly - GPGPU Code Generation</h1>
+  <!--*********************************************************************-->
+<p><em>WARNING: This project was part of the Google Summer of Code 2012.
+It is currently not finished, but it is in the design and implementation stage.
+The ideas/plans described here may not yet be implemented in Polly and may
+change later on.</em></p>
+
+This project adds GPGPU code generation feature to Polly.
+
+<h2>Objective</h2>
+<p>The overall objective of this GSoC project is to create a preliminary
+   implementation of GPGPU code generation for Polly. With this addition, users
+   can parallelize some perfectly nested loops with Polly to execute on a
+   heterogeneous platform, composed of CPU and GPU.</p>
+<p>There are several successful projects about automatic source-to-source gpu
+   code transformation. C-to-CUDA[1] uses the standard Pluto algorithms for
+   computing an affine schedule and then applies a wavefront transformation to
+   obtain one sequential and n-1 parallel loops. The parallel loops are then
+   mapped onto the blocks and threads of GPU. PPCG[2] introduces some advanced
+   algorithms which can expose much more parallelism than other methods . And It
+   also introduces affine partition heuristics and code generation algorithms
+   for locality enhancement in the registers and shared memory.</p>
+<p>Since automatic GPGPU code generation is quite a complex problem and what we
+   target is a low-level intermediate representation, LLVM IR, rather than a
+   high-level language source, it is important for us to set a proper objective
+   as a start step to give a complete solution to GPGPU code generation for LLVM
+   IR.</p>
+<p>Firstly, we plan to target two kinds of relatively simple test cases. One is
+   comprised of pure parallel and perfectly nested loops, like the following
+   code.</p>
+<pre>
+parfor(int i=0 to M)
+  parfor(int j=0 to N)
+    LoopBody(i, j);
+</pre>
+<p>Another one is that all the loops in it are parallel except the inner-most
+   one, just like this:</p>
+<pre>
+parfor(int i=0 to M)
+  parfor(int j=0 to N)
+    non-parfor(int k=0 to K)
+      LoopBody(i, j, k);
+</pre>
+<p>The LoopBody part should be limited to instructions or functions calls
+   (intrinsics) which can be handled by LLVM's NVPTX backend.</p>
+<p>On the other hand, we focus on building a preliminary and scalable framework
+   of GPGPU code generation for polly. Thus we plan to employ relatively simple
+   tiling and mapping algorithms and optimize them later.</p>
+<h2>Work Flow</h2>
+<h3>GPGPU Code Generation In General</h3>
+<p>C-to-CUDA[1] and PPCG[2] propose similar steps to solve the automatic GPGPU
+   code generation problem.</p>
+<li>Look for parallel loops.</li>
+<li>Create a polyhedral model from the loops.</li>
+<li>Tile and map the loops to GPU blocks and threads.</li>
+<li>Determine where to place the data.</li>
+<h3>What has been done in Polly</h3>
+<p>Polly has implemented the 1st, 2nd and part of the 3rd of the above steps and
+   many other analysis and transformation passes.</p>
+<h3>What to do in Polly</h3>
+<p>Unlike many source-to-source optimizers such as C-to-CUDA and PPCG, Polly is
+   a low-level optimizer, which means we can't use a source-level compiler
+   (e.g. NVCC) to generate the final assembly for the device. We need manually
+   insert device driver API calls to execute the generated kernel assembly
+   text.</p>
+<p>In this project, we assume that the device driver library has provided an
+   interface to launch kernels in the form of assembly text. Fortunately, most
+   of the mainstream GPU vendors provide such a feature in thier products (see
+   ptxjit of NVIDIA GPUs and CAL of AMD GPUs). Generally speaking, what we
+   are going to do in Polly is:</p>
+<li>Find a way to tile the parallel loops.</li>
+<li>Find a way to extract the loop body and transform it into thread-centric
+    parallel code.</li>
+<li>Find a way to store/load the thread-centric code into/from a device module.
+<li>Find a way to pass the target machine information and generate code of the
+    device module for the target.
+<li>Find a way to map the tiled loop to GPU blocks and threads.</li>
+<li>Find a way to insert CUDA synchronization operations on-demand.
+<li>Find a way to generate the memory copy operations between a host and a
+    device.</li>
+<li>Implement/Wrap a runtime library to serve as the execution engine for the
+    generated device code.</li>
+
+<h3>The Work Flow</h3>
+<p>In this section, we assume that the host cpu is X86 and the device is NVIDIA
+   CUDA-compatible. we will use the following test case to describe our work
+   flow.</p>
+<pre>
+for(i = 0; i &lt; 128; i++)
+      for(j = 0; j &lt; 128; j++)
+              A[i][j] = i*128 + j;
+</pre>
+<p>The work flow of our code generator is as follows.</p>
+<p>1.We first use Polly's jscop file importer to get a wanted 4-level parallel
+   tiled code.</p>
+The "schedule" part of the pre-optimization jscop file is as the following:
+<pre>
+"schedule" : "{ Stmt_for_body3[i0, i1] -&gt; scattering[0, i0, 0, i1, 0] }"
+</pre>
+The jscop file describing the tiling transformation is:
+<pre>
+"schedule" : "{ Stmt_for_body3[i0, i1] -&gt; scattering[0, o0, o1, o2, o3]:
+              o0 &gt;= 0 and o0 &lt;= 7 and o1 &gt;= 0 and o1 &lt;= 15 and
+              o2 &gt;= 0 and o2 &lt;= 7 and o3 &gt;= 0 and o3 &lt;= 15 and
+              i0 = 16o0 + o1 and i1 = 16o2 + o3 }"
+</pre>
+We can test the schedule with the following command line.
+<pre>
+opt -load /path/to/polly/build/LLVMPolly.so -basicaa -polly-import-jscop
+    -polly-ast -analyze -q ./test.ll
+    -polly-import-jscop-postfix=transformed+gpu
+</pre>
+The output of this schedule is:
+<pre>
+for (c2=0;c2&lt;=7;c2++) {
+  for (c3=0;c3&lt;=15;c3++) {
+    for (c4=0;c4&lt;=7;c4++) {
+      for (c5=0;c5&lt;=15;c5++) {
+        Stmt_for_body3(16*c2+c3,16*c4+c5);
+      }
+    }
+  }
+}
+</pre>
+Now we get a 4-dimensional parallel loops with a single SCoP statement in it.
+<p>2.We then extract the loop body (or the inner-most non-parallel loop) into a
+   LLVM function, tagging it with PTX_Kernel call convention.</p>
+<p>3.We extract the PTX_kernel function into a temporary module, set the target
+   triple (e.g. nvptx64-unknown-linux) for the module, transform the temporary
+   module into a string, store it in the original module and erase the
+   PTX_kernel function.</p>
+<p>4.We replace the loops with their GPGPU counterpart. The GPGPU part of code
+   is composed of a call to the llvm.codegen intrinsic and function calls to our
+   GPU runtime library.</p>
+<p>5.Finally, we generate the executable program with <em>llc</em> or run the
+   optimized LLVM IRs with a JIT compiler like  <em>lli</em>.</p>
+<h2>Usage</h2>
+<p>1. Apply the llvm.codegen intrinsic patch to LLVM code base.</p>
+<pre>cd /path/to/llvm/source
+git am /path/to/polly/source/utils/0001-Add-llvm.codegen-intrinsic.patch</pre>
+<p>2. Build the test case.</p>
+<pre>/path/to/polly/source/test/create_ll.sh test.c</pre>
+<p>3. Get and edit the jscop file (take function "gpu_codegen" as an example).
+</p>
+<pre>opt -load /path/to/polly/build/lib/LLVMPolly.so -basicaa
+    -polly-export-jscop ./test.ll
+cp gpu_codegen___%for.cond---%for.end8.jscop
+   gpu_codegen___%for.cond---%for.end8.jscop.transformed+gpu
+vi gpu_codegen___%for.cond---%for.end8.jscop.transformed+gpu</pre>
+<p><em>(Please refer to section "The Work Flow" on how to edit the "schedule"
+       part of a statement)</em></p>
+<p>4. Optimize the code with GPGPU code generation.</p>
+<pre>opt -load /path/to/polly/build/lib/LLVMPolly.so -basicaa
+    -polly-import-jscop-postfix=transformed+gpu -enable-polly-gpgpu
+    -polly-gpgpu-triple=nvptx64-unknown-unknown -polly-codegen ./test.ll -S
+    -o test.gpued.ll</pre>
+<p>5. Build the final assembly and executable.</p>
+<pre>llc test.gpued.ll -o test.s
+gcc test.s -lGPURuntime -o test</pre>
+<p><em>(Please make sure that LD_LIBRARY_PATH is set properly so that
+        /path/to/polly/build/lib/libGPURuntime.so is visible to gcc.)</em></p>
+<h2>TODO List</h2>
+
+<table class="wikitable" cellpadding="2">
+<tbody>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Tasks</th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left">Tiling the Parallel Loops with An External Jscop File</th>
+<td align="center" class='open'>Open, In Design</td>
+<td>Yabin Hu</td>
+</tr>
+<tr>
+<th align="left">GPU Runtime Library Implementation</th>
+<td align="center" class='inprogress'>Coding Finished, In Reviewing</td>
+<td></td>
+</tr>
+<tr>
+<th align="left">llvm.codegen Intrinsic Implementation</th>
+<td align="center" class='inprogress'>Codeing Finished, To Be Reviewed</td>
+<td></td>
+</tr>
+<tr>
+<th align="left">Code Generation For Host</th>
+<td align="center" class='inprogress'>50% Done</td>
+<td></td>
+</tr>
+
+</tbody></table>
+
+<h2>References</h2>
+<li type="1" value="1">
+<em>Automatic C-to-CUDA Code Generation for Affine Programs. </em><br />
+    Muthu Manikandan Baskaran, J. Ramanujam and P. Sadayappan.<br />
+    International Conference on Compiler Construction (CC) 2010.<br />
+</li>
+<li type="1"><em>PPCG Project</em><br />
+<a href="http://freecode.com/projects/ppcg">http://freecode.com/projects/ppcg
+</a></li>
+<li type="1">
+<em>Where is the Data? Why You Cannot Debate GPU vs. CPU Performance Without the
+    Answer. </em><br />
+  Chris Gregg and Kim Hazelwood<br />
+  International Symposium on Performance Analysis of Systems and Software
+  (ISPASS) 2011.
+</li>
+<p></p>
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/documentation/memaccess.html b/final/www/documentation/memaccess.html
new file mode 100644
index 0000000..fa48771
--- /dev/null
+++ b/final/www/documentation/memaccess.html
@@ -0,0 +1,128 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Memory access optimizations</title>
+  <link type="text/css" rel="stylesheet" href="../menu.css">
+  <link type="text/css" rel="stylesheet" href="../content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="../menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>Memory access optimizations</h1>
+  <!--*********************************************************************-->
+<p><em>WARNING: This project was part of the Google Summer of Code 2011.
+Tt is currently not finished, but it is in the design and implementation stage.
+The Ideas/Plans described here may not yet be implemented in Polly and may be
+changed during the actual implementation.</em></p>
+
+This project adds memory access transformations to Polly. In many cases
+changing the memory access pattern yields to better data locality or removes
+dependences that would otherwise block transformations.
+
+<p>An examples which uses this feature is given below.</p>
+
+Consider the following loop
+<pre>
+for (i = 0; i < 8; i++)
+  sum += A[i];
+</pre>
+Through memory access transformations this loop can be executed in parallel.
+It can be transformed to
+<pre>
+<em>// Create and initialize an array 'tmp' with size 4</em>
+for (i = 0; i < 8; i++)
+  tmp[i % 4] += A[i];
+sum = tmp[0] + tmp[1] + tmp[2] + tmp[3];
+</pre>
+
+Optimizers like PluTo can schedule the code such that an outer, parallel
+loop is created:
+<pre>
+parfor (ii = 0; ii < 4; ii++) {
+  tmp[ii] = 0;
+  for (i = ii * 2; i < (ii+1) * 2; i++)
+    tmp[ii] += A[i];
+  }
+sum = tmp[0] + tmp[1] + tmp[2] + tmp[3];
+</pre>
+
+<h2>TODO</h2>
+<h3>Step 1</h3>
+Polly exports its polyhedral description in a JSCoP file. Define how memory
+layout transformations are expressed in Polly and in the JSCOP file. 
+Example:
+
+<p>Consider the following loop.</p>
+<pre>
+for (i = 0; i < 12; i++)
+  A[i] = 0;
+</pre>
+In the JSCOP file the memory accesses are represented as follows.
+<pre>
+"accesses": [{
+        "kind": "write",
+                "relation": "{ Stmt[i] -> A[i] }"
+}]
+</pre>
+To perform a transformation we generate the following code:
+<pre>
+for (i = 0; i < 12; i++)
+  A[0] = i;
+</pre>
+The representation in the JSCoP file is:
+<pre>
+"accesses": [{
+        "kind": "read",
+                "relation": "{ Stmt[i] -> A[0] }"
+}]
+</pre>
+We need to detect this access function change.
+
+<h3>Step 2</h3>
+Update the code generation module to reflect the access function change made
+in Step 1.
+<h3>Step 2.1 Code generation for a constant</h3>
+In the JSCOP file an access function which has variables is changed to a
+constant. Code is generated to reflect this change. Let the content of original
+JSCOP file be:
+<pre>
+"accesses" : [{
+        "kind" : "read",
+                 "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+}]
+</pre>
+The transformed JSCOP file is:
+<pre>
+"accesses" : [{
+        "kind" : "read",
+                 "relation" : "{ Stmt_for_body[i0] -> MemRef_A[10] }"
+}]
+</pre>
+Code is generated for this change.
+<h3>Step 2.2 Code generation for coefficients</h3>
+The coefficients of induction variables are changed here. Let the original
+JSCOP file be:
+<pre>
+"accesses" : [{
+      "kind" : "read",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_A[32i0+i1] }"
+}]
+</pre>
+The transformed JSCOP file is:
+<pre>
+"accesses" : [{
+      "kind" : "read",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_A[16i0+2i1+5] }"
+}]
+</pre>
+Code is generated for this change.
+</div>
+</div>
+</body>
+</html>
+
diff --git a/final/www/documentation/passes.html b/final/www/documentation/passes.html
new file mode 100644
index 0000000..c0c727d
--- /dev/null
+++ b/final/www/documentation/passes.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - The available LLVM passes</title>
+  <link type="text/css" rel="stylesheet" href="../menu.css">
+  <link type="text/css" rel="stylesheet" href="../content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="../menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>The available LLVM passes</h1>
+  <!--*********************************************************************-->
+
+  <p>Polly consists of a set of LLVM passes.  </p>
+
+<h2>Front End</h2>
+<ul>
+<li><em>polly-prepare</em> Prepare code for Polly</li>
+<li><em>polly-detect</em> Detect SCoPs in functions</li>
+<li><em>polly-analyze-ir</em> Analyse the LLVM-IR in the detected SCoPs</li>
+<li><em>polly-independent</em> Create independent blocks</li>
+<li><em>polly-scops</em> Create polyhedral description of SCoPs</li>
+</ul>
+<h2>Middle End</h2>
+<ul>
+<li><em>polly-dependences</em> Calculate the dependences in a SCoPs</li>
+<li><em>polly-opt-pocc</em> Optimize the SCoP using PoCC [removed after <a href="http://llvm.org/releases/download.html#3.4.2">LLVM 3.4.2</a>]</li>
+<li><em>polly-opt-isl</em> Optimize the SCoP using isl</li>
+<li>Import/Export
+<ul>
+<li><em>polly-export-scoplib</em> Export SCoPs with ScopLib library
+(Writes a .scoplib file for each SCoP) [removed after <a href="http://llvm.org/releases/download.html#3.4.2">LLVM 3.4.2</a>]</li>
+<li><em>polly-import-scoplib</em> Import SCoPs with ScopLib library
+(Reads a .scoplib file for each SCoP) [removed after <a href="http://llvm.org/releases/download.html#3.4.2">LLVM 3.4.2</a>]</li>
+<li><em>polly-export-jscop</em> Export SCoPs as JSON
+(Writes a .jscop file for each SCoP)</li>
+<li><em>polly-import-jscop</em> Import SCoPs from JSON
+(Reads a .jscop file for each SCoP)</li>
+</ul>
+</li>
+<li>Graphviz
+<ul>
+<li><em>dot-scops</em> Print SCoPs of function</li>
+<li><em>dot-scops-only</em> Print SCoPs of function (without function bodies)</li>
+<li><em>view-scops</em> View SCoPs of function</li>
+<li><em>view-scops-only</em> View SCoPs of function (without function bodies)</li>
+</ul></li>
+</ul>
+<h2>Back End</h2>
+<ul>
+<li><em>polly-ast</em> Execute isl code generation</li>
+<li><em>polly-codegen</em> Create LLVM-IR from the polyhedral information</li>
+</ul>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/example_load_Polly_into_clang.html b/final/www/example_load_Polly_into_clang.html
new file mode 100644
index 0000000..a43e5bf
--- /dev/null
+++ b/final/www/example_load_Polly_into_clang.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Load Polly into clang</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<!--=====================================================================-->
+<h1>Load Polly into clang and automatically run it at -O3</h1>
+<!--=====================================================================-->
+
+<p><b>Warning:</b> Even though this example makes it very easy to use Polly,
+you should be aware that Polly is a young research project. It is expected
+to crash, produce invalid code or to hang in complex calculations even for
+simple examples. In case you see such a problem, please check the <a
+href="bugs.html">Bug database</a> and consider reporting a bug.
+<p>
+<b>Warning II:</b> clang/LLVM/Polly need to be in sync. This means
+            you need to compile them yourself from a recent svn/git checkout</b>
+<h2>Load Polly into clang</h2>
+
+By default Polly is configured as a shared library plugin that is loaded in
+tools like clang, opt, and bugpoint when they start their execution.
+
+By loading Polly into clang (or opt) the Polly options become automatically
+available. You can load Polly either by adding the relevant commands to
+the CPPFLAGS or by creating an alias.
+
+<pre class="code">
+$ export CPPFLAGS="-Xclang -load -Xclang ${POLLY_BUILD_DIR}/lib/LLVMPolly.so"
+</pre>
+
+or
+<pre class="code">
+$ alias pollycc clang -Xclang -load -Xclang ${POLLY_BUILD_DIR}/lib/LLVMPolly.so
+</pre>
+
+To avoid having to load Polly in the tools, Polly can optionally be configured
+with cmake to be statically linked in the tools:
+
+<pre class="code">
+$ cmake -D LINK_POLLY_INTO_TOOLS:Bool=ON
+</pre>
+
+<h2>Optimizing with Polly</h2>
+
+Optimizing with Polly is as easy as adding <b>-O3 -mllvm -polly</b> to your
+compiler flags (Polly is only available at -O3).
+
+<pre class="code">pollycc -O3 -mllvm -polly file.c</pre>
+
+<h2>Automatic OpenMP code generation</h2>
+
+To automatically detect parallel loops and generate OpenMP code for them you
+also need to add <b>-mllvm -enable-polly-openmp -lgomp</b> to your CFLAGS.
+
+<pre class="code">pollycc -O3 -mllvm -polly -mllvm -enable-polly-openmp -lgomp file.c</pre>
+
+<h2>Automatic Vector code generation</h2>
+
+Automatic vector code generation can be enabled by adding <b>-mllvm
+-polly-vectorizer=polly</b> to your CFLAGS.
+
+<pre class="code">pollycc -O3 -mllvm -polly -mllvm -polly-vectorizer=polly file.c</pre>
+
+<h2>Extract a preoptimized LLVM-IR file</h2>
+
+Often it is useful to derive from a C-file the LLVM-IR code that is actually
+optimized by Polly. Normally the LLVM-IR is automatically generated from
+the C code by first lowering C to LLVM-IR (clang) and by subsequently applying a
+set of preparing transformations on the LLVM-IR. To get the LLVM-IR after the
+preparing transformations have been applied run Polly with '-O0'.
+
+<pre class="code">pollycc -O0 -mllvm -polly -S -emit-llvm file.c</pre>
+
+<h2>Further options</h2>
+
+Polly supports further options that are mainly useful for the development or
+the
+analysis of Polly. The relevant options can be added to clang by appending
+<b>-mllvm -option-name</b> to the CFLAGS or the clang
+command line.
+
+<h3>Limit Polly to a single function</h3>
+To limit the execution of Polly to a single function, use the option
+<b>-polly-detect-only=functionname</b>.
+
+<h3>Disable LLVM-IR generation</h3>
+Polly normally regenerates LLVM-IR from the Polyhedral representation. To only
+see the effects of the preparing transformation, but to disable Polly code
+generation add the option <b>polly-no-codegen</b>.
+
+<h3>Graphical view of the SCoPs</h3>
+
+Polly can use graphviz to show the SCoPs it detects in a program. The relevant
+options are <b>-polly-show</b>, <b>-polly-show-only</b>, <b>-polly-dot</b> and
+<b>-polly-dot-only</b>. The 'show' options automatically run dotty or another
+graphviz viewer to show the scops graphically. The 'dot' options store for each
+function a dot file that highlights the detected SCoPs. If 'only' is appended at
+the end of the option, the basic blocks are shown without the statements the
+contain.
+
+<h3>Change/Disable the Optimizer</h3>
+Polly uses by default the isl scheduling optimizer. The isl optimizer optimizes
+for data-locality and parallelism using the <a
+href="http://pluto-compiler.sf.net">Pluto</a> algorithm. For research it is also
+possible to run <a
+href="http://www-rocq.inria.fr/~pouchet/software/pocc/">PoCC</a> as external
+optimizer. PoCC provides access to the original Pluto implementation. To use
+PoCC add <b>-polly-optimizer=pocc</b> to the command line (only available if
+Polly was compiled with scoplib support) [removed after <a href="http://llvm.org/releases/download.html#3.4.2">LLVM 3.4.2</a>].
+To disable the optimizer entirely use the option <b>-polly-optimizer=none</b>.
+
+<h3>Disable tiling in the optimizer</h3>
+By default both optimizers perform tiling, if possible. In case this is not
+wanted the option <b>-polly-no-tiling</b> can be used to disable it. (This
+option disables tiling for both optimizers).
+
+<h3>Ignore possible aliasing</h3>
+By default we only detect scops, if we can prove that the different array bases
+can not alias. This is correct do if we optimize automatically.  However,
+without special user annotations like 'restrict' we can often not prove that
+no aliasing is possible. In case the user knows no aliasing can happen in the
+code the <b>-polly-ignore-aliasing</b> can be used to disable the check for
+possible aliasing.
+
+<h3>Import / Export</h3>
+The flags <b>-polly-import</b> and <b>-polly-export</b> allow the export and
+reimport of the polyhedral representation. By exporting, modifying and
+reimporting the polyhedral representation externally calculated transformations
+can be applied. This enables external optimizers or the manual optimization of
+specific SCoPs.
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/example_load_Polly_into_dragonegg.html b/final/www/example_load_Polly_into_dragonegg.html
new file mode 100644
index 0000000..ef9f68b
--- /dev/null
+++ b/final/www/example_load_Polly_into_dragonegg.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Load Polly into dragonegg</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<!--=====================================================================-->
+<h1>Load Polly into dragonegg and automatically run it at -O3</h1>
+<!--=====================================================================-->
+
+<p><b>Note:</b>This is a quick note on how to load Polly into
+  dragonegg. The choice of front-end does not affect the passes
+  available with Polly, only the syntax is different.
+  The <a href="example_load_Polly_into_clang.html">examples for use
+  with clang</a> can also be performed with Polly, with suitable
+  corrections in the syntax.
+
+<h2>Compile dragonegg with support for LLVM plugins</h2>
+
+The support for LLVM plugins in dragonegg is still experimental, and
+hence protected by a build option. You must rebuild dragonegg with the
+following options:
+
+<pre class="code">
+$ GCC=${PATH_TO_GCC} LLVM_CONFIG=${PATH_TO_LLVM_CONFIG} ENABLE_LLVM_PLUGINS=1 make
+</pre>
+
+<h2>Load Polly into dragonegg</h2>
+
+By loading Polly into dragonegg, the Polly options become automatically
+available. You can load Polly either by adding the relevant commands to
+the CPPFLAGS or by creating an alias.
+
+<pre class="code">
+$ export CPPFLAGS="-fplugin=/path/to/dragonegg.so -fplugin-arg-dragonegg-llvm-option=-load:${POLLY_BUILD_DIR}/lib/LLVMPolly.so"
+</pre>
+
+or
+
+<pre class="code">
+$ alias pollycc gcc -fplugin=/path/to/dragonegg.so -fplugin-arg-dragonegg-llvm-option=-load:${POLLY_BUILD_DIR}/lib/LLVMPolly.so
+</pre>
+
+<h2>Optimizing with Polly</h2>
+
+Optimizing with Polly is as easy as adding <b>-O3 -fplugin-arg-dragonegg-llvm-option=-polly</b> to your
+compiler flags (Polly is only available at -O3).
+
+<pre class="code">pollycc -O3 -fplugin-arg-dragonegg-llvm-option=-polly file.c</pre>
+
+<h2>Passing various options to Polly</h2>
+
+As must be evident from the examples so far, options to LLVM and its
+plugins are passed via the <b>-fplugin-arg-dragonegg-llvm-option</b>
+commandline argment.
+The <a href="example_load_Polly_into_clang.html">examples for use with
+clang</a> can be executed with dragonegg by replacing
+the <b>-mllvm</b> syntax with the dragonegg syntax.
+
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/example_manual_matmul.html b/final/www/example_manual_matmul.html
new file mode 100644
index 0000000..5aa5934
--- /dev/null
+++ b/final/www/example_manual_matmul.html
@@ -0,0 +1,454 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Examples</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<!--=====================================================================-->
+<h1>Execute the individual Polly passes manually</h1>
+<!--=====================================================================-->
+
+<p>
+This example presents the individual passes that are involved when optimizing
+code with Polly. We show how to execute them individually and explain for each
+which analysis is performed or what transformation is applied. In this example
+the polyhedral transformation is user-provided to show how much performance
+improvement can be expected by an optimal automatic optimizer.</p>
+
+The files used and created in this example are available in the Polly checkout
+in the folder <em>www/experiments/matmul</em>. They can be created automatically
+by running the <em>www/experiments/matmul/runall.sh</em> script.
+
+<ol>
+<li><h4>Create LLVM-IR from the C code</h4>
+
+Polly works on LLVM-IR. Hence it is necessary to translate the source files into
+LLVM-IR. If more than on file should be optimized the files can be combined into
+a single file with llvm-link.
+
+<pre class="code">clang -S -emit-llvm matmul.c -o matmul.s</pre>
+</li>
+
+
+<li><h4>Load Polly automatically when calling the 'opt' tool</h4>
+
+Polly is not built into opt or bugpoint, but it is a shared library that needs
+to be loaded into these tools explicitally. The Polly library is called
+LVMPolly.so. For a cmake build it is available in the build/lib/ directory,
+autoconf creates the same file in
+build/tools/polly/{Release+Asserts|Asserts|Debug}/lib. For convenience we create
+an alias that automatically loads Polly if 'opt' is called.
+<pre class="code">
+export PATH_TO_POLLY_LIB="~/polly/build/lib/"
+alias opt="opt -load ${PATH_TO_POLLY_LIB}/LLVMPolly.so"</pre>
+</li>
+
+<li><h4>Prepare the LLVM-IR for Polly</h4>
+
+Polly is only able to work with code that matches a canonical form. To translate
+the LLVM-IR into this form we use a set of canonicalication passes. They are
+scheduled by using '-polly-canonicalize'.
+<pre class="code">opt -S -polly-canonicalize matmul.s &gt; matmul.preopt.ll</pre></li>
+
+<li><h4>Show the SCoPs detected by Polly (optional)</h4>
+
+To understand if Polly was able to detect SCoPs, we print the
+structure of the detected SCoPs. In our example two SCoPs were detected. One in
+'init_array' the other in 'main'.
+
+<pre class="code">opt -basicaa -polly-ast -analyze -q matmul.preopt.ll</pre>
+
+<pre>
+init_array():
+for (c2=0;c2&lt;=1023;c2++) {
+  for (c4=0;c4&lt;=1023;c4++) {
+    Stmt_5(c2,c4);
+  }
+}
+
+main():
+for (c2=0;c2&lt;=1023;c2++) {
+  for (c4=0;c4&lt;=1023;c4++) {
+    Stmt_4(c2,c4);
+    for (c6=0;c6&lt;=1023;c6++) {
+      Stmt_6(c2,c4,c6);
+    }
+  }
+}
+</pre>
+</li>
+<li><h4>Highlight the detected SCoPs in the CFGs of the program (requires graphviz/dotty)</h4>
+
+Polly can use graphviz to graphically show a CFG in which the detected SCoPs are
+highlighted. It can also create '.dot' files that can be translated by
+the 'dot' utility into various graphic formats.
+
+<pre class="code">opt -basicaa -view-scops -disable-output matmul.preopt.ll
+opt -basicaa -view-scops-only -disable-output matmul.preopt.ll</pre>
+The output for the different functions<br />
+view-scops:
+<a href="experiments/matmul/scops.main.dot.png">main</a>,
+<a href="experiments/matmul/scops.init_array.dot.png">init_array</a>,
+<a href="experiments/matmul/scops.print_array.dot.png">print_array</a><br />
+view-scops-only:
+<a href="experiments/matmul/scopsonly.main.dot.png">main</a>,
+<a href="experiments/matmul/scopsonly.init_array.dot.png">init_array</a>,
+<a href="experiments/matmul/scopsonly.print_array.dot.png">print_array</a>
+</li>
+
+<li><h4>View the polyhedral representation of the SCoPs</h4>
+<pre class="code">opt -basicaa -polly-scops -analyze matmul.preopt.ll</pre>
+<pre>
+[...]
+Printing analysis 'Polly - Create polyhedral description of Scops' for region:
+'for.cond =&gt; for.end19' in function 'init_array':
+   Context:
+   { [] }
+   Statements {
+   	Stmt_5
+           Domain&nbsp;:=
+               { Stmt_5[i0, i1]&nbsp;: i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023 };
+           Scattering&nbsp;:=
+               { Stmt_5[i0, i1] -&gt; scattering[0, i0, 0, i1, 0] };
+           WriteAccess&nbsp;:=
+               { Stmt_5[i0, i1] -&gt; MemRef_A[1037i0 + i1] };
+           WriteAccess&nbsp;:=
+               { Stmt_5[i0, i1] -&gt; MemRef_B[1047i0 + i1] };
+   	FinalRead
+           Domain&nbsp;:=
+               { FinalRead[0] };
+           Scattering&nbsp;:=
+               { FinalRead[i0] -&gt; scattering[200000000, o1, o2, o3, o4] };
+           ReadAccess&nbsp;:=
+               { FinalRead[i0] -&gt; MemRef_A[o0] };
+           ReadAccess&nbsp;:=
+               { FinalRead[i0] -&gt; MemRef_B[o0] };
+   }
+[...]
+Printing analysis 'Polly - Create polyhedral description of Scops' for region:
+'for.cond =&gt; for.end30' in function 'main':
+   Context:
+   { [] }
+   Statements {
+   	Stmt_4
+           Domain&nbsp;:=
+               { Stmt_4[i0, i1]&nbsp;: i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023 };
+           Scattering&nbsp;:=
+               { Stmt_4[i0, i1] -&gt; scattering[0, i0, 0, i1, 0, 0, 0] };
+           WriteAccess&nbsp;:=
+               { Stmt_4[i0, i1] -&gt; MemRef_C[1067i0 + i1] };
+   	Stmt_6
+           Domain&nbsp;:=
+               { Stmt_6[i0, i1, i2]&nbsp;: i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023 and i2 &gt;= 0 and i2 &lt;= 1023 };
+           Scattering&nbsp;:=
+               { Stmt_6[i0, i1, i2] -&gt; scattering[0, i0, 0, i1, 1, i2, 0] };
+           ReadAccess&nbsp;:=
+               { Stmt_6[i0, i1, i2] -&gt; MemRef_C[1067i0 + i1] };
+           ReadAccess&nbsp;:=
+               { Stmt_6[i0, i1, i2] -&gt; MemRef_A[1037i0 + i2] };
+           ReadAccess&nbsp;:=
+               { Stmt_6[i0, i1, i2] -&gt; MemRef_B[i1 + 1047i2] };
+           WriteAccess&nbsp;:=
+               { Stmt_6[i0, i1, i2] -&gt; MemRef_C[1067i0 + i1] };
+   	FinalRead
+           Domain&nbsp;:=
+               { FinalRead[0] };
+           Scattering&nbsp;:=
+               { FinalRead[i0] -&gt; scattering[200000000, o1, o2, o3, o4, o5, o6] };
+           ReadAccess&nbsp;:=
+               { FinalRead[i0] -&gt; MemRef_C[o0] };
+           ReadAccess&nbsp;:=
+               { FinalRead[i0] -&gt; MemRef_A[o0] };
+           ReadAccess&nbsp;:=
+               { FinalRead[i0] -&gt; MemRef_B[o0] };
+   }
+[...]
+</pre>
+</li>
+
+<li><h4>Show the dependences for the SCoPs</h4>
+<pre class="code">opt -basicaa -polly-dependences -analyze matmul.preopt.ll</pre>
+<pre>Printing analysis 'Polly - Calculate dependences for SCoP' for region:
+'for.cond =&gt; for.end19' in function 'init_array':
+   Must dependences:
+       {  }
+   May dependences:
+       {  }
+   Must no source:
+       {  }
+   May no source:
+       {  }
+Printing analysis 'Polly - Calculate dependences for SCoP' for region:
+'for.cond =&gt; for.end30' in function 'main':
+   Must dependences:
+       {  Stmt_4[i0, i1] -&gt; Stmt_6[i0, i1, 0]&nbsp;:
+              i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023;
+          Stmt_6[i0, i1, i2] -&gt; Stmt_6[i0, i1, 1 + i2]&nbsp;:
+              i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023 and i2 &gt;= 0 and i2 &lt;= 1022;
+          Stmt_6[i0, i1, 1023] -&gt; FinalRead[0]&nbsp;:
+              i1 &lt;= 1091540 - 1067i0 and i1 &gt;= -1067i0 and i1 &gt;= 0 and i1 &lt;= 1023;
+          Stmt_6[1023, i1, 1023] -&gt; FinalRead[0]&nbsp;:
+              i1 &gt;= 0 and i1 &lt;= 1023
+       }
+   May dependences:
+       {  }
+   Must no source:
+       {  Stmt_6[i0, i1, i2] -&gt; MemRef_A[1037i0 + i2]&nbsp;:
+              i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023 and i2 &gt;= 0 and i2 &lt;= 1023;
+          Stmt_6[i0, i1, i2] -&gt; MemRef_B[i1 + 1047i2]&nbsp;:
+              i0 &gt;= 0 and i0 &lt;= 1023 and i1 &gt;= 0 and i1 &lt;= 1023 and i2 &gt;= 0 and i2 &lt;= 1023;
+          FinalRead[0] -&gt; MemRef_A[o0];
+          FinalRead[0] -&gt; MemRef_B[o0]
+          FinalRead[0] -&gt; MemRef_C[o0]&nbsp;:
+              o0 &gt;= 1092565 or (exists (e0 = [(o0)/1067]: o0 &lt;= 1091540 and o0 &gt;= 0
+              and 1067e0 &lt;= -1024 + o0 and 1067e0 &gt;= -1066 + o0)) or o0 &lt;= -1;
+       }
+   May no source:
+       {  }
+</pre></li>
+
+<li><h4>Export jscop files</h4>
+
+Polly can export the polyhedral representation in so called jscop files. Jscop
+files contain the polyhedral representation stored in a JSON file.
+<pre class="code">opt -basicaa -polly-export-jscop matmul.preopt.ll</pre>
+<pre>Writing SCoP 'for.cond =&gt; for.end19' in function 'init_array' to './init_array___%for.cond---%for.end19.jscop'.
+Writing SCoP 'for.cond =&gt; for.end30' in function 'main' to './main___%for.cond---%for.end30.jscop'.
+</pre></li>
+
+<li><h4>Import the changed jscop files and print the updated SCoP structure
+(optional)</h4>
+<p>Polly can reimport jscop files, in which the schedules of the statements are
+changed. These changed schedules are used to descripe transformations.
+It is possible to import different jscop files by providing the postfix
+of the jscop file that is imported.</p>
+<p> We apply three different transformations on the SCoP in the main function.
+The jscop files describing these transformations are hand written (and available
+in <em>www/experiments/matmul</em>).
+
+<h5>No Polly</h5>
+
+<p>As a baseline we do not call any Polly code generation, but only apply the
+normal -O3 optimizations.</p>
+
+<pre class="code">
+opt matmul.preopt.ll -basicaa \
+    -polly-import-jscop \
+    -polly-ast -analyze
+</pre>
+<pre>
+[...]
+main():
+for (c2=0;c2&ltg;=1535;c2++) {
+  for (c4=0;c4&ltg;=1535;c4++) {
+    Stmt_4(c2,c4);
+    for (c6=0;c6&ltg;=1535;c6++) {
+      Stmt_6(c2,c4,c6);
+    }
+  }
+}
+[...]
+</pre>
+<h5>Interchange (and Fission to allow the interchange)</h5>
+<p>We split the loops and can now apply an interchange of the loop dimensions that
+enumerate Stmt_6.</p>
+<pre class="code">
+opt matmul.preopt.ll -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged \
+    -polly-ast -analyze
+</pre>
+<pre>
+[...]
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from './main___%for.cond---%for.end30.jscop.interchanged+tiled'.
+[...]
+main():
+for (c2=0;c2&lt;=1535;c2++) {
+  for (c4=0;c4&lt;=1535;c4++) {
+    Stmt_4(c2,c4);
+  }
+}
+for (c2=0;c2&lt;=1535;c2++) {
+  for (c4=0;c4&lt;=1535;c4++) {
+    for (c6=0;c6&lt;=1535;c6++) {
+      Stmt_6(c2,c6,c4);
+    }
+  }
+}
+[...]
+</pre>
+<h5>Interchange + Tiling</h5>
+<p>In addition to the interchange we tile now the second loop nest.</p>
+
+<pre class="code">
+opt matmul.preopt.ll -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged+tiled \
+    -polly-ast -analyze
+</pre>
+<pre>
+[...]
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from './main___%for.cond---%for.end30.jscop.interchanged+tiled'.
+[...]
+main():
+for (c2=0;c2&lt;=1535;c2++) {
+  for (c4=0;c4&lt;=1535;c4++) {
+    Stmt_4(c2,c4);
+  }
+}
+for (c2=0;c2&lt;=1535;c2+=64) {
+  for (c3=0;c3&lt;=1535;c3+=64) {
+    for (c4=0;c4&lt;=1535;c4+=64) {
+      for (c5=c2;c5&lt;=c2+63;c5++) {
+        for (c6=c4;c6&lt;=c4+63;c6++) {
+          for (c7=c3;c7&lt;=c3+63;c7++) {
+            Stmt_6(c5,c7,c6);
+          }
+        }
+      }
+    }
+  }
+}
+[...]
+</pre>
+<h5>Interchange + Tiling + Strip-mining to prepare vectorization</h5>
+To later allow vectorization we create a so called trivially parallelizable
+loop. It is innermost, parallel and has only four iterations. It can be
+replaced by 4-element SIMD instructions.
+<pre class="code">
+opt matmul.preopt.ll -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged+tiled+vector \
+    -polly-ast -analyze </pre>
+
+<pre>
+[...]
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from './main___%for.cond---%for.end30.jscop.interchanged+tiled+vector'.
+[...]
+main():
+for (c2=0;c2&lt;=1535;c2++) {
+  for (c4=0;c4&lt;=1535;c4++) {
+    Stmt_4(c2,c4);
+  }
+}
+for (c2=0;c2&lt;=1535;c2+=64) {
+  for (c3=0;c3&lt;=1535;c3+=64) {
+    for (c4=0;c4&lt;=1535;c4+=64) {
+      for (c5=c2;c5&lt;=c2+63;c5++) {
+        for (c6=c4;c6&lt;=c4+63;c6++) {
+          for (c7=c3;c7&lt;=c3+63;c7+=4) {
+            for (c8=c7;c8&lt;=c7+3;c8++) {
+              Stmt_6(c5,c8,c6);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+[...]
+</pre>
+
+</li>
+
+<li><h4>Codegenerate the SCoPs</h4>
+<p>
+This generates new code for the SCoPs detected by polly.
+If -polly-import-jscop is present, transformations specified in the imported
+jscop files will be applied.</p>
+<pre class="code">opt matmul.preopt.ll | opt -O3 &gt; matmul.normalopt.ll</pre>
+<pre class="code">
+opt -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged \
+    -polly-codegen matmul.preopt.ll \
+   | opt -O3 &gt; matmul.polly.interchanged.ll</pre>
+<pre>
+Reading JScop 'for.cond =&gt; for.end19' in function 'init_array' from
+    './init_array___%for.cond---%for.end19.jscop.interchanged'.
+File could not be read: No such file or directory
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from
+    './main___%for.cond---%for.end30.jscop.interchanged'.
+</pre>
+<pre class="code">
+opt -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged+tiled \
+    -polly-codegen matmul.preopt.ll \
+   | opt -O3 &gt; matmul.polly.interchanged+tiled.ll</pre>
+<pre>
+Reading JScop 'for.cond =&gt; for.end19' in function 'init_array' from
+    './init_array___%for.cond---%for.end19.jscop.interchanged+tiled'.
+File could not be read: No such file or directory
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from
+    './main___%for.cond---%for.end30.jscop.interchanged+tiled'.
+</pre>
+<pre class="code">
+opt -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged+tiled+vector \
+    -polly-codegen -polly-vectorizer=polly matmul.preopt.ll \
+   | opt -O3 &gt; matmul.polly.interchanged+tiled+vector.ll</pre>
+<pre>
+Reading JScop 'for.cond =&gt; for.end19' in function 'init_array' from
+    './init_array___%for.cond---%for.end19.jscop.interchanged+tiled+vector'.
+File could not be read: No such file or directory
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from
+    './main___%for.cond---%for.end30.jscop.interchanged+tiled+vector'.
+</pre>
+<pre class="code">
+opt -basicaa \
+    -polly-import-jscop -polly-import-jscop-postfix=interchanged+tiled+vector \
+    -polly-codegen -polly-vectorizer=polly -enable-polly-openmp matmul.preopt.ll \
+  | opt -O3 &gt; matmul.polly.interchanged+tiled+openmp.ll</pre>
+<pre>
+Reading JScop 'for.cond =&gt; for.end19' in function 'init_array' from
+    './init_array___%for.cond---%for.end19.jscop.interchanged+tiled+vector'.
+File could not be read: No such file or directory
+Reading JScop 'for.cond =&gt; for.end30' in function 'main' from
+    './main___%for.cond---%for.end30.jscop.interchanged+tiled+vector'.
+</pre>
+
+<li><h4>Create the executables</h4>
+
+Create one executable optimized with plain -O3 as well as a set of executables
+optimized in different ways with Polly. One changes only the loop structure, the
+other adds tiling, the next adds vectorization and finally we use OpenMP
+parallelism.
+<pre class="code">
+llc matmul.normalopt.ll -o matmul.normalopt.s &amp;&amp; \
+    gcc matmul.normalopt.s -o matmul.normalopt.exe
+llc matmul.polly.interchanged.ll -o matmul.polly.interchanged.s &amp;&amp; \
+    gcc matmul.polly.interchanged.s -o matmul.polly.interchanged.exe
+llc matmul.polly.interchanged+tiled.ll -o matmul.polly.interchanged+tiled.s &amp;&amp; \
+    gcc matmul.polly.interchanged+tiled.s -o matmul.polly.interchanged+tiled.exe
+llc matmul.polly.interchanged+tiled+vector.ll -o matmul.polly.interchanged+tiled+vector.s &amp;&amp; \
+    gcc matmul.polly.interchanged+tiled+vector.s -o matmul.polly.interchanged+tiled+vector.exe
+llc matmul.polly.interchanged+tiled+vector+openmp.ll -o matmul.polly.interchanged+tiled+vector+openmp.s &amp;&amp; \
+    gcc -lgomp matmul.polly.interchanged+tiled+vector+openmp.s -o matmul.polly.interchanged+tiled+vector+openmp.exe </pre>
+
+<li><h4>Compare the runtime of the executables</h4>
+
+By comparing the runtimes of the different code snippets we see that a simple
+loop interchange gives here the largest performance boost. However by adding
+vectorization and by using OpenMP we can further improve the performance
+significantly.
+<pre class="code">time ./matmul.normalopt.exe</pre>
+<pre>42.68 real, 42.55 user, 0.00 sys</pre>
+<pre class="code">time ./matmul.polly.interchanged.exe</pre>
+<pre>04.33 real, 4.30 user, 0.01 sys</pre>
+<pre class="code">time ./matmul.polly.interchanged+tiled.exe</pre>
+<pre>04.11 real, 4.10 user, 0.00 sys</pre>
+<pre class="code">time ./matmul.polly.interchanged+tiled+vector.exe</pre>
+<pre>01.39 real, 1.36 user, 0.01 sys</pre>
+<pre class="code">time ./matmul.polly.interchanged+tiled+vector+openmp.exe</pre>
+<pre>00.66 real, 2.58 user, 0.02 sys</pre>
+</li>
+</ol>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/examples.html b/final/www/examples.html
new file mode 100644
index 0000000..c8ceb65
--- /dev/null
+++ b/final/www/examples.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Examples</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+  <meta http-equiv="REFRESH"
+  content="0;url=documentation.html"></HEAD>
+</head>
+<body>
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<!--=====================================================================-->
+<h1>Polly: Examples</h1>
+<!--=====================================================================-->
+
+</div>
+</body>
+</html>
diff --git a/final/www/experiments/matmul/init_array___%for.cond---%for.end19.jscop b/final/www/experiments/matmul/init_array___%for.cond---%for.end19.jscop
new file mode 100644
index 0000000..dfd1093
--- /dev/null
+++ b/final/www/experiments/matmul/init_array___%for.cond---%for.end19.jscop
@@ -0,0 +1,21 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end19",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_A[1536i0 + i1] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_B[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= 1535 and i1 >= 0 and i1 <= 1535 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "{ Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0] }"
+      }
+   ]
+}
diff --git a/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop
new file mode 100644
index 0000000..4d6e463
--- /dev/null
+++ b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop
@@ -0,0 +1,40 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end30",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body3[i0, i1] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body3[i0, i1] : i0 >= 0 and i0 <= 1535 and i1 >= 0 and i1 <= 1535 }",
+         "name" : "Stmt_for_body3",
+         "schedule" : "{ Stmt_for_body3[i0, i1] -> scattering[0, i0, 0, i1, 0, 0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body8[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body8[i0, i1, i2] -> MemRef_A[1536i0 + i2] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_for_body8[i0, i1, i2] -> MemRef_B[i1 + 1536i2] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body8[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body8[i0, i1, i2] : i0 >= 0 and i0 <= 1535 and i1 >= 0 and i1 <= 1535 and i2 >= 0 and i2 <= 1535 }",
+         "name" : "Stmt_for_body8",
+         "schedule" : "{ Stmt_for_body8[i0, i1, i2] -> scattering[0, i0, 0, i1, 1, i2, 0] }"
+      }
+   ]
+}
diff --git a/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged
new file mode 100644
index 0000000..1d73c8a
--- /dev/null
+++ b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged
@@ -0,0 +1,40 @@
+{
+   "context" : "{ [] }",
+   "name" : "%1 => %17",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_4[i0, i1] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_4[i0, i1] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_4",
+         "schedule" : "{ Stmt_4[i0, i1] -> scattering[0, i0, 0, i1, 0, 0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_A[1536i0 + i2] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_B[i1 + 1536i2] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_6[i0, i1, i2] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1023 }",
+         "name" : "Stmt_6",
+         "schedule" : "{ Stmt_6[i0, i1, i2] -> scattering[1, i0, 0, i2, 0, i1, 0] }"
+      }
+   ]
+}
diff --git a/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled
new file mode 100644
index 0000000..ab68b5e
--- /dev/null
+++ b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled
@@ -0,0 +1,40 @@
+{
+   "context" : "{ [] }",
+   "name" : "%1 => %17",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_4[i0, i1] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_4[i0, i1] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_4",
+         "schedule" : "{ Stmt_4[i0, i1] -> scattering[0, i0, 0, i1, 0, 0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_A[1536i0 + i2] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_B[i1 + 1536i2] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_6[i0, i1, i2] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1023 }",
+         "name" : "Stmt_6",
+         "schedule" : "{ Stmt_6[i0, i1, i2] -> scattering[1, o0, o1, o2, i0, i2, i1]: o0 <= i0 < o0 + 64 and o1 <= i1 < o1 + 64 and o2 <= i2 < o2 + 64 and o0 % 64 = 0 and o1 % 64 = 0 and o2 % 64 = 0 }"
+      }
+   ]
+}
diff --git a/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled+vector b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled+vector
new file mode 100644
index 0000000..67a1cd9
--- /dev/null
+++ b/final/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled+vector
@@ -0,0 +1,40 @@
+{
+   "context" : "{ [] }",
+   "name" : "%1 => %17",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_4[i0, i1] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_4[i0, i1] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 }",
+         "name" : "Stmt_4",
+         "schedule" : "{ Stmt_4[i0, i1] -> scattering[0, i0, 0, i1, 0, 0, 0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_A[1536i0 + i2] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_B[i1 + 1536i2] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_6[i0, i1, i2] -> MemRef_C[1536i0 + i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_6[i0, i1, i2] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1023 }",
+         "name" : "Stmt_6",
+         "schedule" : "{ Stmt_6[i0, i1, i2] -> scattering[1, o0, o1, o2, i0, i2, ii1, i1]: o0 <= i0 < o0 + 64 and o1 <= i1 < o1 + 64 and o2 <= i2 < o2 + 64 and o0 % 64 = 0 and o1 % 64 = 0 and o2 % 64 = 0 and ii1 % 4 = 0 and ii1 <= i1 < ii1 + 4}"
+      }
+   ]
+}
diff --git a/final/www/experiments/matmul/matmul.c b/final/www/experiments/matmul/matmul.c
new file mode 100644
index 0000000..edb2455
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+
+#define N 1536
+float A[N][N];
+float B[N][N];
+float C[N][N];
+
+void init_array()
+{
+    int i, j;
+
+    for (i=0; i<N; i++) {
+        for (j=0; j<N; j++) {
+            A[i][j] = (1+(i*j)%1024)/2.0;
+            B[i][j] = (1+(i*j)%1024)/2.0;
+        }
+    }
+}
+
+void print_array()
+{
+    int i, j;
+
+    for (i=0; i<N; i++) {
+        for (j=0; j<N; j++) {
+            fprintf(stdout, "%lf ", C[i][j]);
+            if (j%80 == 79) fprintf(stdout, "\n");
+        }
+        fprintf(stdout, "\n");
+    }
+}
+
+int main()
+{
+    int i, j, k;
+    double t_start, t_end;
+
+    init_array();
+
+    for(i=0; i<N; i++)  {
+        for(j=0; j<N; j++)  {
+            C[i][j] = 0;
+            for(k=0; k<N; k++)
+                C[i][j] = C[i][j] + A[i][k] * B[k][j];
+        }
+    }
+
+#ifdef TEST
+    print_array();
+#endif
+    return 0;
+}
diff --git a/final/www/experiments/matmul/matmul.normalopt.exe b/final/www/experiments/matmul/matmul.normalopt.exe
new file mode 100755
index 0000000..cdb9e67
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.normalopt.exe
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.normalopt.ll b/final/www/experiments/matmul/matmul.normalopt.ll
new file mode 100644
index 0000000..ba792c2
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.normalopt.ll
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.normalopt.s b/final/www/experiments/matmul/matmul.normalopt.s
new file mode 100644
index 0000000..079af70
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.normalopt.s
@@ -0,0 +1,274 @@
+	.file	"matmul.normalopt.ll"
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI0_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	init_array
+	.align	16, 0x90
+	.type	init_array,@function
+init_array:                             # @init_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp2:
+	.cfi_def_cfa_offset 16
+.Ltmp3:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp4:
+	.cfi_def_cfa_register %rbp
+	xorl	%r8d, %r8d
+	vmovsd	.LCPI0_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB0_1:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB0_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB0_2:                                # %for.body3
+                                        #   Parent Loop BB0_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%r8d, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%r8, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB0_2
+# BB#3:                                 # %for.inc17
+                                        #   in Loop: Header=BB0_1 Depth=1
+	incq	%r8
+	cmpq	$1536, %r8              # imm = 0x600
+	jne	.LBB0_1
+# BB#4:                                 # %for.end19
+	popq	%rbp
+	ret
+.Ltmp5:
+	.size	init_array, .Ltmp5-init_array
+	.cfi_endproc
+
+	.globl	print_array
+	.align	16, 0x90
+	.type	print_array,@function
+print_array:                            # @print_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp9:
+	.cfi_def_cfa_offset 16
+.Ltmp10:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp11:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r12
+	pushq	%rbx
+.Ltmp12:
+	.cfi_offset %rbx, -48
+.Ltmp13:
+	.cfi_offset %r12, -40
+.Ltmp14:
+	.cfi_offset %r14, -32
+.Ltmp15:
+	.cfi_offset %r15, -24
+	xorl	%r14d, %r14d
+	movl	$C, %r15d
+	.align	16, 0x90
+.LBB1_1:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB1_2 Depth 2
+	movq	stdout(%rip), %rax
+	movq	%r15, %r12
+	xorl	%ebx, %ebx
+	.align	16, 0x90
+.LBB1_2:                                # %for.body3
+                                        #   Parent Loop BB1_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	vmovss	(%r12), %xmm0
+	vcvtss2sd	%xmm0, %xmm0, %xmm0
+	movq	%rax, %rdi
+	movl	$.L.str, %esi
+	movb	$1, %al
+	callq	fprintf
+	movslq	%ebx, %rax
+	imulq	$1717986919, %rax, %rcx # imm = 0x66666667
+	movq	%rcx, %rdx
+	shrq	$63, %rdx
+	sarq	$37, %rcx
+	addl	%edx, %ecx
+	imull	$80, %ecx, %ecx
+	subl	%ecx, %eax
+	cmpl	$79, %eax
+	jne	.LBB1_4
+# BB#3:                                 # %if.then
+                                        #   in Loop: Header=BB1_2 Depth=2
+	movq	stdout(%rip), %rsi
+	movl	$10, %edi
+	callq	fputc
+.LBB1_4:                                # %for.inc
+                                        #   in Loop: Header=BB1_2 Depth=2
+	addq	$4, %r12
+	incq	%rbx
+	movq	stdout(%rip), %rax
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB1_2
+# BB#5:                                 # %for.end
+                                        #   in Loop: Header=BB1_1 Depth=1
+	movl	$10, %edi
+	movq	%rax, %rsi
+	callq	fputc
+	addq	$6144, %r15             # imm = 0x1800
+	incq	%r14
+	cmpq	$1536, %r14             # imm = 0x600
+	jne	.LBB1_1
+# BB#6:                                 # %for.end12
+	popq	%rbx
+	popq	%r12
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp16:
+	.size	print_array, .Ltmp16-print_array
+	.cfi_endproc
+
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI2_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	main
+	.align	16, 0x90
+	.type	main,@function
+main:                                   # @main
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp19:
+	.cfi_def_cfa_offset 16
+.Ltmp20:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp21:
+	.cfi_def_cfa_register %rbp
+	xorl	%r8d, %r8d
+	vmovsd	.LCPI2_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB2_1:                                # %for.cond1.preheader.i
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB2_2:                                # %for.body3.i
+                                        #   Parent Loop BB2_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%r8d, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%r8, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB2_2
+# BB#3:                                 # %for.inc17.i
+                                        #   in Loop: Header=BB2_1 Depth=1
+	incq	%r8
+	cmpq	$1536, %r8              # imm = 0x600
+	jne	.LBB2_1
+# BB#4:
+	xorl	%r8d, %r8d
+	movl	$A, %r9d
+	.align	16, 0x90
+.LBB2_5:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_6 Depth 2
+                                        #       Child Loop BB2_7 Depth 3
+	leaq	(%r8,%r8,2), %rdx
+	shlq	$11, %rdx
+	leaq	C(%rdx), %rsi
+	xorl	%edi, %edi
+	.align	16, 0x90
+.LBB2_6:                                # %for.body3
+                                        #   Parent Loop BB2_5 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB2_7 Depth 3
+	movl	$0, (%rsi)
+	vxorps	%xmm0, %xmm0, %xmm0
+	movq	$-9437184, %rax         # imm = 0xFFFFFFFFFF700000
+	movq	%r9, %rcx
+	.align	16, 0x90
+.LBB2_7:                                # %for.body8
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_6 Depth=2
+                                        # =>    This Inner Loop Header: Depth=3
+	vmovss	(%rcx), %xmm1
+	vmulss	B+9437184(%rax,%rdi,4), %xmm1, %xmm1
+	vaddss	%xmm1, %xmm0, %xmm0
+	addq	$4, %rcx
+	addq	$6144, %rax             # imm = 0x1800
+	jne	.LBB2_7
+# BB#8:                                 # %for.inc25
+                                        #   in Loop: Header=BB2_6 Depth=2
+	vmovss	%xmm0, (%rsi)
+	leaq	C+4(%rdx,%rdi,4), %rsi
+	incq	%rdi
+	cmpq	$1536, %rdi             # imm = 0x600
+	jne	.LBB2_6
+# BB#9:                                 # %for.inc28
+                                        #   in Loop: Header=BB2_5 Depth=1
+	addq	$6144, %r9              # imm = 0x1800
+	incq	%r8
+	cmpq	$1536, %r8              # imm = 0x600
+	jne	.LBB2_5
+# BB#10:                                # %for.end30
+	xorl	%eax, %eax
+	popq	%rbp
+	ret
+.Ltmp22:
+	.size	main, .Ltmp22-main
+	.cfi_endproc
+
+	.type	A,@object               # @A
+	.comm	A,9437184,16
+	.type	B,@object               # @B
+	.comm	B,9437184,16
+	.type	.L.str,@object          # @.str
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.L.str:
+	.asciz	 "%lf "
+	.size	.L.str, 5
+
+	.type	C,@object               # @C
+	.comm	C,9437184,16
+
+	.section	".note.GNU-stack","",@progbits
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.exe b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.exe
new file mode 100755
index 0000000..feb2436
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.exe
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.ll b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.ll
new file mode 100644
index 0000000..593794e
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.ll
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.s b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.s
new file mode 100644
index 0000000..ca87de1
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.s
@@ -0,0 +1,754 @@
+	.file	"matmul.polly.interchanged+tiled+vector+openmp.ll"
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI0_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	init_array
+	.align	16, 0x90
+	.type	init_array,@function
+init_array:                             # @init_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp3:
+	.cfi_def_cfa_offset 16
+.Ltmp4:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp5:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%rbx
+	subq	$24, %rsp
+.Ltmp6:
+	.cfi_offset %rbx, -40
+.Ltmp7:
+	.cfi_offset %r14, -32
+.Ltmp8:
+	.cfi_offset %r15, -24
+	leaq	-32(%rbp), %rsi
+	movl	$init_array.omp_subfn, %edi
+	xorl	%edx, %edx
+	xorl	%ecx, %ecx
+	movl	$1536, %r8d             # imm = 0x600
+	movl	$1, %r9d
+	callq	GOMP_parallel_loop_runtime_start
+	leaq	-40(%rbp), %rdi
+	leaq	-48(%rbp), %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	je	.LBB0_4
+# BB#1:
+	leaq	-40(%rbp), %r14
+	leaq	-48(%rbp), %r15
+	vmovsd	.LCPI0_0(%rip), %xmm1
+	.align	16, 0x90
+.LBB0_2:                                # %omp.loadIVBounds.i
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB0_8 Depth 2
+                                        #       Child Loop BB0_5 Depth 3
+	movq	-48(%rbp), %r8
+	leaq	-1(%r8), %rcx
+	movq	-40(%rbp), %rax
+	cmpq	%rcx, %rax
+	jg	.LBB0_3
+# BB#7:                                 # %polly.loop_preheader4.preheader.i
+                                        #   in Loop: Header=BB0_2 Depth=1
+	addq	$-2, %r8
+	.align	16, 0x90
+.LBB0_8:                                # %polly.loop_preheader4.i
+                                        #   Parent Loop BB0_2 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB0_5 Depth 3
+	xorl	%edx, %edx
+	.align	16, 0x90
+.LBB0_5:                                # %polly.loop_header3.i
+                                        #   Parent Loop BB0_2 Depth=1
+                                        #     Parent Loop BB0_8 Depth=2
+                                        # =>    This Inner Loop Header: Depth=3
+	movl	%edx, %esi
+	imull	%eax, %esi
+	movl	%esi, %edi
+	sarl	$31, %edi
+	shrl	$22, %edi
+	addl	%esi, %edi
+	andl	$-1024, %edi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%edi
+	movq	%rax, %rcx
+	shlq	$11, %rcx
+	leal	1(%rsi,%rdi), %ebx
+	leaq	(%rcx,%rcx,2), %rdi
+	leaq	1(%rdx), %rsi
+	cmpq	$1536, %rsi             # imm = 0x600
+	vcvtsi2sdl	%ebx, %xmm0, %xmm0
+	vmulsd	%xmm1, %xmm0, %xmm0
+	vcvtsd2ss	%xmm0, %xmm0, %xmm0
+	vmovss	%xmm0, A(%rdi,%rdx,4)
+	vmovss	%xmm0, B(%rdi,%rdx,4)
+	movq	%rsi, %rdx
+	jne	.LBB0_5
+# BB#6:                                 # %polly.loop_exit5.i
+                                        #   in Loop: Header=BB0_8 Depth=2
+	cmpq	%r8, %rax
+	leaq	1(%rax), %rax
+	jle	.LBB0_8
+.LBB0_3:                                # %omp.checkNext.backedge.i
+                                        #   in Loop: Header=BB0_2 Depth=1
+	movq	%r14, %rdi
+	movq	%r15, %rsi
+	callq	GOMP_loop_runtime_next
+	vmovsd	.LCPI0_0(%rip), %xmm1
+	testb	%al, %al
+	jne	.LBB0_2
+.LBB0_4:                                # %init_array.omp_subfn.exit
+	callq	GOMP_loop_end_nowait
+	callq	GOMP_parallel_end
+	addq	$24, %rsp
+	popq	%rbx
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp9:
+	.size	init_array, .Ltmp9-init_array
+	.cfi_endproc
+
+	.globl	print_array
+	.align	16, 0x90
+	.type	print_array,@function
+print_array:                            # @print_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp13:
+	.cfi_def_cfa_offset 16
+.Ltmp14:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp15:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r12
+	pushq	%rbx
+.Ltmp16:
+	.cfi_offset %rbx, -48
+.Ltmp17:
+	.cfi_offset %r12, -40
+.Ltmp18:
+	.cfi_offset %r14, -32
+.Ltmp19:
+	.cfi_offset %r15, -24
+	xorl	%r14d, %r14d
+	movl	$C, %r15d
+	.align	16, 0x90
+.LBB1_1:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB1_2 Depth 2
+	movq	stdout(%rip), %rax
+	movq	%r15, %r12
+	xorl	%ebx, %ebx
+	.align	16, 0x90
+.LBB1_2:                                # %for.body3
+                                        #   Parent Loop BB1_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	vmovss	(%r12), %xmm0
+	vcvtss2sd	%xmm0, %xmm0, %xmm0
+	movq	%rax, %rdi
+	movl	$.L.str, %esi
+	movb	$1, %al
+	callq	fprintf
+	movslq	%ebx, %rax
+	imulq	$1717986919, %rax, %rcx # imm = 0x66666667
+	movq	%rcx, %rdx
+	shrq	$63, %rdx
+	sarq	$37, %rcx
+	addl	%edx, %ecx
+	imull	$80, %ecx, %ecx
+	subl	%ecx, %eax
+	cmpl	$79, %eax
+	jne	.LBB1_4
+# BB#3:                                 # %if.then
+                                        #   in Loop: Header=BB1_2 Depth=2
+	movq	stdout(%rip), %rsi
+	movl	$10, %edi
+	callq	fputc
+.LBB1_4:                                # %for.inc
+                                        #   in Loop: Header=BB1_2 Depth=2
+	addq	$4, %r12
+	incq	%rbx
+	movq	stdout(%rip), %rax
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB1_2
+# BB#5:                                 # %for.end
+                                        #   in Loop: Header=BB1_1 Depth=1
+	movl	$10, %edi
+	movq	%rax, %rsi
+	callq	fputc
+	addq	$6144, %r15             # imm = 0x1800
+	incq	%r14
+	cmpq	$1536, %r14             # imm = 0x600
+	jne	.LBB1_1
+# BB#6:                                 # %for.end12
+	popq	%rbx
+	popq	%r12
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp20:
+	.size	print_array, .Ltmp20-print_array
+	.cfi_endproc
+
+	.globl	main
+	.align	16, 0x90
+	.type	main,@function
+main:                                   # @main
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp24:
+	.cfi_def_cfa_offset 16
+.Ltmp25:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp26:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r13
+	pushq	%r12
+	pushq	%rbx
+	subq	$24, %rsp
+.Ltmp27:
+	.cfi_offset %rbx, -56
+.Ltmp28:
+	.cfi_offset %r12, -48
+.Ltmp29:
+	.cfi_offset %r13, -40
+.Ltmp30:
+	.cfi_offset %r14, -32
+.Ltmp31:
+	.cfi_offset %r15, -24
+	callq	init_array
+	leaq	-48(%rbp), %rsi
+	movl	$main.omp_subfn, %edi
+	xorl	%edx, %edx
+	xorl	%ecx, %ecx
+	movl	$1536, %r8d             # imm = 0x600
+	movl	$1, %r9d
+	callq	GOMP_parallel_loop_runtime_start
+	leaq	-56(%rbp), %rdi
+	leaq	-64(%rbp), %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	je	.LBB2_4
+# BB#1:
+	leaq	-56(%rbp), %r14
+	leaq	-64(%rbp), %r15
+	.align	16, 0x90
+.LBB2_2:                                # %omp.loadIVBounds.i
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_6 Depth 2
+	movq	-64(%rbp), %r12
+	leaq	-1(%r12), %rcx
+	movq	-56(%rbp), %rax
+	cmpq	%rcx, %rax
+	jg	.LBB2_3
+# BB#5:                                 # %polly.loop_preheader4.preheader.i
+                                        #   in Loop: Header=BB2_2 Depth=1
+	addq	$-2, %r12
+	leaq	(%rax,%rax,2), %rcx
+	leaq	-1(%rax), %r13
+	shlq	$11, %rcx
+	leaq	C(%rcx), %rbx
+	.align	16, 0x90
+.LBB2_6:                                # %polly.loop_preheader4.i
+                                        #   Parent Loop BB2_2 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movq	%rbx, %rdi
+	xorl	%esi, %esi
+	movl	$6144, %edx             # imm = 0x1800
+	callq	memset
+	addq	$6144, %rbx             # imm = 0x1800
+	incq	%r13
+	cmpq	%r12, %r13
+	jle	.LBB2_6
+.LBB2_3:                                # %omp.checkNext.backedge.i
+                                        #   in Loop: Header=BB2_2 Depth=1
+	movq	%r14, %rdi
+	movq	%r15, %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	jne	.LBB2_2
+.LBB2_4:                                # %main.omp_subfn.exit
+	callq	GOMP_loop_end_nowait
+	callq	GOMP_parallel_end
+	leaq	-48(%rbp), %rbx
+	movl	$main.omp_subfn1, %edi
+	movq	%rbx, %rsi
+	xorl	%edx, %edx
+	xorl	%ecx, %ecx
+	movl	$1536, %r8d             # imm = 0x600
+	movl	$64, %r9d
+	callq	GOMP_parallel_loop_runtime_start
+	movq	%rbx, %rdi
+	callq	main.omp_subfn1
+	callq	GOMP_parallel_end
+	xorl	%eax, %eax
+	addq	$24, %rsp
+	popq	%rbx
+	popq	%r12
+	popq	%r13
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp32:
+	.size	main, .Ltmp32-main
+	.cfi_endproc
+
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI3_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.align	16, 0x90
+	.type	init_array.omp_subfn,@function
+init_array.omp_subfn:                   # @init_array.omp_subfn
+	.cfi_startproc
+# BB#0:                                 # %omp.setup
+	pushq	%rbp
+.Ltmp36:
+	.cfi_def_cfa_offset 16
+.Ltmp37:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp38:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%rbx
+	subq	$24, %rsp
+.Ltmp39:
+	.cfi_offset %rbx, -40
+.Ltmp40:
+	.cfi_offset %r14, -32
+.Ltmp41:
+	.cfi_offset %r15, -24
+	leaq	-32(%rbp), %rdi
+	leaq	-40(%rbp), %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	je	.LBB3_4
+# BB#1:
+	leaq	-32(%rbp), %r14
+	leaq	-40(%rbp), %r15
+	vmovsd	.LCPI3_0(%rip), %xmm1
+	.align	16, 0x90
+.LBB3_2:                                # %omp.loadIVBounds
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB3_8 Depth 2
+                                        #       Child Loop BB3_5 Depth 3
+	movq	-40(%rbp), %r8
+	leaq	-1(%r8), %rcx
+	movq	-32(%rbp), %rax
+	cmpq	%rcx, %rax
+	jg	.LBB3_3
+# BB#7:                                 # %polly.loop_preheader4.preheader
+                                        #   in Loop: Header=BB3_2 Depth=1
+	addq	$-2, %r8
+	.align	16, 0x90
+.LBB3_8:                                # %polly.loop_preheader4
+                                        #   Parent Loop BB3_2 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB3_5 Depth 3
+	xorl	%edx, %edx
+	.align	16, 0x90
+.LBB3_5:                                # %polly.loop_header3
+                                        #   Parent Loop BB3_2 Depth=1
+                                        #     Parent Loop BB3_8 Depth=2
+                                        # =>    This Inner Loop Header: Depth=3
+	movl	%edx, %esi
+	imull	%eax, %esi
+	movl	%esi, %edi
+	sarl	$31, %edi
+	shrl	$22, %edi
+	addl	%esi, %edi
+	andl	$-1024, %edi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%edi
+	movq	%rax, %rcx
+	shlq	$11, %rcx
+	leal	1(%rsi,%rdi), %ebx
+	leaq	(%rcx,%rcx,2), %rdi
+	leaq	1(%rdx), %rsi
+	cmpq	$1536, %rsi             # imm = 0x600
+	vcvtsi2sdl	%ebx, %xmm0, %xmm0
+	vmulsd	%xmm1, %xmm0, %xmm0
+	vcvtsd2ss	%xmm0, %xmm0, %xmm0
+	vmovss	%xmm0, A(%rdi,%rdx,4)
+	vmovss	%xmm0, B(%rdi,%rdx,4)
+	movq	%rsi, %rdx
+	jne	.LBB3_5
+# BB#6:                                 # %polly.loop_exit5
+                                        #   in Loop: Header=BB3_8 Depth=2
+	cmpq	%r8, %rax
+	leaq	1(%rax), %rax
+	jle	.LBB3_8
+.LBB3_3:                                # %omp.checkNext.backedge
+                                        #   in Loop: Header=BB3_2 Depth=1
+	movq	%r14, %rdi
+	movq	%r15, %rsi
+	callq	GOMP_loop_runtime_next
+	vmovsd	.LCPI3_0(%rip), %xmm1
+	testb	%al, %al
+	jne	.LBB3_2
+.LBB3_4:                                # %omp.exit
+	callq	GOMP_loop_end_nowait
+	addq	$24, %rsp
+	popq	%rbx
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp42:
+	.size	init_array.omp_subfn, .Ltmp42-init_array.omp_subfn
+	.cfi_endproc
+
+	.align	16, 0x90
+	.type	main.omp_subfn,@function
+main.omp_subfn:                         # @main.omp_subfn
+	.cfi_startproc
+# BB#0:                                 # %omp.setup
+	pushq	%rbp
+.Ltmp46:
+	.cfi_def_cfa_offset 16
+.Ltmp47:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp48:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r13
+	pushq	%r12
+	pushq	%rbx
+	subq	$24, %rsp
+.Ltmp49:
+	.cfi_offset %rbx, -56
+.Ltmp50:
+	.cfi_offset %r12, -48
+.Ltmp51:
+	.cfi_offset %r13, -40
+.Ltmp52:
+	.cfi_offset %r14, -32
+.Ltmp53:
+	.cfi_offset %r15, -24
+	leaq	-48(%rbp), %rdi
+	leaq	-56(%rbp), %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	je	.LBB4_4
+# BB#1:
+	leaq	-48(%rbp), %r14
+	leaq	-56(%rbp), %r15
+	.align	16, 0x90
+.LBB4_2:                                # %omp.loadIVBounds
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB4_6 Depth 2
+	movq	-56(%rbp), %r12
+	leaq	-1(%r12), %rcx
+	movq	-48(%rbp), %rax
+	cmpq	%rcx, %rax
+	jg	.LBB4_3
+# BB#5:                                 # %polly.loop_preheader4.preheader
+                                        #   in Loop: Header=BB4_2 Depth=1
+	addq	$-2, %r12
+	leaq	(%rax,%rax,2), %rcx
+	leaq	-1(%rax), %r13
+	shlq	$11, %rcx
+	leaq	C(%rcx), %rbx
+	.align	16, 0x90
+.LBB4_6:                                # %polly.loop_preheader4
+                                        #   Parent Loop BB4_2 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movq	%rbx, %rdi
+	xorl	%esi, %esi
+	movl	$6144, %edx             # imm = 0x1800
+	callq	memset
+	addq	$6144, %rbx             # imm = 0x1800
+	incq	%r13
+	cmpq	%r12, %r13
+	jle	.LBB4_6
+.LBB4_3:                                # %omp.checkNext.backedge
+                                        #   in Loop: Header=BB4_2 Depth=1
+	movq	%r14, %rdi
+	movq	%r15, %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	jne	.LBB4_2
+.LBB4_4:                                # %omp.exit
+	callq	GOMP_loop_end_nowait
+	addq	$24, %rsp
+	popq	%rbx
+	popq	%r12
+	popq	%r13
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp54:
+	.size	main.omp_subfn, .Ltmp54-main.omp_subfn
+	.cfi_endproc
+
+	.align	16, 0x90
+	.type	main.omp_subfn1,@function
+main.omp_subfn1:                        # @main.omp_subfn1
+	.cfi_startproc
+# BB#0:                                 # %omp.setup
+	pushq	%rbp
+.Ltmp58:
+	.cfi_def_cfa_offset 16
+.Ltmp59:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp60:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r13
+	pushq	%r12
+	pushq	%rbx
+	subq	$72, %rsp
+.Ltmp61:
+	.cfi_offset %rbx, -56
+.Ltmp62:
+	.cfi_offset %r12, -48
+.Ltmp63:
+	.cfi_offset %r13, -40
+.Ltmp64:
+	.cfi_offset %r14, -32
+.Ltmp65:
+	.cfi_offset %r15, -24
+	jmp	.LBB5_1
+	.align	16, 0x90
+.LBB5_2:                                # %omp.loadIVBounds
+                                        #   in Loop: Header=BB5_1 Depth=1
+	movq	-56(%rbp), %rax
+	movq	%rax, -112(%rbp)        # 8-byte Spill
+	leaq	-1(%rax), %rax
+	movq	-48(%rbp), %rcx
+	cmpq	%rax, %rcx
+	jg	.LBB5_1
+# BB#3:                                 # %polly.loop_preheader4.preheader
+                                        #   in Loop: Header=BB5_1 Depth=1
+	leaq	-1(%rcx), %rax
+	movq	%rax, -88(%rbp)         # 8-byte Spill
+	addq	$-65, -112(%rbp)        # 8-byte Folded Spill
+	movq	%rcx, %rax
+	shlq	$9, %rax
+	leaq	(%rax,%rax,2), %rax
+	leaq	C+16(,%rax,4), %rax
+	movq	%rax, -104(%rbp)        # 8-byte Spill
+	.align	16, 0x90
+.LBB5_7:                                # %polly.loop_preheader4
+                                        #   Parent Loop BB5_1 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB5_8 Depth 3
+                                        #         Child Loop BB5_9 Depth 4
+                                        #           Child Loop BB5_12 Depth 5
+                                        #             Child Loop BB5_17 Depth 6
+                                        #               Child Loop BB5_18 Depth 7
+                                        #           Child Loop BB5_14 Depth 5
+	movq	%rcx, -72(%rbp)         # 8-byte Spill
+	leaq	62(%rcx), %rdi
+	xorl	%edx, %edx
+	.align	16, 0x90
+.LBB5_8:                                # %polly.loop_preheader11
+                                        #   Parent Loop BB5_1 Depth=1
+                                        #     Parent Loop BB5_7 Depth=2
+                                        # =>    This Loop Header: Depth=3
+                                        #         Child Loop BB5_9 Depth 4
+                                        #           Child Loop BB5_12 Depth 5
+                                        #             Child Loop BB5_17 Depth 6
+                                        #               Child Loop BB5_18 Depth 7
+                                        #           Child Loop BB5_14 Depth 5
+	movq	%rdx, -96(%rbp)         # 8-byte Spill
+	leaq	-4(%rdx), %rcx
+	movq	%rdx, %rax
+	decq	%rax
+	cmovsq	%rcx, %rax
+	movq	%rax, %r14
+	sarq	$63, %r14
+	shrq	$62, %r14
+	addq	%rax, %r14
+	andq	$-4, %r14
+	movq	%rdx, %rax
+	orq	$63, %rax
+	leaq	-4(%rax), %rdx
+	movq	-104(%rbp), %rcx        # 8-byte Reload
+	leaq	(%rcx,%r14,4), %rcx
+	movq	%rcx, -80(%rbp)         # 8-byte Spill
+	leaq	B+16(,%r14,4), %rbx
+	leaq	4(%r14), %rcx
+	movq	%rcx, -64(%rbp)         # 8-byte Spill
+	xorl	%r11d, %r11d
+	.align	16, 0x90
+.LBB5_9:                                # %polly.loop_header10
+                                        #   Parent Loop BB5_1 Depth=1
+                                        #     Parent Loop BB5_7 Depth=2
+                                        #       Parent Loop BB5_8 Depth=3
+                                        # =>      This Loop Header: Depth=4
+                                        #           Child Loop BB5_12 Depth 5
+                                        #             Child Loop BB5_17 Depth 6
+                                        #               Child Loop BB5_18 Depth 7
+                                        #           Child Loop BB5_14 Depth 5
+	movabsq	$9223372036854775744, %rcx # imm = 0x7FFFFFFFFFFFFFC0
+	cmpq	%rcx, -72(%rbp)         # 8-byte Folded Reload
+	jg	.LBB5_15
+# BB#10:                                # %polly.loop_header17.preheader
+                                        #   in Loop: Header=BB5_9 Depth=4
+	movq	%r11, %r15
+	orq	$63, %r15
+	cmpq	%r15, %r11
+	movq	-88(%rbp), %rcx         # 8-byte Reload
+	jle	.LBB5_11
+	.align	16, 0x90
+.LBB5_14:                               # %polly.loop_exit28.us
+                                        #   Parent Loop BB5_1 Depth=1
+                                        #     Parent Loop BB5_7 Depth=2
+                                        #       Parent Loop BB5_8 Depth=3
+                                        #         Parent Loop BB5_9 Depth=4
+                                        # =>        This Inner Loop Header: Depth=5
+	incq	%rcx
+	cmpq	%rdi, %rcx
+	jle	.LBB5_14
+	jmp	.LBB5_15
+	.align	16, 0x90
+.LBB5_11:                               #   in Loop: Header=BB5_9 Depth=4
+	decq	%r15
+	movq	-80(%rbp), %r13         # 8-byte Reload
+	movq	-72(%rbp), %rcx         # 8-byte Reload
+	.align	16, 0x90
+.LBB5_12:                               # %polly.loop_header26.preheader
+                                        #   Parent Loop BB5_1 Depth=1
+                                        #     Parent Loop BB5_7 Depth=2
+                                        #       Parent Loop BB5_8 Depth=3
+                                        #         Parent Loop BB5_9 Depth=4
+                                        # =>        This Loop Header: Depth=5
+                                        #             Child Loop BB5_17 Depth 6
+                                        #               Child Loop BB5_18 Depth 7
+	cmpq	%rax, -64(%rbp)         # 8-byte Folded Reload
+	movq	%rbx, %r12
+	movq	%r11, %r8
+	jg	.LBB5_13
+	.align	16, 0x90
+.LBB5_17:                               # %polly.loop_header35.preheader
+                                        #   Parent Loop BB5_1 Depth=1
+                                        #     Parent Loop BB5_7 Depth=2
+                                        #       Parent Loop BB5_8 Depth=3
+                                        #         Parent Loop BB5_9 Depth=4
+                                        #           Parent Loop BB5_12 Depth=5
+                                        # =>          This Loop Header: Depth=6
+                                        #               Child Loop BB5_18 Depth 7
+	leaq	(%rcx,%rcx,2), %rsi
+	shlq	$11, %rsi
+	vbroadcastss	A(%rsi,%r8,4), %xmm0
+	movq	%r13, %r9
+	movq	%r12, %r10
+	movq	%r14, %rsi
+.LBB5_18:                               # %polly.loop_header35
+                                        #   Parent Loop BB5_1 Depth=1
+                                        #     Parent Loop BB5_7 Depth=2
+                                        #       Parent Loop BB5_8 Depth=3
+                                        #         Parent Loop BB5_9 Depth=4
+                                        #           Parent Loop BB5_12 Depth=5
+                                        #             Parent Loop BB5_17 Depth=6
+                                        # =>            This Inner Loop Header: Depth=7
+	vmulps	(%r10), %xmm0, %xmm1
+	vaddps	(%r9), %xmm1, %xmm1
+	vmovaps	%xmm1, (%r9)
+	addq	$16, %r9
+	addq	$16, %r10
+	addq	$4, %rsi
+	cmpq	%rdx, %rsi
+	jle	.LBB5_18
+# BB#16:                                # %polly.loop_exit37
+                                        #   in Loop: Header=BB5_17 Depth=6
+	addq	$6144, %r12             # imm = 0x1800
+	cmpq	%r15, %r8
+	leaq	1(%r8), %r8
+	jle	.LBB5_17
+	.align	16, 0x90
+.LBB5_13:                               # %polly.loop_exit28
+                                        #   in Loop: Header=BB5_12 Depth=5
+	addq	$6144, %r13             # imm = 0x1800
+	cmpq	%rdi, %rcx
+	leaq	1(%rcx), %rcx
+	jle	.LBB5_12
+	.align	16, 0x90
+.LBB5_15:                               # %polly.loop_exit19
+                                        #   in Loop: Header=BB5_9 Depth=4
+	addq	$393216, %rbx           # imm = 0x60000
+	cmpq	$1472, %r11             # imm = 0x5C0
+	leaq	64(%r11), %r11
+	jl	.LBB5_9
+# BB#5:                                 # %polly.loop_exit12
+                                        #   in Loop: Header=BB5_8 Depth=3
+	movq	-96(%rbp), %rdx         # 8-byte Reload
+	cmpq	$1472, %rdx             # imm = 0x5C0
+	leaq	64(%rdx), %rdx
+	jl	.LBB5_8
+# BB#6:                                 # %polly.loop_exit5
+                                        #   in Loop: Header=BB5_7 Depth=2
+	addq	$64, -88(%rbp)          # 8-byte Folded Spill
+	addq	$393216, -104(%rbp)     # 8-byte Folded Spill
+                                        # imm = 0x60000
+	movq	-72(%rbp), %rcx         # 8-byte Reload
+	cmpq	-112(%rbp), %rcx        # 8-byte Folded Reload
+	leaq	64(%rcx), %rcx
+	jle	.LBB5_7
+.LBB5_1:                                # %omp.setup
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB5_7 Depth 2
+                                        #       Child Loop BB5_8 Depth 3
+                                        #         Child Loop BB5_9 Depth 4
+                                        #           Child Loop BB5_12 Depth 5
+                                        #             Child Loop BB5_17 Depth 6
+                                        #               Child Loop BB5_18 Depth 7
+                                        #           Child Loop BB5_14 Depth 5
+	leaq	-48(%rbp), %rdi
+	leaq	-56(%rbp), %rsi
+	callq	GOMP_loop_runtime_next
+	testb	%al, %al
+	jne	.LBB5_2
+# BB#4:                                 # %omp.exit
+	callq	GOMP_loop_end_nowait
+	addq	$72, %rsp
+	popq	%rbx
+	popq	%r12
+	popq	%r13
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp66:
+	.size	main.omp_subfn1, .Ltmp66-main.omp_subfn1
+	.cfi_endproc
+
+	.type	A,@object               # @A
+	.comm	A,9437184,16
+	.type	B,@object               # @B
+	.comm	B,9437184,16
+	.type	.L.str,@object          # @.str
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.L.str:
+	.asciz	 "%lf "
+	.size	.L.str, 5
+
+	.type	C,@object               # @C
+	.comm	C,9437184,16
+
+	.section	".note.GNU-stack","",@progbits
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.exe b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.exe
new file mode 100755
index 0000000..36b788e
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.exe
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.ll b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.ll
new file mode 100644
index 0000000..9d1f9ad
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.ll
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.s b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.s
new file mode 100644
index 0000000..485d230
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.s
@@ -0,0 +1,396 @@
+	.file	"matmul.polly.interchanged+tiled+vector.ll"
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI0_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	init_array
+	.align	16, 0x90
+	.type	init_array,@function
+init_array:                             # @init_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp2:
+	.cfi_def_cfa_offset 16
+.Ltmp3:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp4:
+	.cfi_def_cfa_register %rbp
+	xorl	%r8d, %r8d
+	vmovsd	.LCPI0_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB0_1:                                # %polly.loop_preheader3
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB0_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB0_2:                                # %polly.loop_header2
+                                        #   Parent Loop BB0_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%r8d, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%r8, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB0_2
+# BB#3:                                 # %polly.loop_exit4
+                                        #   in Loop: Header=BB0_1 Depth=1
+	incq	%r8
+	cmpq	$1536, %r8              # imm = 0x600
+	jne	.LBB0_1
+# BB#4:                                 # %polly.loop_exit
+	popq	%rbp
+	ret
+.Ltmp5:
+	.size	init_array, .Ltmp5-init_array
+	.cfi_endproc
+
+	.globl	print_array
+	.align	16, 0x90
+	.type	print_array,@function
+print_array:                            # @print_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp9:
+	.cfi_def_cfa_offset 16
+.Ltmp10:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp11:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r12
+	pushq	%rbx
+.Ltmp12:
+	.cfi_offset %rbx, -48
+.Ltmp13:
+	.cfi_offset %r12, -40
+.Ltmp14:
+	.cfi_offset %r14, -32
+.Ltmp15:
+	.cfi_offset %r15, -24
+	xorl	%r14d, %r14d
+	movl	$C, %r15d
+	.align	16, 0x90
+.LBB1_1:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB1_2 Depth 2
+	movq	stdout(%rip), %rax
+	movq	%r15, %r12
+	xorl	%ebx, %ebx
+	.align	16, 0x90
+.LBB1_2:                                # %for.body3
+                                        #   Parent Loop BB1_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	vmovss	(%r12), %xmm0
+	vcvtss2sd	%xmm0, %xmm0, %xmm0
+	movq	%rax, %rdi
+	movl	$.L.str, %esi
+	movb	$1, %al
+	callq	fprintf
+	movslq	%ebx, %rax
+	imulq	$1717986919, %rax, %rcx # imm = 0x66666667
+	movq	%rcx, %rdx
+	shrq	$63, %rdx
+	sarq	$37, %rcx
+	addl	%edx, %ecx
+	imull	$80, %ecx, %ecx
+	subl	%ecx, %eax
+	cmpl	$79, %eax
+	jne	.LBB1_4
+# BB#3:                                 # %if.then
+                                        #   in Loop: Header=BB1_2 Depth=2
+	movq	stdout(%rip), %rsi
+	movl	$10, %edi
+	callq	fputc
+.LBB1_4:                                # %for.inc
+                                        #   in Loop: Header=BB1_2 Depth=2
+	addq	$4, %r12
+	incq	%rbx
+	movq	stdout(%rip), %rax
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB1_2
+# BB#5:                                 # %for.end
+                                        #   in Loop: Header=BB1_1 Depth=1
+	movl	$10, %edi
+	movq	%rax, %rsi
+	callq	fputc
+	addq	$6144, %r15             # imm = 0x1800
+	incq	%r14
+	cmpq	$1536, %r14             # imm = 0x600
+	jne	.LBB1_1
+# BB#6:                                 # %for.end12
+	popq	%rbx
+	popq	%r12
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp16:
+	.size	print_array, .Ltmp16-print_array
+	.cfi_endproc
+
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI2_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	main
+	.align	16, 0x90
+	.type	main,@function
+main:                                   # @main
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp20:
+	.cfi_def_cfa_offset 16
+.Ltmp21:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp22:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r13
+	pushq	%r12
+	pushq	%rbx
+	subq	$56, %rsp
+.Ltmp23:
+	.cfi_offset %rbx, -56
+.Ltmp24:
+	.cfi_offset %r12, -48
+.Ltmp25:
+	.cfi_offset %r13, -40
+.Ltmp26:
+	.cfi_offset %r14, -32
+.Ltmp27:
+	.cfi_offset %r15, -24
+	xorl	%ebx, %ebx
+	vmovsd	.LCPI2_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB2_1:                                # %polly.loop_preheader3.i
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB2_2:                                # %polly.loop_header2.i
+                                        #   Parent Loop BB2_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%ebx, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%rbx, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB2_2
+# BB#3:                                 # %polly.loop_exit4.i
+                                        #   in Loop: Header=BB2_1 Depth=1
+	incq	%rbx
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB2_1
+# BB#4:                                 # %polly.loop_preheader3.preheader
+	movl	$C, %edi
+	xorl	%esi, %esi
+	movl	$9437184, %edx          # imm = 0x900000
+	callq	memset
+	xorl	%esi, %esi
+	movl	$C+16, %eax
+	movq	%rax, -88(%rbp)         # 8-byte Spill
+	.align	16, 0x90
+.LBB2_5:                                # %polly.loop_preheader17
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_15 Depth 2
+                                        #       Child Loop BB2_8 Depth 3
+                                        #         Child Loop BB2_11 Depth 4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	movq	%rsi, -56(%rbp)         # 8-byte Spill
+	movq	%rsi, %rax
+	orq	$63, %rax
+	movq	%rax, -72(%rbp)         # 8-byte Spill
+	leaq	-1(%rax), %rax
+	movq	%rax, -48(%rbp)         # 8-byte Spill
+	xorl	%edx, %edx
+	.align	16, 0x90
+.LBB2_15:                               # %polly.loop_preheader24
+                                        #   Parent Loop BB2_5 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB2_8 Depth 3
+                                        #         Child Loop BB2_11 Depth 4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	movq	%rdx, -80(%rbp)         # 8-byte Spill
+	leaq	-4(%rdx), %rcx
+	movq	%rdx, %rax
+	decq	%rax
+	cmovsq	%rcx, %rax
+	movq	%rax, %r15
+	sarq	$63, %r15
+	shrq	$62, %r15
+	addq	%rax, %r15
+	andq	$-4, %r15
+	movq	%rdx, %r13
+	orq	$63, %r13
+	leaq	-4(%r13), %rdx
+	xorl	%r10d, %r10d
+	movq	-88(%rbp), %rax         # 8-byte Reload
+	leaq	(%rax,%r15,4), %rax
+	movq	%rax, -64(%rbp)         # 8-byte Spill
+	leaq	B+16(,%r15,4), %rbx
+	leaq	4(%r15), %r12
+	.align	16, 0x90
+.LBB2_8:                                # %polly.loop_header23
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        # =>    This Loop Header: Depth=3
+                                        #         Child Loop BB2_11 Depth 4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	cmpq	-72(%rbp), %rsi         # 8-byte Folded Reload
+	jg	.LBB2_13
+# BB#9:                                 # %polly.loop_header30.preheader
+                                        #   in Loop: Header=BB2_8 Depth=3
+	movq	%r10, %rax
+	orq	$63, %rax
+	cmpq	%rax, %r10
+	jg	.LBB2_13
+# BB#10:                                #   in Loop: Header=BB2_8 Depth=3
+	decq	%rax
+	movq	-64(%rbp), %r14         # 8-byte Reload
+	movq	-56(%rbp), %r11         # 8-byte Reload
+	.align	16, 0x90
+.LBB2_11:                               # %polly.loop_header37.preheader
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        #       Parent Loop BB2_8 Depth=3
+                                        # =>      This Loop Header: Depth=4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	cmpq	%r13, %r12
+	movq	%rbx, %r8
+	movq	%r10, %rsi
+	jg	.LBB2_12
+	.align	16, 0x90
+.LBB2_17:                               # %polly.loop_header46.preheader
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        #       Parent Loop BB2_8 Depth=3
+                                        #         Parent Loop BB2_11 Depth=4
+                                        # =>        This Loop Header: Depth=5
+                                        #             Child Loop BB2_18 Depth 6
+	leaq	(%r11,%r11,2), %rcx
+	shlq	$11, %rcx
+	vbroadcastss	A(%rcx,%rsi,4), %xmm0
+	movq	%r14, %rdi
+	movq	%r8, %r9
+	movq	%r15, %rcx
+.LBB2_18:                               # %polly.loop_header46
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        #       Parent Loop BB2_8 Depth=3
+                                        #         Parent Loop BB2_11 Depth=4
+                                        #           Parent Loop BB2_17 Depth=5
+                                        # =>          This Inner Loop Header: Depth=6
+	vmulps	(%r9), %xmm0, %xmm1
+	vaddps	(%rdi), %xmm1, %xmm1
+	vmovaps	%xmm1, (%rdi)
+	addq	$16, %rdi
+	addq	$16, %r9
+	addq	$4, %rcx
+	cmpq	%rdx, %rcx
+	jle	.LBB2_18
+# BB#16:                                # %polly.loop_exit48
+                                        #   in Loop: Header=BB2_17 Depth=5
+	addq	$6144, %r8              # imm = 0x1800
+	cmpq	%rax, %rsi
+	leaq	1(%rsi), %rsi
+	jle	.LBB2_17
+	.align	16, 0x90
+.LBB2_12:                               # %polly.loop_exit39
+                                        #   in Loop: Header=BB2_11 Depth=4
+	addq	$6144, %r14             # imm = 0x1800
+	cmpq	-48(%rbp), %r11         # 8-byte Folded Reload
+	leaq	1(%r11), %r11
+	jle	.LBB2_11
+	.align	16, 0x90
+.LBB2_13:                               # %polly.loop_exit32
+                                        #   in Loop: Header=BB2_8 Depth=3
+	addq	$393216, %rbx           # imm = 0x60000
+	cmpq	$1472, %r10             # imm = 0x5C0
+	leaq	64(%r10), %r10
+	movq	-56(%rbp), %rsi         # 8-byte Reload
+	jl	.LBB2_8
+# BB#14:                                # %polly.loop_exit25
+                                        #   in Loop: Header=BB2_15 Depth=2
+	movq	-80(%rbp), %rdx         # 8-byte Reload
+	cmpq	$1472, %rdx             # imm = 0x5C0
+	leaq	64(%rdx), %rdx
+	jl	.LBB2_15
+# BB#6:                                 # %polly.loop_exit18
+                                        #   in Loop: Header=BB2_5 Depth=1
+	addq	$393216, -88(%rbp)      # 8-byte Folded Spill
+                                        # imm = 0x60000
+	cmpq	$1472, %rsi             # imm = 0x5C0
+	leaq	64(%rsi), %rsi
+	jl	.LBB2_5
+# BB#7:                                 # %polly.loop_exit11
+	xorl	%eax, %eax
+	addq	$56, %rsp
+	popq	%rbx
+	popq	%r12
+	popq	%r13
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp28:
+	.size	main, .Ltmp28-main
+	.cfi_endproc
+
+	.type	A,@object               # @A
+	.comm	A,9437184,16
+	.type	B,@object               # @B
+	.comm	B,9437184,16
+	.type	.L.str,@object          # @.str
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.L.str:
+	.asciz	 "%lf "
+	.size	.L.str, 5
+
+	.type	C,@object               # @C
+	.comm	C,9437184,16
+
+	.section	".note.GNU-stack","",@progbits
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled.exe b/final/www/experiments/matmul/matmul.polly.interchanged+tiled.exe
new file mode 100755
index 0000000..fbd8b12
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled.exe
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled.ll b/final/www/experiments/matmul/matmul.polly.interchanged+tiled.ll
new file mode 100644
index 0000000..acdd95f
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled.ll
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged+tiled.s b/final/www/experiments/matmul/matmul.polly.interchanged+tiled.s
new file mode 100644
index 0000000..f7ab7fd
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged+tiled.s
@@ -0,0 +1,390 @@
+	.file	"matmul.polly.interchanged+tiled.ll"
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI0_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	init_array
+	.align	16, 0x90
+	.type	init_array,@function
+init_array:                             # @init_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp2:
+	.cfi_def_cfa_offset 16
+.Ltmp3:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp4:
+	.cfi_def_cfa_register %rbp
+	xorl	%r8d, %r8d
+	vmovsd	.LCPI0_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB0_1:                                # %polly.loop_preheader3
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB0_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB0_2:                                # %polly.loop_header2
+                                        #   Parent Loop BB0_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%r8d, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%r8, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB0_2
+# BB#3:                                 # %polly.loop_exit4
+                                        #   in Loop: Header=BB0_1 Depth=1
+	incq	%r8
+	cmpq	$1536, %r8              # imm = 0x600
+	jne	.LBB0_1
+# BB#4:                                 # %polly.loop_exit
+	popq	%rbp
+	ret
+.Ltmp5:
+	.size	init_array, .Ltmp5-init_array
+	.cfi_endproc
+
+	.globl	print_array
+	.align	16, 0x90
+	.type	print_array,@function
+print_array:                            # @print_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp9:
+	.cfi_def_cfa_offset 16
+.Ltmp10:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp11:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r12
+	pushq	%rbx
+.Ltmp12:
+	.cfi_offset %rbx, -48
+.Ltmp13:
+	.cfi_offset %r12, -40
+.Ltmp14:
+	.cfi_offset %r14, -32
+.Ltmp15:
+	.cfi_offset %r15, -24
+	xorl	%r14d, %r14d
+	movl	$C, %r15d
+	.align	16, 0x90
+.LBB1_1:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB1_2 Depth 2
+	movq	stdout(%rip), %rax
+	movq	%r15, %r12
+	xorl	%ebx, %ebx
+	.align	16, 0x90
+.LBB1_2:                                # %for.body3
+                                        #   Parent Loop BB1_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	vmovss	(%r12), %xmm0
+	vcvtss2sd	%xmm0, %xmm0, %xmm0
+	movq	%rax, %rdi
+	movl	$.L.str, %esi
+	movb	$1, %al
+	callq	fprintf
+	movslq	%ebx, %rax
+	imulq	$1717986919, %rax, %rcx # imm = 0x66666667
+	movq	%rcx, %rdx
+	shrq	$63, %rdx
+	sarq	$37, %rcx
+	addl	%edx, %ecx
+	imull	$80, %ecx, %ecx
+	subl	%ecx, %eax
+	cmpl	$79, %eax
+	jne	.LBB1_4
+# BB#3:                                 # %if.then
+                                        #   in Loop: Header=BB1_2 Depth=2
+	movq	stdout(%rip), %rsi
+	movl	$10, %edi
+	callq	fputc
+.LBB1_4:                                # %for.inc
+                                        #   in Loop: Header=BB1_2 Depth=2
+	addq	$4, %r12
+	incq	%rbx
+	movq	stdout(%rip), %rax
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB1_2
+# BB#5:                                 # %for.end
+                                        #   in Loop: Header=BB1_1 Depth=1
+	movl	$10, %edi
+	movq	%rax, %rsi
+	callq	fputc
+	addq	$6144, %r15             # imm = 0x1800
+	incq	%r14
+	cmpq	$1536, %r14             # imm = 0x600
+	jne	.LBB1_1
+# BB#6:                                 # %for.end12
+	popq	%rbx
+	popq	%r12
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp16:
+	.size	print_array, .Ltmp16-print_array
+	.cfi_endproc
+
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI2_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	main
+	.align	16, 0x90
+	.type	main,@function
+main:                                   # @main
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp20:
+	.cfi_def_cfa_offset 16
+.Ltmp21:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp22:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r13
+	pushq	%r12
+	pushq	%rbx
+	subq	$56, %rsp
+.Ltmp23:
+	.cfi_offset %rbx, -56
+.Ltmp24:
+	.cfi_offset %r12, -48
+.Ltmp25:
+	.cfi_offset %r13, -40
+.Ltmp26:
+	.cfi_offset %r14, -32
+.Ltmp27:
+	.cfi_offset %r15, -24
+	xorl	%ebx, %ebx
+	vmovsd	.LCPI2_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB2_1:                                # %polly.loop_preheader3.i
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB2_2:                                # %polly.loop_header2.i
+                                        #   Parent Loop BB2_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%ebx, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%rbx, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB2_2
+# BB#3:                                 # %polly.loop_exit4.i
+                                        #   in Loop: Header=BB2_1 Depth=1
+	incq	%rbx
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB2_1
+# BB#4:                                 # %polly.loop_preheader3.preheader
+	movl	$C, %ebx
+	movl	$C, %edi
+	xorl	%esi, %esi
+	movl	$9437184, %edx          # imm = 0x900000
+	callq	memset
+	xorl	%eax, %eax
+	.align	16, 0x90
+.LBB2_5:                                # %polly.loop_preheader17
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_15 Depth 2
+                                        #       Child Loop BB2_8 Depth 3
+                                        #         Child Loop BB2_11 Depth 4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	movq	%rax, -56(%rbp)         # 8-byte Spill
+	movq	%rbx, -88(%rbp)         # 8-byte Spill
+	movq	%rax, %rcx
+	orq	$63, %rcx
+	movq	%rcx, -72(%rbp)         # 8-byte Spill
+	leaq	-1(%rcx), %rcx
+	movq	%rcx, -48(%rbp)         # 8-byte Spill
+	movq	$-1, %r15
+	movl	$B, %ecx
+	movq	%rbx, -64(%rbp)         # 8-byte Spill
+	xorl	%r12d, %r12d
+	.align	16, 0x90
+.LBB2_15:                               # %polly.loop_preheader24
+                                        #   Parent Loop BB2_5 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB2_8 Depth 3
+                                        #         Child Loop BB2_11 Depth 4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	movq	%rcx, -80(%rbp)         # 8-byte Spill
+	movq	%r12, %r13
+	orq	$63, %r13
+	leaq	-1(%r13), %rbx
+	xorl	%r9d, %r9d
+	movq	%rcx, %rdx
+	.align	16, 0x90
+.LBB2_8:                                # %polly.loop_header23
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        # =>    This Loop Header: Depth=3
+                                        #         Child Loop BB2_11 Depth 4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	cmpq	-72(%rbp), %rax         # 8-byte Folded Reload
+	jg	.LBB2_13
+# BB#9:                                 # %polly.loop_header30.preheader
+                                        #   in Loop: Header=BB2_8 Depth=3
+	movq	%r9, %rax
+	orq	$63, %rax
+	cmpq	%rax, %r9
+	jg	.LBB2_13
+# BB#10:                                #   in Loop: Header=BB2_8 Depth=3
+	decq	%rax
+	movq	-64(%rbp), %r10         # 8-byte Reload
+	movq	-56(%rbp), %r11         # 8-byte Reload
+	.align	16, 0x90
+.LBB2_11:                               # %polly.loop_header37.preheader
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        #       Parent Loop BB2_8 Depth=3
+                                        # =>      This Loop Header: Depth=4
+                                        #           Child Loop BB2_17 Depth 5
+                                        #             Child Loop BB2_18 Depth 6
+	cmpq	%r13, %r12
+	movq	%rdx, %r14
+	movq	%r9, %rcx
+	jg	.LBB2_12
+	.align	16, 0x90
+.LBB2_17:                               # %polly.loop_header46.preheader
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        #       Parent Loop BB2_8 Depth=3
+                                        #         Parent Loop BB2_11 Depth=4
+                                        # =>        This Loop Header: Depth=5
+                                        #             Child Loop BB2_18 Depth 6
+	leaq	(%r11,%r11,2), %rsi
+	shlq	$11, %rsi
+	vmovss	A(%rsi,%rcx,4), %xmm0
+	movq	%r10, %rdi
+	movq	%r14, %r8
+	movq	%r15, %rsi
+.LBB2_18:                               # %polly.loop_header46
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_15 Depth=2
+                                        #       Parent Loop BB2_8 Depth=3
+                                        #         Parent Loop BB2_11 Depth=4
+                                        #           Parent Loop BB2_17 Depth=5
+                                        # =>          This Inner Loop Header: Depth=6
+	vmulss	(%r8), %xmm0, %xmm1
+	vaddss	(%rdi), %xmm1, %xmm1
+	vmovss	%xmm1, (%rdi)
+	addq	$4, %rdi
+	addq	$4, %r8
+	incq	%rsi
+	cmpq	%rbx, %rsi
+	jle	.LBB2_18
+# BB#16:                                # %polly.loop_exit48
+                                        #   in Loop: Header=BB2_17 Depth=5
+	addq	$6144, %r14             # imm = 0x1800
+	cmpq	%rax, %rcx
+	leaq	1(%rcx), %rcx
+	jle	.LBB2_17
+	.align	16, 0x90
+.LBB2_12:                               # %polly.loop_exit39
+                                        #   in Loop: Header=BB2_11 Depth=4
+	addq	$6144, %r10             # imm = 0x1800
+	cmpq	-48(%rbp), %r11         # 8-byte Folded Reload
+	leaq	1(%r11), %r11
+	jle	.LBB2_11
+	.align	16, 0x90
+.LBB2_13:                               # %polly.loop_exit32
+                                        #   in Loop: Header=BB2_8 Depth=3
+	addq	$393216, %rdx           # imm = 0x60000
+	cmpq	$1472, %r9              # imm = 0x5C0
+	leaq	64(%r9), %r9
+	movq	-56(%rbp), %rax         # 8-byte Reload
+	jl	.LBB2_8
+# BB#14:                                # %polly.loop_exit25
+                                        #   in Loop: Header=BB2_15 Depth=2
+	addq	$256, -64(%rbp)         # 8-byte Folded Spill
+                                        # imm = 0x100
+	movq	-80(%rbp), %rcx         # 8-byte Reload
+	addq	$256, %rcx              # imm = 0x100
+	addq	$64, %r15
+	cmpq	$1472, %r12             # imm = 0x5C0
+	leaq	64(%r12), %r12
+	jl	.LBB2_15
+# BB#6:                                 # %polly.loop_exit18
+                                        #   in Loop: Header=BB2_5 Depth=1
+	movq	-88(%rbp), %rbx         # 8-byte Reload
+	addq	$393216, %rbx           # imm = 0x60000
+	cmpq	$1472, %rax             # imm = 0x5C0
+	leaq	64(%rax), %rax
+	jl	.LBB2_5
+# BB#7:                                 # %polly.loop_exit11
+	xorl	%eax, %eax
+	addq	$56, %rsp
+	popq	%rbx
+	popq	%r12
+	popq	%r13
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp28:
+	.size	main, .Ltmp28-main
+	.cfi_endproc
+
+	.type	A,@object               # @A
+	.comm	A,9437184,16
+	.type	B,@object               # @B
+	.comm	B,9437184,16
+	.type	.L.str,@object          # @.str
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.L.str:
+	.asciz	 "%lf "
+	.size	.L.str, 5
+
+	.type	C,@object               # @C
+	.comm	C,9437184,16
+
+	.section	".note.GNU-stack","",@progbits
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged.exe b/final/www/experiments/matmul/matmul.polly.interchanged.exe
new file mode 100755
index 0000000..240c95a
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged.exe
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged.ll b/final/www/experiments/matmul/matmul.polly.interchanged.ll
new file mode 100644
index 0000000..52fbccc
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged.ll
Binary files differ
diff --git a/final/www/experiments/matmul/matmul.polly.interchanged.s b/final/www/experiments/matmul/matmul.polly.interchanged.s
new file mode 100644
index 0000000..a764da0
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.polly.interchanged.s
@@ -0,0 +1,286 @@
+	.file	"matmul.polly.interchanged.ll"
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI0_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	init_array
+	.align	16, 0x90
+	.type	init_array,@function
+init_array:                             # @init_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp2:
+	.cfi_def_cfa_offset 16
+.Ltmp3:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp4:
+	.cfi_def_cfa_register %rbp
+	xorl	%r8d, %r8d
+	vmovsd	.LCPI0_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB0_1:                                # %polly.loop_preheader3
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB0_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB0_2:                                # %polly.loop_header2
+                                        #   Parent Loop BB0_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%r8d, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%r8, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB0_2
+# BB#3:                                 # %polly.loop_exit4
+                                        #   in Loop: Header=BB0_1 Depth=1
+	incq	%r8
+	cmpq	$1536, %r8              # imm = 0x600
+	jne	.LBB0_1
+# BB#4:                                 # %polly.loop_exit
+	popq	%rbp
+	ret
+.Ltmp5:
+	.size	init_array, .Ltmp5-init_array
+	.cfi_endproc
+
+	.globl	print_array
+	.align	16, 0x90
+	.type	print_array,@function
+print_array:                            # @print_array
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp9:
+	.cfi_def_cfa_offset 16
+.Ltmp10:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp11:
+	.cfi_def_cfa_register %rbp
+	pushq	%r15
+	pushq	%r14
+	pushq	%r12
+	pushq	%rbx
+.Ltmp12:
+	.cfi_offset %rbx, -48
+.Ltmp13:
+	.cfi_offset %r12, -40
+.Ltmp14:
+	.cfi_offset %r14, -32
+.Ltmp15:
+	.cfi_offset %r15, -24
+	xorl	%r14d, %r14d
+	movl	$C, %r15d
+	.align	16, 0x90
+.LBB1_1:                                # %for.cond1.preheader
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB1_2 Depth 2
+	movq	stdout(%rip), %rax
+	movq	%r15, %r12
+	xorl	%ebx, %ebx
+	.align	16, 0x90
+.LBB1_2:                                # %for.body3
+                                        #   Parent Loop BB1_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	vmovss	(%r12), %xmm0
+	vcvtss2sd	%xmm0, %xmm0, %xmm0
+	movq	%rax, %rdi
+	movl	$.L.str, %esi
+	movb	$1, %al
+	callq	fprintf
+	movslq	%ebx, %rax
+	imulq	$1717986919, %rax, %rcx # imm = 0x66666667
+	movq	%rcx, %rdx
+	shrq	$63, %rdx
+	sarq	$37, %rcx
+	addl	%edx, %ecx
+	imull	$80, %ecx, %ecx
+	subl	%ecx, %eax
+	cmpl	$79, %eax
+	jne	.LBB1_4
+# BB#3:                                 # %if.then
+                                        #   in Loop: Header=BB1_2 Depth=2
+	movq	stdout(%rip), %rsi
+	movl	$10, %edi
+	callq	fputc
+.LBB1_4:                                # %for.inc
+                                        #   in Loop: Header=BB1_2 Depth=2
+	addq	$4, %r12
+	incq	%rbx
+	movq	stdout(%rip), %rax
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB1_2
+# BB#5:                                 # %for.end
+                                        #   in Loop: Header=BB1_1 Depth=1
+	movl	$10, %edi
+	movq	%rax, %rsi
+	callq	fputc
+	addq	$6144, %r15             # imm = 0x1800
+	incq	%r14
+	cmpq	$1536, %r14             # imm = 0x600
+	jne	.LBB1_1
+# BB#6:                                 # %for.end12
+	popq	%rbx
+	popq	%r12
+	popq	%r14
+	popq	%r15
+	popq	%rbp
+	ret
+.Ltmp16:
+	.size	print_array, .Ltmp16-print_array
+	.cfi_endproc
+
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align	8
+.LCPI2_0:
+	.quad	4602678819172646912     # double 0.5
+	.text
+	.globl	main
+	.align	16, 0x90
+	.type	main,@function
+main:                                   # @main
+	.cfi_startproc
+# BB#0:                                 # %entry
+	pushq	%rbp
+.Ltmp20:
+	.cfi_def_cfa_offset 16
+.Ltmp21:
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+.Ltmp22:
+	.cfi_def_cfa_register %rbp
+	pushq	%r14
+	pushq	%rbx
+.Ltmp23:
+	.cfi_offset %rbx, -32
+.Ltmp24:
+	.cfi_offset %r14, -24
+	xorl	%ebx, %ebx
+	vmovsd	.LCPI2_0(%rip), %xmm0
+	.align	16, 0x90
+.LBB2_1:                                # %polly.loop_preheader3.i
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_2 Depth 2
+	xorl	%ecx, %ecx
+	.align	16, 0x90
+.LBB2_2:                                # %polly.loop_header2.i
+                                        #   Parent Loop BB2_1 Depth=1
+                                        # =>  This Inner Loop Header: Depth=2
+	movl	%ecx, %edx
+	imull	%ebx, %edx
+	movl	%edx, %esi
+	sarl	$31, %esi
+	shrl	$22, %esi
+	addl	%edx, %esi
+	andl	$-1024, %esi            # imm = 0xFFFFFFFFFFFFFC00
+	negl	%esi
+	movq	%rbx, %rax
+	shlq	$11, %rax
+	leal	1(%rdx,%rsi), %edi
+	leaq	(%rax,%rax,2), %rsi
+	leaq	1(%rcx), %rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	vcvtsi2sdl	%edi, %xmm0, %xmm1
+	vmulsd	%xmm0, %xmm1, %xmm1
+	vcvtsd2ss	%xmm1, %xmm1, %xmm1
+	vmovss	%xmm1, A(%rsi,%rcx,4)
+	vmovss	%xmm1, B(%rsi,%rcx,4)
+	movq	%rdx, %rcx
+	jne	.LBB2_2
+# BB#3:                                 # %polly.loop_exit4.i
+                                        #   in Loop: Header=BB2_1 Depth=1
+	incq	%rbx
+	cmpq	$1536, %rbx             # imm = 0x600
+	jne	.LBB2_1
+# BB#4:                                 # %polly.loop_preheader3.preheader
+	movl	$C, %r14d
+	movl	$C, %edi
+	xorl	%esi, %esi
+	movl	$9437184, %edx          # imm = 0x900000
+	callq	memset
+	xorl	%eax, %eax
+	.align	16, 0x90
+.LBB2_5:                                # %polly.loop_preheader17
+                                        # =>This Loop Header: Depth=1
+                                        #     Child Loop BB2_10 Depth 2
+                                        #       Child Loop BB2_8 Depth 3
+	movl	$B, %ebx
+	xorl	%edx, %edx
+	.align	16, 0x90
+.LBB2_10:                               # %polly.loop_preheader24
+                                        #   Parent Loop BB2_5 Depth=1
+                                        # =>  This Loop Header: Depth=2
+                                        #       Child Loop BB2_8 Depth 3
+	leaq	(%rax,%rax,2), %rcx
+	shlq	$11, %rcx
+	vmovss	A(%rcx,%rdx,4), %xmm0
+	movl	$1536, %esi             # imm = 0x600
+	movq	%r14, %rdi
+	movq	%rbx, %rcx
+	.align	16, 0x90
+.LBB2_8:                                # %polly.loop_header23
+                                        #   Parent Loop BB2_5 Depth=1
+                                        #     Parent Loop BB2_10 Depth=2
+                                        # =>    This Inner Loop Header: Depth=3
+	vmulss	(%rcx), %xmm0, %xmm1
+	vaddss	(%rdi), %xmm1, %xmm1
+	vmovss	%xmm1, (%rdi)
+	addq	$4, %rdi
+	addq	$4, %rcx
+	decq	%rsi
+	jne	.LBB2_8
+# BB#9:                                 # %polly.loop_exit25
+                                        #   in Loop: Header=BB2_10 Depth=2
+	addq	$6144, %rbx             # imm = 0x1800
+	incq	%rdx
+	cmpq	$1536, %rdx             # imm = 0x600
+	jne	.LBB2_10
+# BB#6:                                 # %polly.loop_exit18
+                                        #   in Loop: Header=BB2_5 Depth=1
+	addq	$6144, %r14             # imm = 0x1800
+	incq	%rax
+	cmpq	$1536, %rax             # imm = 0x600
+	jne	.LBB2_5
+# BB#7:                                 # %polly.loop_exit11
+	xorl	%eax, %eax
+	popq	%rbx
+	popq	%r14
+	popq	%rbp
+	ret
+.Ltmp25:
+	.size	main, .Ltmp25-main
+	.cfi_endproc
+
+	.type	A,@object               # @A
+	.comm	A,9437184,16
+	.type	B,@object               # @B
+	.comm	B,9437184,16
+	.type	.L.str,@object          # @.str
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.L.str:
+	.asciz	 "%lf "
+	.size	.L.str, 5
+
+	.type	C,@object               # @C
+	.comm	C,9437184,16
+
+	.section	".note.GNU-stack","",@progbits
diff --git a/final/www/experiments/matmul/matmul.preopt.ll b/final/www/experiments/matmul/matmul.preopt.ll
new file mode 100644
index 0000000..3931716
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.preopt.ll
@@ -0,0 +1,186 @@
+; ModuleID = 'matmul.s'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+
+@A = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@B = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@stdout = external global %struct._IO_FILE*
+@.str = private unnamed_addr constant [5 x i8] c"%lf \00", align 1
+@C = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@.str1 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
+
+; Function Attrs: nounwind uwtable
+define void @init_array() #0 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc17, %entry
+  %0 = phi i64 [ %indvar.next2, %for.inc17 ], [ 0, %entry ]
+  %exitcond3 = icmp ne i64 %0, 1536
+  br i1 %exitcond3, label %for.body, label %for.end19
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body ]
+  %arrayidx6 = getelementptr [1536 x [1536 x float]]* @A, i64 0, i64 %0, i64 %indvar
+  %arrayidx16 = getelementptr [1536 x [1536 x float]]* @B, i64 0, i64 %0, i64 %indvar
+  %1 = mul i64 %0, %indvar
+  %mul = trunc i64 %1 to i32
+  %exitcond = icmp ne i64 %indvar, 1536
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %rem = srem i32 %mul, 1024
+  %add = add nsw i32 1, %rem
+  %conv = sitofp i32 %add to double
+  %div = fdiv double %conv, 2.000000e+00
+  %conv4 = fptrunc double %div to float
+  store float %conv4, float* %arrayidx6, align 4
+  %rem8 = srem i32 %mul, 1024
+  %add9 = add nsw i32 1, %rem8
+  %conv10 = sitofp i32 %add9 to double
+  %div11 = fdiv double %conv10, 2.000000e+00
+  %conv12 = fptrunc double %div11 to float
+  store float %conv12, float* %arrayidx16, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc17
+
+for.inc17:                                        ; preds = %for.end
+  %indvar.next2 = add i64 %0, 1
+  br label %for.cond
+
+for.end19:                                        ; preds = %for.cond
+  ret void
+}
+
+; Function Attrs: nounwind uwtable
+define void @print_array() #0 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %indvar1 = phi i64 [ %indvar.next2, %for.inc10 ], [ 0, %entry ]
+  %exitcond3 = icmp ne i64 %indvar1, 1536
+  br i1 %exitcond3, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body ]
+  %arrayidx5 = getelementptr [1536 x [1536 x float]]* @C, i64 0, i64 %indvar1, i64 %indvar
+  %j.0 = trunc i64 %indvar to i32
+  %exitcond = icmp ne i64 %indvar, 1536
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %0 = load %struct._IO_FILE** @stdout, align 8
+  %1 = load float* %arrayidx5, align 4
+  %conv = fpext float %1 to double
+  %call = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %0, i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0), double %conv)
+  %rem = srem i32 %j.0, 80
+  %cmp6 = icmp eq i32 %rem, 79
+  br i1 %cmp6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body3
+  %2 = load %struct._IO_FILE** @stdout, align 8
+  %call8 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %2, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body3
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  %3 = load %struct._IO_FILE** @stdout, align 8
+  %call9 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %3, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end
+  %indvar.next2 = add i64 %indvar1, 1
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
+
+declare i32 @fprintf(%struct._IO_FILE*, i8*, ...) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @main() #0 {
+entry:
+  call void @init_array()
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc28, %entry
+  %indvar3 = phi i64 [ %indvar.next4, %for.inc28 ], [ 0, %entry ]
+  %exitcond6 = icmp ne i64 %indvar3, 1536
+  br i1 %exitcond6, label %for.body, label %for.end30
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc25, %for.body
+  %indvar1 = phi i64 [ %indvar.next2, %for.inc25 ], [ 0, %for.body ]
+  %arrayidx5 = getelementptr [1536 x [1536 x float]]* @C, i64 0, i64 %indvar3, i64 %indvar1
+  %exitcond5 = icmp ne i64 %indvar1, 1536
+  br i1 %exitcond5, label %for.body3, label %for.end27
+
+for.body3:                                        ; preds = %for.cond1
+  store float 0.000000e+00, float* %arrayidx5, align 4
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc, %for.body3
+  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body3 ]
+  %arrayidx16 = getelementptr [1536 x [1536 x float]]* @A, i64 0, i64 %indvar3, i64 %indvar
+  %arrayidx20 = getelementptr [1536 x [1536 x float]]* @B, i64 0, i64 %indvar, i64 %indvar1
+  %exitcond = icmp ne i64 %indvar, 1536
+  br i1 %exitcond, label %for.body8, label %for.end
+
+for.body8:                                        ; preds = %for.cond6
+  %0 = load float* %arrayidx5, align 4
+  %1 = load float* %arrayidx16, align 4
+  %2 = load float* %arrayidx20, align 4
+  %mul = fmul float %1, %2
+  %add = fadd float %0, %mul
+  store float %add, float* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body8
+  %indvar.next = add i64 %indvar, 1
+  br label %for.cond6
+
+for.end:                                          ; preds = %for.cond6
+  br label %for.inc25
+
+for.inc25:                                        ; preds = %for.end
+  %indvar.next2 = add i64 %indvar1, 1
+  br label %for.cond1
+
+for.end27:                                        ; preds = %for.cond1
+  br label %for.inc28
+
+for.inc28:                                        ; preds = %for.end27
+  %indvar.next4 = add i64 %indvar3, 1
+  br label %for.cond
+
+for.end30:                                        ; preds = %for.cond
+  ret i32 0
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/final/www/experiments/matmul/matmul.s b/final/www/experiments/matmul/matmul.s
new file mode 100644
index 0000000..22ea57b
--- /dev/null
+++ b/final/www/experiments/matmul/matmul.s
@@ -0,0 +1,264 @@
+; ModuleID = 'matmul.c'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+
+@A = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@B = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@stdout = external global %struct._IO_FILE*
+@.str = private unnamed_addr constant [5 x i8] c"%lf \00", align 1
+@C = common global [1536 x [1536 x float]] zeroinitializer, align 16
+@.str1 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
+
+; Function Attrs: nounwind uwtable
+define void @init_array() #0 {
+entry:
+  %i = alloca i32, align 4
+  %j = alloca i32, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc17, %entry
+  %0 = load i32* %i, align 4
+  %cmp = icmp slt i32 %0, 1536
+  br i1 %cmp, label %for.body, label %for.end19
+
+for.body:                                         ; preds = %for.cond
+  store i32 0, i32* %j, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %1 = load i32* %j, align 4
+  %cmp2 = icmp slt i32 %1, 1536
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %2 = load i32* %i, align 4
+  %3 = load i32* %j, align 4
+  %mul = mul nsw i32 %2, %3
+  %rem = srem i32 %mul, 1024
+  %add = add nsw i32 1, %rem
+  %conv = sitofp i32 %add to double
+  %div = fdiv double %conv, 2.000000e+00
+  %conv4 = fptrunc double %div to float
+  %4 = load i32* %j, align 4
+  %idxprom = sext i32 %4 to i64
+  %5 = load i32* %i, align 4
+  %idxprom5 = sext i32 %5 to i64
+  %arrayidx = getelementptr inbounds [1536 x [1536 x float]]* @A, i32 0, i64 %idxprom5
+  %arrayidx6 = getelementptr inbounds [1536 x float]* %arrayidx, i32 0, i64 %idxprom
+  store float %conv4, float* %arrayidx6, align 4
+  %6 = load i32* %i, align 4
+  %7 = load i32* %j, align 4
+  %mul7 = mul nsw i32 %6, %7
+  %rem8 = srem i32 %mul7, 1024
+  %add9 = add nsw i32 1, %rem8
+  %conv10 = sitofp i32 %add9 to double
+  %div11 = fdiv double %conv10, 2.000000e+00
+  %conv12 = fptrunc double %div11 to float
+  %8 = load i32* %j, align 4
+  %idxprom13 = sext i32 %8 to i64
+  %9 = load i32* %i, align 4
+  %idxprom14 = sext i32 %9 to i64
+  %arrayidx15 = getelementptr inbounds [1536 x [1536 x float]]* @B, i32 0, i64 %idxprom14
+  %arrayidx16 = getelementptr inbounds [1536 x float]* %arrayidx15, i32 0, i64 %idxprom13
+  store float %conv12, float* %arrayidx16, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %10 = load i32* %j, align 4
+  %inc = add nsw i32 %10, 1
+  store i32 %inc, i32* %j, align 4
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc17
+
+for.inc17:                                        ; preds = %for.end
+  %11 = load i32* %i, align 4
+  %inc18 = add nsw i32 %11, 1
+  store i32 %inc18, i32* %i, align 4
+  br label %for.cond
+
+for.end19:                                        ; preds = %for.cond
+  ret void
+}
+
+; Function Attrs: nounwind uwtable
+define void @print_array() #0 {
+entry:
+  %i = alloca i32, align 4
+  %j = alloca i32, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc10, %entry
+  %0 = load i32* %i, align 4
+  %cmp = icmp slt i32 %0, 1536
+  br i1 %cmp, label %for.body, label %for.end12
+
+for.body:                                         ; preds = %for.cond
+  store i32 0, i32* %j, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %1 = load i32* %j, align 4
+  %cmp2 = icmp slt i32 %1, 1536
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %2 = load %struct._IO_FILE** @stdout, align 8
+  %3 = load i32* %j, align 4
+  %idxprom = sext i32 %3 to i64
+  %4 = load i32* %i, align 4
+  %idxprom4 = sext i32 %4 to i64
+  %arrayidx = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom4
+  %arrayidx5 = getelementptr inbounds [1536 x float]* %arrayidx, i32 0, i64 %idxprom
+  %5 = load float* %arrayidx5, align 4
+  %conv = fpext float %5 to double
+  %call = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %2, i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0), double %conv)
+  %6 = load i32* %j, align 4
+  %rem = srem i32 %6, 80
+  %cmp6 = icmp eq i32 %rem, 79
+  br i1 %cmp6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body3
+  %7 = load %struct._IO_FILE** @stdout, align 8
+  %call8 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %7, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body3
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %8 = load i32* %j, align 4
+  %inc = add nsw i32 %8, 1
+  store i32 %inc, i32* %j, align 4
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  %9 = load %struct._IO_FILE** @stdout, align 8
+  %call9 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %9, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.end
+  %10 = load i32* %i, align 4
+  %inc11 = add nsw i32 %10, 1
+  store i32 %inc11, i32* %i, align 4
+  br label %for.cond
+
+for.end12:                                        ; preds = %for.cond
+  ret void
+}
+
+declare i32 @fprintf(%struct._IO_FILE*, i8*, ...) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @main() #0 {
+entry:
+  %retval = alloca i32, align 4
+  %i = alloca i32, align 4
+  %j = alloca i32, align 4
+  %k = alloca i32, align 4
+  %t_start = alloca double, align 8
+  %t_end = alloca double, align 8
+  store i32 0, i32* %retval
+  call void @init_array()
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc28, %entry
+  %0 = load i32* %i, align 4
+  %cmp = icmp slt i32 %0, 1536
+  br i1 %cmp, label %for.body, label %for.end30
+
+for.body:                                         ; preds = %for.cond
+  store i32 0, i32* %j, align 4
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc25, %for.body
+  %1 = load i32* %j, align 4
+  %cmp2 = icmp slt i32 %1, 1536
+  br i1 %cmp2, label %for.body3, label %for.end27
+
+for.body3:                                        ; preds = %for.cond1
+  %2 = load i32* %j, align 4
+  %idxprom = sext i32 %2 to i64
+  %3 = load i32* %i, align 4
+  %idxprom4 = sext i32 %3 to i64
+  %arrayidx = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom4
+  %arrayidx5 = getelementptr inbounds [1536 x float]* %arrayidx, i32 0, i64 %idxprom
+  store float 0.000000e+00, float* %arrayidx5, align 4
+  store i32 0, i32* %k, align 4
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc, %for.body3
+  %4 = load i32* %k, align 4
+  %cmp7 = icmp slt i32 %4, 1536
+  br i1 %cmp7, label %for.body8, label %for.end
+
+for.body8:                                        ; preds = %for.cond6
+  %5 = load i32* %j, align 4
+  %idxprom9 = sext i32 %5 to i64
+  %6 = load i32* %i, align 4
+  %idxprom10 = sext i32 %6 to i64
+  %arrayidx11 = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom10
+  %arrayidx12 = getelementptr inbounds [1536 x float]* %arrayidx11, i32 0, i64 %idxprom9
+  %7 = load float* %arrayidx12, align 4
+  %8 = load i32* %k, align 4
+  %idxprom13 = sext i32 %8 to i64
+  %9 = load i32* %i, align 4
+  %idxprom14 = sext i32 %9 to i64
+  %arrayidx15 = getelementptr inbounds [1536 x [1536 x float]]* @A, i32 0, i64 %idxprom14
+  %arrayidx16 = getelementptr inbounds [1536 x float]* %arrayidx15, i32 0, i64 %idxprom13
+  %10 = load float* %arrayidx16, align 4
+  %11 = load i32* %j, align 4
+  %idxprom17 = sext i32 %11 to i64
+  %12 = load i32* %k, align 4
+  %idxprom18 = sext i32 %12 to i64
+  %arrayidx19 = getelementptr inbounds [1536 x [1536 x float]]* @B, i32 0, i64 %idxprom18
+  %arrayidx20 = getelementptr inbounds [1536 x float]* %arrayidx19, i32 0, i64 %idxprom17
+  %13 = load float* %arrayidx20, align 4
+  %mul = fmul float %10, %13
+  %add = fadd float %7, %mul
+  %14 = load i32* %j, align 4
+  %idxprom21 = sext i32 %14 to i64
+  %15 = load i32* %i, align 4
+  %idxprom22 = sext i32 %15 to i64
+  %arrayidx23 = getelementptr inbounds [1536 x [1536 x float]]* @C, i32 0, i64 %idxprom22
+  %arrayidx24 = getelementptr inbounds [1536 x float]* %arrayidx23, i32 0, i64 %idxprom21
+  store float %add, float* %arrayidx24, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body8
+  %16 = load i32* %k, align 4
+  %inc = add nsw i32 %16, 1
+  store i32 %inc, i32* %k, align 4
+  br label %for.cond6
+
+for.end:                                          ; preds = %for.cond6
+  br label %for.inc25
+
+for.inc25:                                        ; preds = %for.end
+  %17 = load i32* %j, align 4
+  %inc26 = add nsw i32 %17, 1
+  store i32 %inc26, i32* %j, align 4
+  br label %for.cond1
+
+for.end27:                                        ; preds = %for.cond1
+  br label %for.inc28
+
+for.inc28:                                        ; preds = %for.end27
+  %18 = load i32* %i, align 4
+  %inc29 = add nsw i32 %18, 1
+  store i32 %inc29, i32* %i, align 4
+  br label %for.cond
+
+for.end30:                                        ; preds = %for.cond
+  ret i32 0
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/final/www/experiments/matmul/runall.sh b/final/www/experiments/matmul/runall.sh
new file mode 100755
index 0000000..77ef6b4
--- /dev/null
+++ b/final/www/experiments/matmul/runall.sh
@@ -0,0 +1,94 @@
+#!/bin/sh -a
+
+echo "--> 1. Create LLVM-IR from C"
+clang -S -emit-llvm matmul.c -o matmul.s
+
+echo "--> 2. Load Polly automatically when calling the 'opt' tool"
+export PATH_TO_POLLY_LIB="~/polly/build/lib/"
+alias opt="opt -load ${PATH_TO_POLLY_LIB}/LLVMPolly.so"
+
+echo "--> 3. Prepare the LLVM-IR for Polly"
+opt -S -polly-canonicalize matmul.s > matmul.preopt.ll
+
+echo "--> 4. Show the SCoPs detected by Polly"
+opt -basicaa -polly-ast -analyze -q matmul.preopt.ll
+
+echo "--> 5.1 Highlight the detected SCoPs in the CFGs of the program"
+# We only create .dot files, as directly -view-scops directly calls graphviz
+# which would require user interaction to continue the script.
+# opt -basicaa -view-scops -disable-output matmul.preopt.ll
+opt -basicaa -dot-scops -disable-output matmul.preopt.ll
+
+echo "--> 5.2 Highlight the detected SCoPs in the CFGs of the program (print \
+no instructions)"
+# We only create .dot files, as directly -view-scops-only directly calls
+# graphviz which would require user interaction to continue the script.
+# opt -basicaa -view-scops-only -disable-output matmul.preopt.ll
+opt -basicaa -dot-scops-only -disable-output matmul.preopt.ll
+
+echo "--> 5.3 Create .png files from the .dot files"
+for i in `ls *.dot`; do dot -Tpng $i > $i.png; done
+
+echo "--> 6. View the polyhedral representation of the SCoPs"
+opt -basicaa -polly-scops -analyze matmul.preopt.ll
+
+echo "--> 7. Show the dependences for the SCoPs"
+opt -basicaa -polly-dependences -analyze matmul.preopt.ll
+
+echo "--> 8. Export jscop files"
+opt -basicaa -polly-export-jscop matmul.preopt.ll
+
+echo "--> 9. Import the updated jscop files and print the new SCoPs. (optional)"
+opt -basicaa -polly-import-jscop -polly-ast -analyze matmul.preopt.ll
+opt -basicaa -polly-import-jscop -polly-ast -analyze matmul.preopt.ll \
+    -polly-import-jscop-postfix=interchanged
+opt -basicaa -polly-import-jscop -polly-ast -analyze matmul.preopt.ll \
+    -polly-import-jscop-postfix=interchanged+tiled
+opt -basicaa -polly-import-jscop -polly-ast -analyze matmul.preopt.ll \
+    -polly-import-jscop-postfix=interchanged+tiled+vector
+
+echo "--> 10. Codegenerate the SCoPs"
+opt -basicaa -polly-import-jscop -polly-import-jscop-postfix=interchanged \
+    -polly-codegen \
+    matmul.preopt.ll | opt -O3 > matmul.polly.interchanged.ll
+opt -basicaa -polly-import-jscop \
+    -polly-import-jscop-postfix=interchanged+tiled -polly-codegen \
+    matmul.preopt.ll | opt -O3 > matmul.polly.interchanged+tiled.ll
+opt -basicaa -polly-import-jscop \
+    -polly-import-jscop-postfix=interchanged+tiled+vector -polly-codegen \
+    matmul.preopt.ll -polly-vectorizer=polly\
+    | opt -O3 > matmul.polly.interchanged+tiled+vector.ll
+opt -basicaa -polly-import-jscop \
+    -polly-import-jscop-postfix=interchanged+tiled+vector -polly-codegen \
+    matmul.preopt.ll -polly-vectorizer=polly -enable-polly-openmp\
+    | opt -O3 > matmul.polly.interchanged+tiled+vector+openmp.ll
+opt matmul.preopt.ll | opt -O3 > matmul.normalopt.ll
+
+echo "--> 11. Create the executables"
+llc matmul.polly.interchanged.ll -o matmul.polly.interchanged.s && gcc matmul.polly.interchanged.s \
+    -o matmul.polly.interchanged.exe
+llc matmul.polly.interchanged+tiled.ll -o matmul.polly.interchanged+tiled.s && gcc matmul.polly.interchanged+tiled.s \
+    -o matmul.polly.interchanged+tiled.exe
+llc matmul.polly.interchanged+tiled+vector.ll \
+    -o matmul.polly.interchanged+tiled+vector.s \
+    && gcc matmul.polly.interchanged+tiled+vector.s \
+    -o matmul.polly.interchanged+tiled+vector.exe
+llc matmul.polly.interchanged+tiled+vector+openmp.ll \
+    -o matmul.polly.interchanged+tiled+vector+openmp.s \
+    && gcc -lgomp matmul.polly.interchanged+tiled+vector+openmp.s \
+    -o matmul.polly.interchanged+tiled+vector+openmp.exe
+llc matmul.normalopt.ll -o matmul.normalopt.s && gcc matmul.normalopt.s \
+    -o matmul.normalopt.exe
+
+echo "--> 12. Compare the runtime of the executables"
+
+echo "time ./matmul.normalopt.exe"
+time -f "%E real, %U user, %S sys" ./matmul.normalopt.exe
+echo "time ./matmul.polly.interchanged.exe"
+time -f "%E real, %U user, %S sys" ./matmul.polly.interchanged.exe
+echo "time ./matmul.polly.interchanged+tiled.exe"
+time -f "%E real, %U user, %S sys" ./matmul.polly.interchanged+tiled.exe
+echo "time ./matmul.polly.interchanged+tiled+vector.exe"
+time -f "%E real, %U user, %S sys" ./matmul.polly.interchanged+tiled+vector.exe
+echo "time ./matmul.polly.interchanged+tiled+vector+openmp.exe"
+time -f "%E real, %U user, %S sys" ./matmul.polly.interchanged+tiled+vector+openmp.exe
diff --git a/final/www/experiments/matmul/scops.init_array.dot b/final/www/experiments/matmul/scops.init_array.dot
new file mode 100644
index 0000000..10a0add
--- /dev/null
+++ b/final/www/experiments/matmul/scops.init_array.dot
@@ -0,0 +1,47 @@
+digraph "Scop Graph for 'init_array' function" {
+	label="Scop Graph for 'init_array' function";
+
+	Node0x17d4370 [shape=record,label="{entry:\l  br label %for.cond\l}"];
+	Node0x17d4370 -> Node0x17da5d0;
+	Node0x17da5d0 [shape=record,label="{for.cond:                                         \l  %0 = phi i64 [ %indvar.next2, %for.inc17 ], [ 0, %entry ]\l  %exitcond3 = icmp ne i64 %0, 1536\l  br i1 %exitcond3, label %for.body, label %for.end19\l}"];
+	Node0x17da5d0 -> Node0x17da5f0;
+	Node0x17da5d0 -> Node0x17da650;
+	Node0x17da5f0 [shape=record,label="{for.body:                                         \l  br label %for.cond1\l}"];
+	Node0x17da5f0 -> Node0x17da900;
+	Node0x17da900 [shape=record,label="{for.cond1:                                        \l  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body ]\l  %arrayidx6 = getelementptr [1536 x [1536 x float]]* @A, i64 0, i64 %0, i64 %indvar\l  %arrayidx16 = getelementptr [1536 x [1536 x float]]* @B, i64 0, i64 %0, i64 %indvar\l  %1 = mul i64 %0, %indvar\l  %mul = trunc i64 %1 to i32\l  %exitcond = icmp ne i64 %indvar, 1536\l  br i1 %exitcond, label %for.body3, label %for.end\l}"];
+	Node0x17da900 -> Node0x17da670;
+	Node0x17da900 -> Node0x17da9a0;
+	Node0x17da670 [shape=record,label="{for.body3:                                        \l  %rem = srem i32 %mul, 1024\l  %add = add nsw i32 1, %rem\l  %conv = sitofp i32 %add to double\l  %div = fdiv double %conv, 2.000000e+00\l  %conv4 = fptrunc double %div to float\l  store float %conv4, float* %arrayidx6, align 4\l  %rem8 = srem i32 %mul, 1024\l  %add9 = add nsw i32 1, %rem8\l  %conv10 = sitofp i32 %add9 to double\l  %div11 = fdiv double %conv10, 2.000000e+00\l  %conv12 = fptrunc double %div11 to float\l  store float %conv12, float* %arrayidx16, align 4\l  br label %for.inc\l}"];
+	Node0x17da670 -> Node0x17da8e0;
+	Node0x17da8e0 [shape=record,label="{for.inc:                                          \l  %indvar.next = add i64 %indvar, 1\l  br label %for.cond1\l}"];
+	Node0x17da8e0 -> Node0x17da900[constraint=false];
+	Node0x17da9a0 [shape=record,label="{for.end:                                          \l  br label %for.inc17\l}"];
+	Node0x17da9a0 -> Node0x17d9e70;
+	Node0x17d9e70 [shape=record,label="{for.inc17:                                        \l  %indvar.next2 = add i64 %0, 1\l  br label %for.cond\l}"];
+	Node0x17d9e70 -> Node0x17da5d0[constraint=false];
+	Node0x17da650 [shape=record,label="{for.end19:                                        \l  ret void\l}"];
+	colorscheme = "paired12"
+        subgraph cluster_0x17d3a30 {
+          label = "";
+          style = solid;
+          color = 1
+          subgraph cluster_0x17d4ec0 {
+            label = "";
+            style = filled;
+            color = 3            subgraph cluster_0x17d4180 {
+              label = "";
+              style = solid;
+              color = 5
+              Node0x17da900;
+              Node0x17da670;
+              Node0x17da8e0;
+            }
+            Node0x17da5d0;
+            Node0x17da5f0;
+            Node0x17da9a0;
+            Node0x17d9e70;
+          }
+          Node0x17d4370;
+          Node0x17da650;
+        }
+}
diff --git a/final/www/experiments/matmul/scops.init_array.dot.png b/final/www/experiments/matmul/scops.init_array.dot.png
new file mode 100644
index 0000000..48a9f38
--- /dev/null
+++ b/final/www/experiments/matmul/scops.init_array.dot.png
Binary files differ
diff --git a/final/www/experiments/matmul/scops.main.dot b/final/www/experiments/matmul/scops.main.dot
new file mode 100644
index 0000000..2a1fc50
--- /dev/null
+++ b/final/www/experiments/matmul/scops.main.dot
@@ -0,0 +1,65 @@
+digraph "Scop Graph for 'main' function" {
+	label="Scop Graph for 'main' function";
+
+	Node0x17d21a0 [shape=record,label="{entry:\l  call void @init_array()\l  br label %for.cond\l}"];
+	Node0x17d21a0 -> Node0x17d2020;
+	Node0x17d2020 [shape=record,label="{for.cond:                                         \l  %indvar3 = phi i64 [ %indvar.next4, %for.inc28 ], [ 0, %entry ]\l  %exitcond6 = icmp ne i64 %indvar3, 1536\l  br i1 %exitcond6, label %for.body, label %for.end30\l}"];
+	Node0x17d2020 -> Node0x17d3950;
+	Node0x17d2020 -> Node0x17da500;
+	Node0x17d3950 [shape=record,label="{for.body:                                         \l  br label %for.cond1\l}"];
+	Node0x17d3950 -> Node0x17da760;
+	Node0x17da760 [shape=record,label="{for.cond1:                                        \l  %indvar1 = phi i64 [ %indvar.next2, %for.inc25 ], [ 0, %for.body ]\l  %arrayidx5 = getelementptr [1536 x [1536 x float]]* @C, i64 0, i64 %indvar3, i64 %indvar1\l  %exitcond5 = icmp ne i64 %indvar1, 1536\l  br i1 %exitcond5, label %for.body3, label %for.end27\l}"];
+	Node0x17da760 -> Node0x17db1e0;
+	Node0x17da760 -> Node0x17db250;
+	Node0x17db1e0 [shape=record,label="{for.body3:                                        \l  store float 0.000000e+00, float* %arrayidx5, align 4\l  br label %for.cond6\l}"];
+	Node0x17db1e0 -> Node0x17da740;
+	Node0x17da740 [shape=record,label="{for.cond6:                                        \l  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body3 ]\l  %arrayidx16 = getelementptr [1536 x [1536 x float]]* @A, i64 0, i64 %indvar3, i64 %indvar\l  %arrayidx20 = getelementptr [1536 x [1536 x float]]* @B, i64 0, i64 %indvar, i64 %indvar1\l  %exitcond = icmp ne i64 %indvar, 1536\l  br i1 %exitcond, label %for.body8, label %for.end\l}"];
+	Node0x17da740 -> Node0x17da5a0;
+	Node0x17da740 -> Node0x17da800;
+	Node0x17da5a0 [shape=record,label="{for.body8:                                        \l  %0 = load float* %arrayidx5, align 4\l  %1 = load float* %arrayidx16, align 4\l  %2 = load float* %arrayidx20, align 4\l  %mul = fmul float %1, %2\l  %add = fadd float %0, %mul\l  store float %add, float* %arrayidx5, align 4\l  br label %for.inc\l}"];
+	Node0x17da5a0 -> Node0x17da5c0;
+	Node0x17da5c0 [shape=record,label="{for.inc:                                          \l  %indvar.next = add i64 %indvar, 1\l  br label %for.cond6\l}"];
+	Node0x17da5c0 -> Node0x17da740[constraint=false];
+	Node0x17da800 [shape=record,label="{for.end:                                          \l  br label %for.inc25\l}"];
+	Node0x17da800 -> Node0x17dae20;
+	Node0x17dae20 [shape=record,label="{for.inc25:                                        \l  %indvar.next2 = add i64 %indvar1, 1\l  br label %for.cond1\l}"];
+	Node0x17dae20 -> Node0x17da760[constraint=false];
+	Node0x17db250 [shape=record,label="{for.end27:                                        \l  br label %for.inc28\l}"];
+	Node0x17db250 -> Node0x17dae80;
+	Node0x17dae80 [shape=record,label="{for.inc28:                                        \l  %indvar.next4 = add i64 %indvar3, 1\l  br label %for.cond\l}"];
+	Node0x17dae80 -> Node0x17d2020[constraint=false];
+	Node0x17da500 [shape=record,label="{for.end30:                                        \l  ret i32 0\l}"];
+	colorscheme = "paired12"
+        subgraph cluster_0x17d3f30 {
+          label = "";
+          style = solid;
+          color = 1
+          subgraph cluster_0x17d38d0 {
+            label = "";
+            style = filled;
+            color = 3            subgraph cluster_0x17d3850 {
+              label = "";
+              style = solid;
+              color = 5
+              subgraph cluster_0x17d37d0 {
+                label = "";
+                style = solid;
+                color = 7
+                Node0x17da740;
+                Node0x17da5a0;
+                Node0x17da5c0;
+              }
+              Node0x17da760;
+              Node0x17db1e0;
+              Node0x17da800;
+              Node0x17dae20;
+            }
+            Node0x17d2020;
+            Node0x17d3950;
+            Node0x17db250;
+            Node0x17dae80;
+          }
+          Node0x17d21a0;
+          Node0x17da500;
+        }
+}
diff --git a/final/www/experiments/matmul/scops.main.dot.png b/final/www/experiments/matmul/scops.main.dot.png
new file mode 100644
index 0000000..4e73701
--- /dev/null
+++ b/final/www/experiments/matmul/scops.main.dot.png
Binary files differ
diff --git a/final/www/experiments/matmul/scops.print_array.dot b/final/www/experiments/matmul/scops.print_array.dot
new file mode 100644
index 0000000..59f02e7
--- /dev/null
+++ b/final/www/experiments/matmul/scops.print_array.dot
@@ -0,0 +1,60 @@
+digraph "Scop Graph for 'print_array' function" {
+	label="Scop Graph for 'print_array' function";
+
+	Node0x17d2200 [shape=record,label="{entry:\l  br label %for.cond\l}"];
+	Node0x17d2200 -> Node0x17d4f20;
+	Node0x17d4f20 [shape=record,label="{for.cond:                                         \l  %indvar1 = phi i64 [ %indvar.next2, %for.inc10 ], [ 0, %entry ]\l  %exitcond3 = icmp ne i64 %indvar1, 1536\l  br i1 %exitcond3, label %for.body, label %for.end12\l}"];
+	Node0x17d4f20 -> Node0x17d3680;
+	Node0x17d4f20 -> Node0x17d9fc0;
+	Node0x17d3680 [shape=record,label="{for.body:                                         \l  br label %for.cond1\l}"];
+	Node0x17d3680 -> Node0x17da220;
+	Node0x17da220 [shape=record,label="{for.cond1:                                        \l  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %for.body ]\l  %arrayidx5 = getelementptr [1536 x [1536 x float]]* @C, i64 0, i64 %indvar1, i64 %indvar\l  %j.0 = trunc i64 %indvar to i32\l  %exitcond = icmp ne i64 %indvar, 1536\l  br i1 %exitcond, label %for.body3, label %for.end\l}"];
+	Node0x17da220 -> Node0x17d9ea0;
+	Node0x17da220 -> Node0x17da0f0;
+	Node0x17d9ea0 [shape=record,label="{for.body3:                                        \l  %0 = load %struct._IO_FILE** @stdout, align 8\l  %1 = load float* %arrayidx5, align 4\l  %conv = fpext float %1 to double\l  %call = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %0, i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0), double %conv)\l  %rem = srem i32 %j.0, 80\l  %cmp6 = icmp eq i32 %rem, 79\l  br i1 %cmp6, label %if.then, label %if.end\l}"];
+	Node0x17d9ea0 -> Node0x17d9ec0;
+	Node0x17d9ea0 -> Node0x17da060;
+	Node0x17d9ec0 [shape=record,label="{if.then:                                          \l  %2 = load %struct._IO_FILE** @stdout, align 8\l  %call8 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %2, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))\l  br label %if.end\l}"];
+	Node0x17d9ec0 -> Node0x17da060;
+	Node0x17da060 [shape=record,label="{if.end:                                           \l  br label %for.inc\l}"];
+	Node0x17da060 -> Node0x17da200;
+	Node0x17da200 [shape=record,label="{for.inc:                                          \l  %indvar.next = add i64 %indvar, 1\l  br label %for.cond1\l}"];
+	Node0x17da200 -> Node0x17da220[constraint=false];
+	Node0x17da0f0 [shape=record,label="{for.end:                                          \l  %3 = load %struct._IO_FILE** @stdout, align 8\l  %call9 = call i32 (%struct._IO_FILE*, i8*, ...)* @fprintf(%struct._IO_FILE* %3, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0))\l  br label %for.inc10\l}"];
+	Node0x17da0f0 -> Node0x17da080;
+	Node0x17da080 [shape=record,label="{for.inc10:                                        \l  %indvar.next2 = add i64 %indvar1, 1\l  br label %for.cond\l}"];
+	Node0x17da080 -> Node0x17d4f20[constraint=false];
+	Node0x17d9fc0 [shape=record,label="{for.end12:                                        \l  ret void\l}"];
+	colorscheme = "paired12"
+        subgraph cluster_0x17d38f0 {
+          label = "";
+          style = solid;
+          color = 1
+          subgraph cluster_0x17d4030 {
+            label = "Non affine branch in BB 'for.body3' with LHS: %rem and RHS: 79";
+            style = solid;
+            color = 6
+            subgraph cluster_0x17d3fb0 {
+              label = "Non affine branch in BB 'for.body3' with LHS: %rem and RHS: 79";
+              style = solid;
+              color = 5
+              subgraph cluster_0x17d3f30 {
+                label = "Non affine branch in BB 'for.body3' with LHS: %rem and RHS: 79";
+                style = solid;
+                color = 7
+                Node0x17d9ea0;
+                Node0x17d9ec0;
+              }
+              Node0x17da220;
+              Node0x17da060;
+              Node0x17da200;
+            }
+            Node0x17d4f20;
+            Node0x17d3680;
+            Node0x17da0f0;
+            Node0x17da080;
+          }
+          Node0x17d2200;
+          Node0x17d9fc0;
+        }
+}
diff --git a/final/www/experiments/matmul/scops.print_array.dot.png b/final/www/experiments/matmul/scops.print_array.dot.png
new file mode 100644
index 0000000..e3b973b
--- /dev/null
+++ b/final/www/experiments/matmul/scops.print_array.dot.png
Binary files differ
diff --git a/final/www/experiments/matmul/scopsonly.init_array.dot b/final/www/experiments/matmul/scopsonly.init_array.dot
new file mode 100644
index 0000000..4685c5b
--- /dev/null
+++ b/final/www/experiments/matmul/scopsonly.init_array.dot
@@ -0,0 +1,47 @@
+digraph "Scop Graph for 'init_array' function" {
+	label="Scop Graph for 'init_array' function";
+
+	Node0x17d4370 [shape=record,label="{entry}"];
+	Node0x17d4370 -> Node0x17d9de0;
+	Node0x17d9de0 [shape=record,label="{for.cond}"];
+	Node0x17d9de0 -> Node0x17d9e40;
+	Node0x17d9de0 -> Node0x17d9ea0;
+	Node0x17d9e40 [shape=record,label="{for.body}"];
+	Node0x17d9e40 -> Node0x17d9f90;
+	Node0x17d9f90 [shape=record,label="{for.cond1}"];
+	Node0x17d9f90 -> Node0x17d9ff0;
+	Node0x17d9f90 -> Node0x17da050;
+	Node0x17d9ff0 [shape=record,label="{for.body3}"];
+	Node0x17d9ff0 -> Node0x17d9f00;
+	Node0x17d9f00 [shape=record,label="{for.inc}"];
+	Node0x17d9f00 -> Node0x17d9f90[constraint=false];
+	Node0x17da050 [shape=record,label="{for.end}"];
+	Node0x17da050 -> Node0x17da200;
+	Node0x17da200 [shape=record,label="{for.inc17}"];
+	Node0x17da200 -> Node0x17d9de0[constraint=false];
+	Node0x17d9ea0 [shape=record,label="{for.end19}"];
+	colorscheme = "paired12"
+        subgraph cluster_0x17d3a30 {
+          label = "";
+          style = solid;
+          color = 1
+          subgraph cluster_0x17d4ec0 {
+            label = "";
+            style = filled;
+            color = 3            subgraph cluster_0x17d4180 {
+              label = "";
+              style = solid;
+              color = 5
+              Node0x17d9f90;
+              Node0x17d9ff0;
+              Node0x17d9f00;
+            }
+            Node0x17d9de0;
+            Node0x17d9e40;
+            Node0x17da050;
+            Node0x17da200;
+          }
+          Node0x17d4370;
+          Node0x17d9ea0;
+        }
+}
diff --git a/final/www/experiments/matmul/scopsonly.init_array.dot.png b/final/www/experiments/matmul/scopsonly.init_array.dot.png
new file mode 100644
index 0000000..f101d4d
--- /dev/null
+++ b/final/www/experiments/matmul/scopsonly.init_array.dot.png
Binary files differ
diff --git a/final/www/experiments/matmul/scopsonly.main.dot b/final/www/experiments/matmul/scopsonly.main.dot
new file mode 100644
index 0000000..3b3f328
--- /dev/null
+++ b/final/www/experiments/matmul/scopsonly.main.dot
@@ -0,0 +1,65 @@
+digraph "Scop Graph for 'main' function" {
+	label="Scop Graph for 'main' function";
+
+	Node0x17d3950 [shape=record,label="{entry}"];
+	Node0x17d3950 -> Node0x17d21a0;
+	Node0x17d21a0 [shape=record,label="{for.cond}"];
+	Node0x17d21a0 -> Node0x17db9a0;
+	Node0x17d21a0 -> Node0x17da4f0;
+	Node0x17db9a0 [shape=record,label="{for.body}"];
+	Node0x17db9a0 -> Node0x17da5e0;
+	Node0x17da5e0 [shape=record,label="{for.cond1}"];
+	Node0x17da5e0 -> Node0x17da640;
+	Node0x17da5e0 -> Node0x17da6a0;
+	Node0x17da640 [shape=record,label="{for.body3}"];
+	Node0x17da640 -> Node0x17da550;
+	Node0x17da550 [shape=record,label="{for.cond6}"];
+	Node0x17da550 -> Node0x17da5b0;
+	Node0x17da550 -> Node0x17da850;
+	Node0x17da5b0 [shape=record,label="{for.body8}"];
+	Node0x17da5b0 -> Node0x17da8b0;
+	Node0x17da8b0 [shape=record,label="{for.inc}"];
+	Node0x17da8b0 -> Node0x17da550[constraint=false];
+	Node0x17da850 [shape=record,label="{for.end}"];
+	Node0x17da850 -> Node0x17db930;
+	Node0x17db930 [shape=record,label="{for.inc25}"];
+	Node0x17db930 -> Node0x17da5e0[constraint=false];
+	Node0x17da6a0 [shape=record,label="{for.end27}"];
+	Node0x17da6a0 -> Node0x17dada0;
+	Node0x17dada0 [shape=record,label="{for.inc28}"];
+	Node0x17dada0 -> Node0x17d21a0[constraint=false];
+	Node0x17da4f0 [shape=record,label="{for.end30}"];
+	colorscheme = "paired12"
+        subgraph cluster_0x17d3f30 {
+          label = "";
+          style = solid;
+          color = 1
+          subgraph cluster_0x17d38d0 {
+            label = "";
+            style = filled;
+            color = 3            subgraph cluster_0x17d3850 {
+              label = "";
+              style = solid;
+              color = 5
+              subgraph cluster_0x17d37d0 {
+                label = "";
+                style = solid;
+                color = 7
+                Node0x17da550;
+                Node0x17da5b0;
+                Node0x17da8b0;
+              }
+              Node0x17da5e0;
+              Node0x17da640;
+              Node0x17da850;
+              Node0x17db930;
+            }
+            Node0x17d21a0;
+            Node0x17db9a0;
+            Node0x17da6a0;
+            Node0x17dada0;
+          }
+          Node0x17d3950;
+          Node0x17da4f0;
+        }
+}
diff --git a/final/www/experiments/matmul/scopsonly.main.dot.png b/final/www/experiments/matmul/scopsonly.main.dot.png
new file mode 100644
index 0000000..3263424
--- /dev/null
+++ b/final/www/experiments/matmul/scopsonly.main.dot.png
Binary files differ
diff --git a/final/www/experiments/matmul/scopsonly.print_array.dot b/final/www/experiments/matmul/scopsonly.print_array.dot
new file mode 100644
index 0000000..c900d0f
--- /dev/null
+++ b/final/www/experiments/matmul/scopsonly.print_array.dot
@@ -0,0 +1,60 @@
+digraph "Scop Graph for 'print_array' function" {
+	label="Scop Graph for 'print_array' function";
+
+	Node0x17d2200 [shape=record,label="{entry}"];
+	Node0x17d2200 -> Node0x17d4f20;
+	Node0x17d4f20 [shape=record,label="{for.cond}"];
+	Node0x17d4f20 -> Node0x17d9fd0;
+	Node0x17d4f20 -> Node0x17da030;
+	Node0x17d9fd0 [shape=record,label="{for.body}"];
+	Node0x17d9fd0 -> Node0x17da120;
+	Node0x17da120 [shape=record,label="{for.cond1}"];
+	Node0x17da120 -> Node0x17da180;
+	Node0x17da120 -> Node0x17da1e0;
+	Node0x17da180 [shape=record,label="{for.body3}"];
+	Node0x17da180 -> Node0x17da090;
+	Node0x17da180 -> Node0x17da0f0;
+	Node0x17da090 [shape=record,label="{if.then}"];
+	Node0x17da090 -> Node0x17da0f0;
+	Node0x17da0f0 [shape=record,label="{if.end}"];
+	Node0x17da0f0 -> Node0x17da390;
+	Node0x17da390 [shape=record,label="{for.inc}"];
+	Node0x17da390 -> Node0x17da120[constraint=false];
+	Node0x17da1e0 [shape=record,label="{for.end}"];
+	Node0x17da1e0 -> Node0x17d9e40;
+	Node0x17d9e40 [shape=record,label="{for.inc10}"];
+	Node0x17d9e40 -> Node0x17d4f20[constraint=false];
+	Node0x17da030 [shape=record,label="{for.end12}"];
+	colorscheme = "paired12"
+        subgraph cluster_0x17d38f0 {
+          label = "";
+          style = solid;
+          color = 1
+          subgraph cluster_0x17d4030 {
+            label = "Non affine branch in BB 'for.body3' with LHS: %rem and RHS: 79";
+            style = solid;
+            color = 6
+            subgraph cluster_0x17d3fb0 {
+              label = "Non affine branch in BB 'for.body3' with LHS: %rem and RHS: 79";
+              style = solid;
+              color = 5
+              subgraph cluster_0x17d3f30 {
+                label = "Non affine branch in BB 'for.body3' with LHS: %rem and RHS: 79";
+                style = solid;
+                color = 7
+                Node0x17da180;
+                Node0x17da090;
+              }
+              Node0x17da120;
+              Node0x17da0f0;
+              Node0x17da390;
+            }
+            Node0x17d4f20;
+            Node0x17d9fd0;
+            Node0x17da1e0;
+            Node0x17d9e40;
+          }
+          Node0x17d2200;
+          Node0x17da030;
+        }
+}
diff --git a/final/www/experiments/matmul/scopsonly.print_array.dot.png b/final/www/experiments/matmul/scopsonly.print_array.dot.png
new file mode 100644
index 0000000..b0d4b45
--- /dev/null
+++ b/final/www/experiments/matmul/scopsonly.print_array.dot.png
Binary files differ
diff --git a/final/www/favicon.ico b/final/www/favicon.ico
new file mode 100644
index 0000000..0638d5b
--- /dev/null
+++ b/final/www/favicon.ico
Binary files differ
diff --git a/final/www/get_started.html b/final/www/get_started.html
new file mode 100644
index 0000000..087a631
--- /dev/null
+++ b/final/www/get_started.html
@@ -0,0 +1,200 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+  <title>Polly - Getting Started</title>
+  <link type="text/css" rel="stylesheet" href="menu.css" />
+  <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Getting Started: Building and Installing Polly</h1>
+
+<h2> Automatic </h2>
+
+There is a <a href="polly.sh">script</a> available to automatically checkout,
+update, build, and test Polly. This script contains all the commands that are
+subsequently described on this webpage. The automatic installation consists
+of four simple steps:
+
+<pre>
+mkdir polly &amp;&amp; cd polly
+wget http://polly.llvm.org/polly.sh
+chmod +x polly.sh
+./polly.sh
+</pre>
+
+<h2> Manual </h2>
+<h3 id="source"> Get the code </h3>
+
+The Polly source code is available in the LLVM SVN repository as well as through
+an official git mirror. It is added to the <em>tools</em>
+directory of the llvm sources.
+<b>Polly and LLVM need to be checked out at the same time. Checkouts
+   from different dates may not work!</b>
+<h4>Set the directory layout:</h4>
+<pre>
+export BASE=`pwd`
+export LLVM_SRC=${BASE}/llvm
+export POLLY_SRC=${LLVM_SRC}/tools/polly
+
+# Also build the matching clang-version (optional)
+export CLANG_SRC=${LLVM_SRC}/tools/clang
+</pre>
+
+<h4>SVN</h4>
+<pre>
+svn checkout http://llvm.org/svn/llvm-project/llvm/trunk ${LLVM_SRC}
+svn checkout http://llvm.org/svn/llvm-project/polly/trunk ${POLLY_SRC}
+
+# Also build the matching clang-version (optional)
+svn checkout http://llvm.org/svn/llvm-project/cfe/trunk ${CLANG_SRC}
+</pre>
+<h4>GIT</h4>
+<pre>
+git clone http://llvm.org/git/llvm.git ${LLVM_SRC}
+git clone http://llvm.org/git/polly.git ${POLLY_SRC}
+
+# Also build the matching clang-version (optional)
+git clone http://llvm.org/git/clang.git ${CLANG_SRC}
+</pre>
+<h3 id="prerequisites"> Prerequisites </h3>
+<ul>
+<li>libgmp</li>
+<li>isl</li>
+</ul>
+
+<h4> libgmp </h4>
+Install libgmp (library + developer package) through the package management
+system of your operating system.
+
+<h4> isl</h4>
+
+Polly is tested with a fixed version of isl. To obtain the source code of isl
+use checkout_isl.sh as available in ${POLLY_SRC}/utils/checkout_isl.sh.
+
+<h4>Set the directory layout:</h4>
+<pre>
+export ISL_SRC=${BASE}/isl_src
+export ISL_INSTALL=${BASE}/isl_install
+</pre>
+
+<h4> First installation</h4>
+<pre>
+${POLLY_SRC}/utils/checkout_isl.sh ${ISL_SRC}
+cd ${ISL_SRC}
+./configure --prefix=${ISL_INSTALL}
+make
+make install
+cd ${BASE}
+</pre>
+
+<h4> Update the installation</h4>
+
+Updating isl may become necessary, if Polly uses a feature
+only available in a recent version of isl.
+<pre>
+${POLLY_SRC}/utils/checkout_isl.sh ${ISL_SRC}
+cd ${ISL_SRC}
+make
+make install
+cd ${BASE}
+</pre>
+
+<h3 id="build">Build Polly</h3>
+
+To build Polly you can either use the autoconf or the cmake build system. At the
+moment only the autoconf build system allows to run the llvm test-suite and only
+the cmake build system allows to run 'make check-polly'.
+
+<h4>Set the directory layout:</h4>
+<pre>
+export LLVM_BUILD=${BASE}/llvm_build
+mkdir ${LLVM_BUILD}
+cd ${LLVM_BUILD}
+</pre>
+
+<h4>CMake</h4>
+
+<pre>
+cmake -DCMAKE_PREFIX_PATH=${ISL_INSTALL} ${LLVM_SRC}
+make
+</pre>
+
+<h4> Autoconf </h4>
+
+<pre>
+${LLVM_SRC}/configure --with-isl=${ISL_INSTALL}
+make
+</pre>
+
+<h3> Test Polly</h3>
+
+<p>To check if Polly works correctly you can run <em>make check-polly</em> for the
+cmake build or <em>make check-polly -C tools/polly/test/</em> for the autoconf
+build.
+
+<p>If you get something like <em>"... libisl.so.9: cannot open shared object file .."</em>,
+it is because you installed isl to a non-standard path, and libisl
+could not be found. To solve this issue, you need to append the path of parent
+directory of libisl, i.e. ${ISL_INSTALL}/lib, to LD_LIBRARY_PATH by:
+
+<pre>export LD_LIBRARY_PATH=${ISL_INSTALL}/lib:$LD_LIBRARY_PATH</pre>
+
+<p>Also try the above command if you get errors such as:
+<code>undefined symbol: isl_ctx_get_max_operations</code>
+
+<p>If you get an error in one of the python files, your system probably uses python3
+as default python interpreter. This is the case, for instance, under Arch Linux.
+To solve this issue, run <code>cmake</code> again, but with the added argument:
+<code>-DPYTHON_EXECUTABLE=/usr/bin/python2</code> (replace <code>/usr/bin/python2</code>
+with the location of the python2 interpreter under your system).
+
+<pre>cmake -DCMAKE_PREFIX_PATH=${ISL_INSTALL} -DPYTHON_EXECUTABLE=/usr/bin/python2 ${LLVM_SRC}</pre>
+
+<h2> Optional Features </h2>
+
+<h3> Pocc [Supported until <a href="http://llvm.org/releases/download.html#3.4.2">LLVM 3.4.2</a>]</h3>
+
+<p>Polly can use <a href="http://www.cse.ohio-state.edu/~pouchet/software/pocc">
+PoCC</a> as an external optimizer. PoCC is a research project that provides
+an integrated version of <a href="http://pluto-compiler.sf.net">Pluto</a>, an
+advanced data-locality and tileability optimizer. Polly includes internally
+already a similar optimizer, such that in general PoCC is not needed. It is
+only recommended for people who want to compare against a different
+optimizer.</a>
+<br/>
+To use it install PoCC 1.0-rc3.1 (the one with Polly support) and add it to your PATH.
+
+<pre>
+wget <a
+href="http://www.cse.ohio-state.edu/~pouchet/software/pocc/download/pocc-1.0-rc3.1-full.tar.gz">http://www.cse.ohio-state.edu/~pouchet/software/pocc/download/pocc-1.0-rc3.1-full.tar.gz</a>
+tar xzf pocc-1.0-rc3.1-full.tar.gz
+cd pocc-1.0-rc3.1
+./install.sh
+export PATH=$PATH:`pwd`/bin
+</pre>
+
+You also need to install scoplib-0.2.0 and provide its location to
+Polly's cmake or configure call.
+
+<pre>
+wget <a
+href="http://www.cse.ohio-state.edu/~pouchet/software/pocc/download/modules/scoplib-0.2.0.tar.gz"
+>http://www.cse.ohio-state.edu/~pouchet/software/pocc/download/modules/scoplib-0.2.0.tar.gz</a>
+tar xzf  scoplib-0.2.0.tar.gz
+cd scoplib-0.2.0
+./configure --enable-mp-version --prefix=/path/to/scoplib/installation
+make && make install
+</pre>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/final/www/images/architecture.png b/final/www/images/architecture.png
new file mode 100644
index 0000000..fdd26a0
--- /dev/null
+++ b/final/www/images/architecture.png
Binary files differ
diff --git a/final/www/images/header-background.png b/final/www/images/header-background.png
new file mode 100644
index 0000000..d736b99
--- /dev/null
+++ b/final/www/images/header-background.png
Binary files differ
diff --git a/final/www/images/iit-madras.png b/final/www/images/iit-madras.png
new file mode 100644
index 0000000..caf90ab
--- /dev/null
+++ b/final/www/images/iit-madras.png
Binary files differ
diff --git a/final/www/images/osu.png b/final/www/images/osu.png
new file mode 100644
index 0000000..154a04b
--- /dev/null
+++ b/final/www/images/osu.png
Binary files differ
diff --git a/final/www/images/performance/parallel-large.png b/final/www/images/performance/parallel-large.png
new file mode 100644
index 0000000..76261bb
--- /dev/null
+++ b/final/www/images/performance/parallel-large.png
Binary files differ
diff --git a/final/www/images/performance/parallel-small.png b/final/www/images/performance/parallel-small.png
new file mode 100644
index 0000000..3c9f6ba
--- /dev/null
+++ b/final/www/images/performance/parallel-small.png
Binary files differ
diff --git a/final/www/images/performance/sequential-large.png b/final/www/images/performance/sequential-large.png
new file mode 100644
index 0000000..5c88354
--- /dev/null
+++ b/final/www/images/performance/sequential-large.png
Binary files differ
diff --git a/final/www/images/performance/sequential-small.png b/final/www/images/performance/sequential-small.png
new file mode 100644
index 0000000..94b248d
--- /dev/null
+++ b/final/www/images/performance/sequential-small.png
Binary files differ
diff --git a/final/www/images/sys-uni.png b/final/www/images/sys-uni.png
new file mode 100644
index 0000000..e6b84e1
--- /dev/null
+++ b/final/www/images/sys-uni.png
Binary files differ
diff --git a/final/www/images/uni-passau.png b/final/www/images/uni-passau.png
new file mode 100644
index 0000000..4bbfa21
--- /dev/null
+++ b/final/www/images/uni-passau.png
Binary files differ
diff --git a/final/www/images/video-summit-2011.png b/final/www/images/video-summit-2011.png
new file mode 100644
index 0000000..dc72e7c
--- /dev/null
+++ b/final/www/images/video-summit-2011.png
Binary files differ
diff --git a/final/www/index.html b/final/www/index.html
new file mode 100644
index 0000000..bd869ed
--- /dev/null
+++ b/final/www/index.html
@@ -0,0 +1,385 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Polyhedral optimizations for LLVM</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+  <script src="video-js/video.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript">
+    VideoJS.setupAllWhenReady();
+  </script>
+
+  <!-- Include the VideoJS Stylesheet -->
+  <link rel="stylesheet" href="video-js/video-js.css" type="text/css" media="screen" title="Video JS">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>About Polly</h1>
+  <!--*********************************************************************-->
+
+  <p> Polly is a high-level loop and data-locality optimizer and optimization
+  infrastructure for LLVM. It uses an abstract mathematical representation based
+  on integer polyhedra to analyze and optimize the memory access pattern of a
+  program. We currently perform classical loop transformations, especially
+  tiling and loop fusion to improve data-locality. Polly can also exploit
+  OpenMP level parallelism, expose SIMDization opportunities. Work has also be
+  done in the area of automatic GPU code generation.</p>
+
+  For many users, however, it's not the existing optimizations in Polly that are
+  of most interest, but the new analyses and optimizations enabled by the Polly
+  infrastructure. At
+  <a href="http://polyhedral.info">polyhedral.info</a> you can get an idea of
+  what has already been done and what is possible in the context of polyhedral
+  compilation.
+
+  <p>
+  <div class="video-js-box" style="margin:auto; margin-top: 1em; margin-bottom: 1em">
+    <video id="example_video_2" class="video-js" width="640" height="360"
+           controls="controls" preload="auto"
+           poster="images/video-summit-2011.png">
+      <source
+           src="http://www.grosser.es/publications/grosser-2011--Polly-First-successful-optimizations--LLVM-Developer-Meeting.mp4"
+           type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
+      <source
+           src="http://www.grosser.es/publications/grosser-2011--Polly-First-successful-optimizations--LLVM-Developer-Meeting.webm"
+           type='video/webm; codecs="vp8, vorbis"'>
+      <object id="flash_fallback_2" class="vjs-flash-fallback" width="640"
+      height="360" type="application/x-shockwave-flash"
+        data="http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf">
+        <param name="movie" value="http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf" />
+        <param name="allowfullscreen" value="true" />
+        <param name="flashvars"
+        value='config={"playlist":["publications/images/video-summit-2011.png",
+        {"url":
+        "http://www.grosser.es/publications/grosser-2011--Polly-First-successful-optimizations--LLVM-Developer-Meeting.mp4","autoPlay":false,"autoBuffering":true}]}'
+        />
+        <img src="images/video-summit-2011.png" width="640" height="360" alt="Poster Image"
+          title="No video playback capabilities." />
+      </object>
+    </video>
+  </div>
+
+  <!--=====================================================================-->
+  <h2>News</h2>
+  <!--=====================================================================-->
+
+  <table id="news">
+  <tr><td><b>2014</b></td></tr>
+  <tr><td width="120"><p>August</p></td>
+  <td>
+  <h4>Polly drops the support of ScopLib and the external optimizer PoCC</h4>
+  The support for ScopLib as an exchange format has been removed as recent
+  versions of clan, candl and pluto all support the OpenScop exchange format.
+
+  The support of the external optmizer PoCC has been dropped in favor of the
+  isl optimizer (default) and the still available pluto support.
+  </td>
+  </tr>
+  <tr><td><b>2014</b></td></tr>
+  <tr><td width="120"><p>June</p></td>
+  <td>
+  <h4>Polly can be built without GPL licensed software</h4> After Sebastian
+  Pop's
+  and David Peixotto's (both Qualcomm) recent <a
+  href="http://repo.or.cz/w/isl.git/commit/60703e3ee89b9d5d4d1afb6a3f611292c0884574">commit</a>
+  to isl, isl's latest development version can be built with imath instead of
+  GMP. With both CLooG and gmp having become optional, the last obilgatory
+  dependency to GPL licensed software has been removed. Now Polly only depends
+  on isl (and the included imath), which are both MIT licensed.
+  </td>
+  </tr>
+  <tr><td width="120"><p>April</p></td>
+  <td>
+  <h4>Polly Phone Call - 23April</h4>
+  We had a polly phone call about delinearizing array accesses (II)<a
+  href="https://docs.google.com/document/d/1IZewI8Up0iEkCNIPr6gVtwJxF7RV6KmXkdwOBM_Q5Cs/edit?usp=sharing ">Meeting notes</a> are available online.
+  <h4>Polly Phone Call - 17th April</h4>
+  We had a polly phone call about delinearizing array accesses <a
+  href="https://docs.google.com/document/d/14d3ehkH2MsvBdqsEOSYjysH0Ztyzb75Lp843hnxh2IA/edit?usp=sharing">Meeting notes</a> are available online.
+  <h4>Polly Phone Call - 10th April</h4>
+  We had a polly phone call. <a
+  href="https://docs.google.com/document/d/12W-qZjiZGEQ_lVrob4OzvKJI3EooonC-ap1b9f9KCUE/edit?usp=sharing">Meeting notes</a> are available online.
+  <h4>Polly Phone Call - 4th April</h4>
+  We had a polly phone call. <a
+  href="https://drive.google.com/folderview?id=0B7OMOXTgCYIUWkpJbWVJcW04ams&usp=sharing">Meeting notes</a> are available online.
+  </td>
+  </tr>
+  <tr><td width="120"><p>March</p></td>
+  <td>
+  <h4>Static link Polly into tools</h4> Polly can now be configured with 'cmake
+  -D LINK_POLLY_INTO_TOOLS:Bool=ON' to be statically linked in the tools (opt,
+  bugpoint, and clang.) This makes it easier to use polly without having to load
+  a shared library, and it also reduces the complexity of compiling Polly on
+  Windows.
+  </td>
+  </tr>
+  <tr><td width="120"><p>February</p></td>
+  <td>
+  <h4>Polly presentation at FOSDEM 2014</h4> Polly was <a
+  href="https://fosdem.org/2014/schedule/event/polly/">presented</a> at the
+  FOSDEM LLVM developer's meeting.
+  <h4>New LLVM test-suite buildbots</h4>
+  The set of <a href="http://lab.llvm.org:8011/console?category=polly">Polly
+  buildbots</a> has been extended. We now have 16 new blades that track
+  correctness and performance when compiling the LLVM test-suite. For now five
+  of them are used to provide <a
+  href="http://llvm.org/perf/db_default/v4/nts/22463">fine granularity
+  reports</a> (almost per-commit)
+  for 'clang -O3' (no polly). We also have six machines that track different
+  configurations of polly.
+  </td>
+  </tr>
+  <tr><td width="120"><p>January</p></td>
+  <td>
+  <h4>islplot released</h4>
+  <a href="https://github.com/tobig/islplot">islplot</a> is a library that
+  generates illustrations of integer sets and maps. It relies on <a
+  href="http://repo.or.cz/w/isl.git">isl</a> to model the integer sets and uses the <a
+  href="https://pypi.python.org/pypi/islpy">islpy</a> Python bindings to access
+  them. Plotting is performed with <a
+  href="http://matplotlib.org">matplotlib</a>. The following <a
+  href="http://nbviewer.ipython.org/github/tobig/islplot/blob/master/notebooks/islplot-examples.ipynb">
+  Examples</a> show its use.
+  </td>
+  </tr>
+  <tr><td><b>2013</b></td></tr>
+  <tr><td width="120"><p>November</p></td>
+  <td>
+  <h4>Loop optimization BoF at upcoming LLVM conference</h4>
+  At the upcoming <a href="http://llvm.org/devmtg/2013-11/#bof5">LLVM conference
+  </a> there will be a loop optimization BoF discussing Polly and other high
+  level loop optimizers.
+  </td>
+  </tr>
+  <tr><td width="120"><p>October</p></td>
+  <td>
+  <h4>Automatic code coverage and static analysis tests</h4>
+  Sylvestre Ledru set up automatic tests for <a
+  href="http://buildd-clang.debian.net/coverage/">code coverage</a> and
+  <a href="http://buildd-clang.debian.net/scan-build/">static analysis</a>
+  which run at least once a day and which include results for Polly.
+  <h4>Move to CLooG 0.18.1 and isl 0.12.1</h4>
+  With the move to an isl 0.12 version Polly can be compiled without the
+  need to link directly to GMP (if isl is used for code generation). Currently
+  isl is still internally using GMP, but private patches exist to also remove
+  this dependency. Without the use of GMP, a <b>GPL free</b> version of Polly
+  is possible.
+  </td></tr>
+
+  <tr><td><b>2012</b></td></tr>
+  <tr><td width="120"><p>December</p></td>
+  <td>
+  <h4> New publication in the PPL Journal
+     </h4>
+
+      We published a journal version of the Polly paper named
+      <em>
+      Polly - Performing polyhedral optimizations on a low-level intermediate
+      representation</em> in the Parallel Processing Letters 2012.
+  </td></tr>
+  <tr><td width="120"><p>September</p></td>
+  <td>
+  <h4>Experimental support for the <b>new isl code generator</b></h4>
+     The code generator can be parameterized on a fine-grained
+     level. It gives direct control for example over unrolling, the amount of
+     control overhead and the code size. It can also be used to
+     create loops to handle border conditions or to perform full-partial tile
+     separation.<br />
+     We also relicensed isl under the <b>MIT license</b>. This means, with the
+     exception of GMP (LGPL), there is no other (L)GPL licensed software used in
+     Polly. The
+     use of GMP is limited to a well defined interface. Replacing it with
+     a BSD licensed replacement is a tractable engineering project we would
+     be very interested in. For more information about isl see the <a
+     href="http://www.kotnet.org/~skimo/isl/manual.pdf">isl manual</a>.
+     </p>
+  </td></tr>
+  <tr><td width="120"><p>July</p></td>
+  <td>
+  <p> Polly can now be directly linked to the <a
+href="http://pluto-compiler.sourceforge.net/">Pluto optimizer</a>. We were
+already able to perform Pluto-like optimizations with Polly, as a similar
+algorithm was added to isl half a year ago. However, being able to directly
+compare with the original implementation will not only bring in competition in
+the optimizer field. It will also allow new experiments with a cutting edge
+research tool.<br \>
+  This support was on of the outcomes of the 1-day Polly workshop and the
+  following week of joint work at IISC Bangalore and in cooperation with
+  AMD India.
+  </td></tr>
+  <td>
+  </td></tr>
+  <tr><td width="120"><p>February</p></td>
+  <td>
+  <p>Polly is an official LLVM project, reachable at <a
+  href="http://polly.llvm.org">http://polly.llvm.org</a></p>
+  </td></tr>
+  <tr><td width="120"><p>January</p></td>
+  <td>
+  <p>Improved support for the isl scheduling optimizer</p>
+  Polly can now automatically optimize all <a
+  href="http://www.cse.ohio-state.edu/~pouchet/software/polybench/">polybench
+  2.0</a> kernels without the help of
+  an external optimizer. The compile time is reasonable and we can show
+  notable speedups for various kernels.
+  </td></tr>
+
+  <tr>
+  <tr><td><b><br/>2011</b></td></tr>
+  <tr><td width="120"><p>November</p></td>
+  <td>
+  <p>
+  Talk at the <a href="http://llvm.org/devmtg/2011-11/">
+      LLVM Developer Meeting 2011</a></p>
+  New SCEV parser<br>
+  (Allows parameters in array subscript and max/signextend)
+  </td></tr>
+
+  <tr>
+  <td><p>October</p></td>
+  <td>
+  <p>Polly can use the isl schedule optimizer<br>
+    (The optimizer is similar to the one in Pluto, but it is part of isl)
+  </p>
+  </td></tr>
+
+  <tr>
+  <td><p>August</p></td>
+  <td>
+  <p>
+  <a href="example_load_Polly_into_clang.html">Use Polly as
+  clang plugin</a></p>
+  </td>
+  </tr>
+
+  <tr>
+  <td><p>July</p></td>
+  <td>
+  <p> Polly builder as part of the <a
+  href="http://lab.llvm.org:8011/console">LLVM Buildbots</a>
+  </p>
+  </td>
+  </tr>
+
+  <tr>
+  <td><p>June</p></td>
+  <td>
+  <p><a href="http://www.grosser.es">Tobias</a> is founded for
+  three years by a <a
+  href="http://research.google.com/university/relations/fellowship_recipients.html">
+  Google Europe Fellowship in Efficient Computing</a>.
+  </p>
+  </td>
+  </tr>
+
+  <tr>
+  <td><p>May </p></td>
+  <td><p><a href="http://www.grosser.es">Tobias</a>' diploma thesis and
+  Raghesh's master thesis. See our <a
+  href="publications.html">list of publications</a>.</p></td>
+  </tr>
+
+  <tr>
+  <td><p>April</p></td>
+  <td><p>Polly moves to the LLVM infrastructure (svn, bugtracker)</p></td>
+  </tr>
+
+  <tr>
+  <td><p>March</p></td>
+  <td><p>Presentation at <a
+  href="http://impact2011.inrialpes.fr/">CGO/IMPACT</a></p>
+  <p>Polly can compile
+  polybench 2.0 with vectorization and OpenMP code generation</p>
+  </td>
+  </tr>
+  <tr>
+  <td><p>Februar</p></td>
+  <td><p>pollycc - a script to automatically compile with
+  polyhedral optimizations </p></td>
+  </tr>
+
+  <tr>
+  <td><p> Januar</p></td>
+  <td><p> Basic OpenMP support, Alias analysis integration,
+  Pluto/POCC support </p></td>
+  </tr>
+
+  <tr><td><b><br>2010</b></td></tr>
+  <tr>
+  <td><p> Dezember </p></td>
+  <td><p>Basic vectorization support </p></td>
+  </tr>
+
+  <tr>
+  <td><p> November </p></td>
+  <td><p>Talk at the <a
+  href="http://llvm.org/devmtg/2010-11/">LLVM Developer Meeting</a> </p></td>
+  </tr>
+
+  <tr>
+  <td><p>October</p></td>
+  <td><p>Dependency analysis </p>
+  <p>Finished Phase 1 - Get something working </p>
+  <p>Support scalar dependences and sequential SCoPs </p>
+  </td>
+  </tr>
+
+  <tr>
+  <td><p>August</p></td>
+  <td><p>RegionInfo pass committed to LLVM</p>
+  <p>llvm-test suite compiles </p>
+  </td>
+  </tr>
+
+  <tr>
+  <td><p>July</p></td>
+  <td><p>Code generation works for normal SCoPs.  </p></td>
+  </tr>
+
+  <tr>
+  <td><p>May</p></td>
+  <td><p>The CLooG AST can be parsed.</p>
+  </td>
+  </tr>
+
+  <tr>
+  <td><p>April</p></td>
+  <td><p>SCoPs can automatically be detected. </p></td>
+  </tr>
+
+  <tr>
+  <td><p>March</p></td>
+  <td><p>The RegionInfo framework is almost completed.  </p></td>
+  </tr>
+
+  <tr>
+  <td><p>February</p></td>
+  <td><p>Translate a simple loop to Polly-IR and regenerate a loop structure
+         with CLooG works.  </p>
+  <p>ISL and CLooG are integrated.  </p></td>
+  </tr>
+
+  </tr>
+
+  <tr>
+  <td><p>January</p></td>
+  <td><p>The RegionInfo pass is finished.  </p></td>
+  </tr>
+
+  <tr><td><b><br>2009</b></td></tr>
+  <tr>
+  <td><p>End of the year</p></td>
+  <td><p>Work on the infrastructure started.  </p></td>
+  </tr>
+  </table>
+  </ul>
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/menu.css b/final/www/menu.css
new file mode 100644
index 0000000..a3e3ad7
--- /dev/null
+++ b/final/www/menu.css
@@ -0,0 +1,87 @@
+/***************/
+/* page layout */
+/***************/
+
+#menu {
+        line-height: 1.3em;
+	width: 18em;
+        float: left;
+        margin-right: 3em;
+        padding: 1em;
+        background-color: #edf7ff;
+}
+/**************/
+/* menu style */
+/**************/
+
+#menu .submenu {
+	display:block;
+        padding-top: 0.2em;
+        font-bottom: 1.2em;
+}
+
+/*
+ * Color scheme
+ * blue: #556293
+ * red:  #931e24
+ * brown: #937155
+ * green: #24931e
+ */
+
+#menu label {
+	display:block;
+        color: white;
+        margin-bottom: 0.4em;
+        margin-top: 0.4em;
+	font-weight: bold;
+        font-size: 1.1em;
+	text-align: center;
+	background-color: #3b4567;
+        -webkit-border-radius: 5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+        padding-top: 0.2em;
+        padding-bottom: 0.2em;
+}
+
+#menu a {
+	padding:0 .2em;
+        -webkit-border-radius: 5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+	display:block;
+        font-weight: bold;
+	text-decoration: none;
+        color: #3b4567;
+}
+
+#menu a:visited {
+}
+
+#menu .submenu2 {
+        margin-top: 2em;
+}
+
+#menu .submenu2 label {
+	background-color: #f35555;
+}
+
+.rss-box {
+  padding: 0em;
+}
+
+li.rss-item {
+  padding-bottom: 0em;
+  height: 1.3em;
+}
+
+.rss_item {
+  line-height: 0.5em;
+  padding-top: 1em;
+}
+
+.rss_date {
+  font-size: 0.8em;
+  color: #f35555;
+  padding-left: 0.4em;
+}
diff --git a/final/www/menu.html.incl b/final/www/menu.html.incl
new file mode 100644
index 0000000..44fab67
--- /dev/null
+++ b/final/www/menu.html.incl
@@ -0,0 +1,76 @@
+<div id="head" style="position: relative">
+<h1><span><a href="/">Polly</a></span></h1>
+<h2><span>LLVM Framework for High-Level Loop and Data-Locality
+Optimizations</span></h2>
+
+
+<p> Hexagonal tiling in 3D</p>
+
+</div>
+<div id="menu">
+  <div class="submenu">
+    <label>Information</label>
+    <a href="/index.html">About Polly</a>
+    <a href="/documentation.html">Documentation</a>
+    <a href="/performance.html">Performance</a>
+    <a href="/publications.html">Publications</a>
+    <a href="/contributors.html">Contributors</a>
+    <a href="/todo.html">TODO</a>
+    <a href="/changelog.html">ChangeLog</a>
+  </div>
+
+  <div class="submenu">
+    <label>Development </label>
+    <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">
+      Mailing List (patches)
+    </a>
+    <a href="http://groups.google.com/group/polly-dev">Mailing List (discussion)</a>
+    <a href="/bugs.html">Bug Reports</a>
+    <a href="http://lab.llvm.org:8011/console?category=polly">Buildbot</a>
+    <!--
+     These analyses currently do not include Polly.
+    <a href="http://buildd-clang.debian.net/coverage/">Code Coverage</a>
+    <a href="http://buildd-clang.debian.net/scan-build/">Static analysis</a>
+    -->
+  </div>
+
+  <div class="submenu">
+    <label>The Code</label>
+    <a href="/get_started.html">Get and Install</a>
+    <a href="http://llvm.org/viewvc/llvm-project/polly/trunk/">
+      Browse (ViewVC)
+    </a>
+    <a href="http://repo.or.cz/w/polly-mirror.git">Browse (GitWeb)</a>
+  </div>
+
+  <div class="submenu2">
+  <label>polyhedral.info news</label>
+  <script language="JavaScript"
+  src="http://feed2js.org//feed2js.php?src=http%3A%2F%2Fpolyhedral.info%2Frss.xml&num=5&utf=y"
+  charset="UTF-8" type="text/javascript"></script>
+
+  <noscript>
+  <a
+  href="http://feed2js.org//feed2js.php?src=http%3A%2F%2Fpolyhedral.info%2Frss.xml&num=5&utf=y&html=y">View
+  RSS feed</a>
+  </noscript>
+ </div>
+</div>
+
+<script type="text/javascript">
+  var _paq = _paq || [];
+  _paq.push(["trackPageView"]);
+  _paq.push(["enableLinkTracking"]);
+
+  (function() {
+    var u=(("https:" == document.location.protocol) ? "https" : "http") + "://www.grosser.es/piwik/piwik/";
+    _paq.push(["setTrackerUrl", u+"piwik.php"]);
+    _paq.push(["setSiteId", "3"]);
+    var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
+    g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
+  })();
+</script>
+<noscript>
+<img src="http://www.grosser.es/piwik/piwik/piwik.php?idsite=3&amp;rec=1" style="border:0" alt="" />
+</noscript>
+
diff --git a/final/www/performance.html b/final/www/performance.html
new file mode 100644
index 0000000..300a188
--- /dev/null
+++ b/final/www/performance.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head> <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Performance</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<h1>Performance</h1>
+
+<p>To evaluate the performance benefits Polly currently provides we compiled the
+<a href="http://www.cse.ohio-state.edu/~pouchet/software/polybench/">Polybench
+2.0</a> benchmark suite.  Each benchmark was run with double precision floating
+point values on an Intel Core Xeon X5670 CPU @ 2.93GHz (12 cores, 24 thread)
+system. We used <a href="http://pocc.sf.net">PoCC</a> and the included <a
+href="http://pluto-compiler.sf.net">Pluto</a> transformations to optimize the
+code. The source code of Polly and LLVM/clang was checked out on 
+25/03/2011.</p>
+
+<p>The results shown were created fully automatically without manual
+interaction. We did not yet spend any time to tune the results. Hence
+further improvments may be achieved by tuning the code generated by Polly, the
+heuristics used by Pluto or by investigating if more code could be optimized.
+As Pluto was never used at such a low level, its heuristics are probably
+far from perfect. Another area where we expect larger performance improvements
+is the SIMD vector code generation. At the moment, it rarely yields to
+performance improvements, as we did not yet include vectorization in our
+heuristics. By changing this we should be able to significantly increase the
+number of test cases that show improvements.</p>
+
+<p>The polybench test suite contains computation kernels from linear algebra
+routines, stencil computations, image processing and data mining. Polly
+recognices the majority of them and is able to show good speedup. However,
+to show similar speedup on larger examples like the SPEC CPU benchmarks Polly
+still misses support for integer casts, variable-sized multi-dimensional arrays
+and probably several other construts. This support is necessary as such
+constructs appear in larger programs, but not in our limited test suite.
+
+<h2> Sequential runs</h2>
+
+For the sequential runs we used Polly to create a program structure that is
+optimized for data-locality. One of the major optimizations performed is tiling.
+The speedups shown are without the use of any multi-core parallelism. No
+additional hardware is used, but the single available core is used more
+efficiently.
+<h3> Small data size</h3>
+<img src="images/performance/sequential-small.png" /><br />
+<h3> Large data size</h3>
+<img src="images/performance/sequential-large.png" />
+<h2> Parallel runs</h2>
+For the parallel runs we used Polly to expose parallelism and to add calls to an
+OpenMP runtime library. With OpenMP we can use all 12 hardware cores
+instead of the single core that was used before. We can see that in several
+cases we obtain more than linear speedup. This additional speedup is due to
+improved data-locality.
+<h3> Small data size</h3>
+<img src="images/performance/parallel-small.png" /><br />
+<h3> Large data size</h3>
+<img src="images/performance/parallel-large.png" />
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/phonecall.html b/final/www/phonecall.html
new file mode 100644
index 0000000..53f1a92
--- /dev/null
+++ b/final/www/phonecall.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Polyhedral Phone Call</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>Polly: Polyhedral Phone Call</h1>
+  <!--*********************************************************************-->
+
+  <p>There are irregular phone calls to discuss polyhedral topics and
+     related projects. For this we use a conference service that can be
+     reached both through SIP clients and international dial in numbers.</p>
+
+ <ul>
+ <li><b>VoIP/SIP:</b> sip:000777polyhedral@iptel.org<br />
+    <a href="http://ekiga.org">Ekiga</a> is a SIP client that works well for
+    most of us.</li>
+ <li><b>Traditional Dailin Numbers:</b><br />
+    To use your normal land line phone to connect to the conference dial
+    one of the many available <a
+    href="http://www.sipbroker.com/sipbroker/action/pstnNumbers">dial in
+    numbers</a>. When asked for the number to connect type: <em>*011497659</em>.
+    <br />
+    Attention: Some of the dial in numbers do not work reliable. If you are not
+    asked for the number you want to connect to after a couple of seconds, just
+    try another one. <br/>
+    Some selected dial in numbers:
+    <ul>
+    <li><b>USA:</b> +1-443-524-7370, +1-702-553-2797 </li>
+    <li><b>UK:</b> +44-151-601-8747, +44-115-871-8347</li>
+    <li><b>Belgium:</b> +32-4-2680133, +32-9-2980106</li>
+    </ul>
+
+    </ul> 
+  
+</div>
+</body>
+</html>
diff --git a/final/www/polly.sh b/final/www/polly.sh
new file mode 100644
index 0000000..ae4c480
--- /dev/null
+++ b/final/www/polly.sh
@@ -0,0 +1,50 @@
+#!/bin/bash -xe
+
+export BASE=`pwd`
+export LLVM_SRC=${BASE}/llvm
+export POLLY_SRC=${LLVM_SRC}/tools/polly
+export CLANG_SRC=${LLVM_SRC}/tools/clang
+export ISL_SRC=${BASE}/isl_src
+export ISL_INSTALL=${BASE}/isl_install
+export LLVM_BUILD=${BASE}/llvm_build
+
+if [ -e /proc/cpuinfo ]; then
+    procs=`cat /proc/cpuinfo | grep processor | wc -l`
+else
+    procs=1
+fi
+
+if ! test -d ${LLVM_SRC}; then
+    git clone http://llvm.org/git/llvm.git ${LLVM_SRC}
+fi
+
+if ! test -d ${POLLY_SRC}; then
+    git clone http://llvm.org/git/polly.git ${POLLY_SRC}
+fi
+
+if ! test -d ${CLANG_SRC}; then
+    git clone http://llvm.org/git/clang.git ${CLANG_SRC}
+fi
+
+${POLLY_SRC}/utils/checkout_isl.sh ${ISL_SRC}
+cd ${ISL_SRC}
+
+if ! test -e ${ISL_SRC}/config.log; then
+    ./configure --prefix=${ISL_INSTALL}
+fi
+make
+make install
+cd ${BASE}
+
+mkdir -p ${LLVM_BUILD}
+cd ${LLVM_BUILD}
+
+if which cmake ; then
+    cmake -DCMAKE_PREFIX_PATH=${ISL_INSTALL} ${LLVM_SRC}
+    make -j$procs -l$procs
+    make check-polly
+else
+    ${LLVM_SRC}/configure --with-isl=${ISL_INSTALL}
+    make -j$procs -l$procs
+    make check-polly -C tools/polly/test/
+fi
diff --git a/final/www/publications.html b/final/www/publications.html
new file mode 100644
index 0000000..90d34a2
--- /dev/null
+++ b/final/www/publications.html
@@ -0,0 +1,190 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head>
+  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Publications</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+  <!--*********************************************************************-->
+  <h1>Publications</h1>
+  <!--*********************************************************************-->
+
+  <h2> Publications about polyhedral compilation </h2>
+  <a href="http://polyhedral.info/publications.html">polyhedral.info</a> has a
+  large list of publications related to polyhedral compilation. They are very
+  useful to get an idea of the latest developments in this area of compilation
+  as well as to understand what kind of optimizations can be built on top of
+  Polly.
+
+  <h2> Citing Polly</h2>
+
+  The canonical publication to cite Polly is:
+
+<p>
+  <em>Polly - Performing polyhedral optimizations on a low-level intermediate
+      representation </em><br />
+Tobias Grosser, Armin Groesslinger, Christian Lengauer<br />
+Parallel Processing Letters 2012 22:04<br />
+  <a
+href="http://www.worldscientific.com/doi/abs/10.1142/S0129626412500107?af=R">
+Online Issue</a>
+</p>
+
+  <h2> Publications involving Polly </h2>
+  <h3> 2012 </h3>
+  <ul>
+  <li><em>KernelGen - a prototype of auto-parallelizing Fortran/C compiler for NVIDIA GPUs</em><br />
+  Dmitry Mikushin, Nikolay Likhogrud, Hou Yunqing, Sergey Kovylov<br />
+  Multi-core Workshop 2012, NCAR, Boulder, CO<br /><a
+  href="publications/kernelgen-ncar-2012-slides.pdf">Slides</a>
+  </li>
+  <li><em>KernelGen - a toolchain for automatic GPU-centric applications porting</em><br />
+  Nikolay Likhogrud, Dmitry Mikushin, Andrew Adinets<br />
+  Parallel Computational Technologies (PCT) 2012, Novosibirsk<br /><a
+  href="publications/kernelgen-pavt-2012-slides.pdf">Slides</a>
+  </li>
+  </ul>
+  <h3> 2011 </h3>
+  <ul>
+  <li><em>Polly - First Successful Optimizations - How to proceed?</em><br />
+  Tobias Grosser, Ragesh A<br />
+  LLVM Developer Meeting 2011<br /><a
+  href="http://llvm.org/devmtg/2011-11/Grosser_PollyOptimizations.pdf">Slides</a>, <a
+  href="http://llvm.org/devmtg/2011-11/videos/Grosser_PollyOptimizations-desktop.mov">Video
+  (Computer)</a>, <a
+  href="http://llvm.org/devmtg/2011-11/videos/Grosser_PollyOptimizations-mobile.mp4">Video
+  (Mobile)</a></li>
+  <li><em>A Framework for Automatic OpenMP Code Generation</em><br />
+  Raghesh A<br />
+  Masters Thesis (May 2011)<br />
+  <a
+  href="publications/raghesh-a-masters-thesis.pdf">Thesis</a>
+  </li>
+  <li><em>Enabling Polyhedral Optimizations in LLVM</em><br />
+  Tobias Grosser<br />
+  Diploma Thesis (April 2011)<br />
+  <a
+  href="publications/grosser-diploma-thesis.pdf">Thesis</a>
+  </li>
+  <li><em>Polly - Polyhedral Optimization in LLVM</em><br />
+  Tobias Grosser, Hongbin Zheng, Ragesh Aloor, Andreas Simb&uuml;rger, Armin
+  Gr&ouml;&szlig;linger, Louis-No&euml;l Pouchet<br />
+  IMPACT at CGO 2011 <br />
+  <a
+  href="publications/grosser-impact-2011.pdf">Paper</a>, <a
+  href="publications/grosser-impact-2011-slides.pdf">Slides </a>
+  </li>
+  </ul>
+  <h3> 2010 </h3>
+  <ul>
+  <li><em>Polly - Polyhedral Transformations for LLVM</em><br />
+  Tobias Grosser, Hongbin Zheng<br />
+  LLVM Developer Meeting 2010<br /><a
+  href="http://llvm.org/devmtg/2010-11/Grosser-Polly.pdf">Slides</a>, <a
+  href="http://llvm.org/devmtg/2010-11/videos/Grosser_Polly-desktop.mp4">Video
+  (Computer)</a>, <a
+  href="http://llvm.org/devmtg/2010-11/videos/Grosser_Polly-mobile.mp4">Video
+  (Mobile)</a></li>
+  </ul>
+
+  <h2>Publications used within Polly</h2>
+  <h3>Polyhedral library</h3>
+  <ul>
+  <li><em>isl: An Integer Set Library for the Polyhedral Model </em><br />
+  Sven Verdoolaege<br />
+  ICMS 2010
+  </li>
+  </ul>
+  <h3>Optimization</h3>
+  <ul>
+  <li><em>A Practical Automatic Polyhedral Parallelizer and Locality Optimizer
+          </em><br />
+  Uday Bondhugula, Alberto Hartono, J. Ramanujam, P. Sadayappan<br />
+  PLDI 2008
+  </li>
+  <li><em>Effective Automatic Parallelization and Locality Optimization using
+          the Polyhedral Model
+          </em><br />
+  Uday Bondhugula<br />
+  PhD thesis 2008
+  </li>
+  </ul>
+  <h3>Code Generation</h3>
+  <ul>
+  <li><em>Code Generation in the Polyhedral Model Is Easier Than You Think</em>
+  <br />
+  C&eacute;dric Bastoul<br />
+  PACT 2004
+  </li>
+  </ul>
+  <h2>Interesting Publications</h2>
+
+  Publications that are not yet used or implemented in Polly, but that are
+  interesting to look at either to understand general concepts or to implement
+  the corresponding ideas. This list is incomplete and papers are added as
+  we hear about them.<br />
+  <h3>GPGPU</h3>
+  <ul>
+  <li><em>Automatic C-to-CUDA Code Generation for Affine Programs</em>
+  <br />
+  Muthu Manikandan Baskaran, J. Ramanujam and P. Sadayappan<br />
+  CC 2010
+  </li>
+  <li><em>Putting Automatic Polyhedral Compilation for GPGPU to Work<em>
+  Soufiane Baghdadi, Armin Gr&ouml;&szlig;linger, and Albert Cohen. <br />
+  In Proc. of Compilers for Parallel Computers (CPC), 2010.
+  </li>
+  </ul>
+  <h3>Vectorization</h3>
+  <ul>
+  <li><em>Joint Scheduling and Layout Optimization to Enable Multi-Level
+  Vectorization</em>
+  <br />
+  Nicolas Vasilache, Benoit Meister, Muthu Baskaran, Richard Lethin<br />
+  IMPACT 2012 (upcoming)
+  </li>
+  </ul>
+  <h3>Iterative Compilation</h3>
+  <ul>
+  <li><em>Iterative optimization in the polyhedral model: Part I,
+  one-dimensional time.  </em>
+  <br />
+  Louis-No&euml;l Pouchet, C&eacute;dric Bastoul, Albert Cohen and Nicolas Vasilache<br />
+  CGO 2007
+  </li>
+  <li><em>Iterative optimization in the polyhedral model: Part II,
+  multidimensional time.  </em>
+  <br />
+  Louis-No&euml;l Pouchet, C&eacute;dric Bastoul, Albert Cohen and John Cavazos<br />
+  PLDI 2008
+  </li>
+  </ul>
+  <h3>Non-static Control</h3>
+  <ul>
+  <li><em>The Polyhedral Model Is More Widely Applicable Than You Think</em>
+  <br />
+  Mohamed-Walid Benabderrahmane, Louis-No&euml;l Pouchet, Albert Cohen,
+  C&eacute;dric
+  Bastoul.<br />
+  CC 2010
+  </li>
+  </ul>
+  <h3>Source to Source Tools</h3>
+  <ul>
+  <li><em> Polyhedral Extraction Tool</em>
+  <br />
+  Sven Verdoolaege, Tobias Grosser<br />
+  IMPACT 2012
+  </li>
+  </ul>
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/publications/grosser-diploma-thesis.pdf b/final/www/publications/grosser-diploma-thesis.pdf
new file mode 100644
index 0000000..f7e8dd3
--- /dev/null
+++ b/final/www/publications/grosser-diploma-thesis.pdf
Binary files differ
diff --git a/final/www/publications/grosser-impact-2011-slides.pdf b/final/www/publications/grosser-impact-2011-slides.pdf
new file mode 100644
index 0000000..3e60410
--- /dev/null
+++ b/final/www/publications/grosser-impact-2011-slides.pdf
Binary files differ
diff --git a/final/www/publications/grosser-impact-2011.pdf b/final/www/publications/grosser-impact-2011.pdf
new file mode 100644
index 0000000..9b79bd2
--- /dev/null
+++ b/final/www/publications/grosser-impact-2011.pdf
Binary files differ
diff --git a/final/www/publications/kernelgen-ncar-2012-slides.pdf b/final/www/publications/kernelgen-ncar-2012-slides.pdf
new file mode 100644
index 0000000..8a91611
--- /dev/null
+++ b/final/www/publications/kernelgen-ncar-2012-slides.pdf
Binary files differ
diff --git a/final/www/publications/kernelgen-pavt-2012-slides.pdf b/final/www/publications/kernelgen-pavt-2012-slides.pdf
new file mode 100644
index 0000000..ce4b832
--- /dev/null
+++ b/final/www/publications/kernelgen-pavt-2012-slides.pdf
Binary files differ
diff --git a/final/www/publications/raghesh-a-masters-thesis.pdf b/final/www/publications/raghesh-a-masters-thesis.pdf
new file mode 100644
index 0000000..2eeb193
--- /dev/null
+++ b/final/www/publications/raghesh-a-masters-thesis.pdf
Binary files differ
diff --git a/final/www/todo.html b/final/www/todo.html
new file mode 100644
index 0000000..e9098b9
--- /dev/null
+++ b/final/www/todo.html
@@ -0,0 +1,646 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
+<html>
+<head> <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+  <title>Polly - Todo</title>
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <link type="text/css" rel="stylesheet" href="content.css">
+</head>
+<body>
+<div id="box">
+<!--#include virtual="menu.html.incl"-->
+<div id="content">
+<h1> TODO </h1>
+
+<h2> Overview</h2>
+<ul>
+<li><a href="#phase3">Phase 4</a></li>
+<li><a href="#phase3">Phase 3 - Improve Robustness, Interoperability and
+Optimizations (ongoing)</a></li>
+<li><a href="#llvm">Polly as a LLVM Project (Finished February 2012)</a></li>
+<li><a href="#phase2">Phase 2 - First Optimizations and Enhanced User Experience (Finished
+February 2012)</a></li>
+<li><a href="#phase1">Phase 1 - Get Something Working (Finished October 2010)</a>
+</li>
+</ul>
+<h2> Individual Phases</h3>
+
+<h3 id="phase4"> Phase 4</h3>
+<table class="wikitable" cellpadding="2">
+<p> </p>
+
+<tbody>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Infrastructure </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Move to isl C++ bindings
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+<th align="left"> &nbsp; &nbsp; - Add isl C++ bindings generator to isl
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+<tr>
+<th align="left"> Add isl as an external library to Polly SVN
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+<tr>
+<th align="left"> Compile-time: Speed up transformations
+</th><td align="center">
+</td><td>
+</td>
+</tr>
+<th align="left"> &nbsp; &nbsp; - Optimize isl_int for small integers
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+<tr>
+<th align="left"> Compile-time: Minimize SCoP detection time
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+<th align="left"> &nbsp; &nbsp; - Reconsider pass-ordering (move Polly later)
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Increase coverage
+</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+
+<tr>
+<th align="left">
+Support for Modulos
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Boolean Combinations
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Unsigned Integers
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Pointer Comparisions
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Polly as an
+analysis </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+
+<tr>
+<th align="left">
+Model scalars dependences directly in Polly
+</th><td align="center" class='done'> Done
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Code generate scalar dependences
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Model PHI dependences directly in Polly
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Code generate PHI dependences
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> <a href="http://llvm.org/bugs/show_bug.cgi?id=12398">Remove
+the need for independent blocks</a>
+</th><td class="open"> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Remove polly-prepare pass
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Correctness in
+cornercases </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> <a href="http://llvm.org/bugs/show_bug.cgi?id=10381">Derive
+optimal types (instead of always using i64)</a>
+</th><td class="open"> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> <a href="http://llvm.org/bugs/show_bug.cgi?id=12397">Model
+integer wrapping</a>
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr
+
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Optimize Julia
+code with Polly
+analysis </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+
+<th align="left">
+Integrate Polly into Julia
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Eliminate run-time bounds checks
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> &nbsp; &nbsp; - Reconsider unreachables in post-dominance tree
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+
+<th align="left"> &nbsp; &nbsp; - Actually eliminate statements
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Improved
+Optimizations in Polly
+</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+
+<th align="left">
+Multi-level tiling
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Register Tiling
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left">
+Full/partial tile separation for vectorization
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+<th align="left">
+Loop interchange after vectorization to maximize stride-one accesses
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+</table>
+
+
+<h3 id="phase3"> Phase 3 - Improve Robustness, Interoperability and
+Optimizations (ongoing)</h3>
+<table class="wikitable" cellpadding="2">
+<p> </p>
+
+<tbody>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Frontend </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Non-affine access functions
+</th><td align="center" class='done'> Done, needs testing
+</td><td>Marcello
+</td>
+</tr>
+
+
+<tr>
+<tr>
+<th align="left"> <a
+href="http://llvm.org/bugs/show_bug.cgi?id=12403">Variable-size
+multi-dimensional arrays</a>
+</th><td align="center" class='done'> Done
+</td><td>Sebastian
+</td></tr>
+<tr>
+<th align="left"> <a
+href="http://llvm.org/bugs/show_bug.cgi?id=12407">Derive information for
+the SCoP context
+</a>
+</th>
+<td align="center" class='nice'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> <a href="http://llvm.org/bugs/show_bug.cgi?id=12402">Finer
+grained statements</a>
+</th><td align="center" class='nice'> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> Detect reductions
+</th><td align="center" class='done'>Done
+</td><td>Johannes
+</td></tr>
+<tr>
+<th align="left"> Generate code for reductions
+</th><td align="center" class='niceinprogress'>in progress
+</td><td>Johannes
+</td></tr>
+<tr>
+<th align="left"> Assume static sized arrays are only accessed in-bounds
+</th><td align="center" class='done'>Done
+</td><td>Tobias
+</td></tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Optimizer </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> <a href="http://llvm.org/bugs/show_bug.cgi?id=12405">Polyhedral
+dead code elimination</a>
+</th><td class="done">Done
+</td><td>
+</td></tr>
+
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Back End</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> OpenMP code generation support in isl backend
+(requirement to drop CLooG)
+</th><td class="done"> Done
+</td><td> Tobias
+</td></tr>
+<tr>
+<th align="left"> Run-time alias checks
+</th><td class="done"> Done
+</td><td>Johannes
+<tr>
+<th align="left"> <a
+href="http://polly.llvm.org/documentation/gpgpucodegen.html">GPGPU Code
+Generation</a>
+</th><td class="niceinprogress">in progress
+</td><td>
+Yabin
+</td></tr>
+<tr>
+<th align="left"> <a
+href="http://polly.llvm.org/documentation/memaccess.html">Allow optimizers to
+change memory access functions</a>
+</th><td class="done"> Done
+</td><td>Johannes
+</td></tr>
+<tr>
+<th align="left"> <a href="http://llvm.org/bugs/show_bug.cgi?id=12406">Make code
+generation independent of the clast</a>
+</th><td class="done">Done
+</td><td>
+</td></tr>
+
+<tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> General</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Teach bugpoint to extract regions
+</th><td class="nice"> Open
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> Add <a
+href="http://www.cse.ohio-state.edu/~pouchet/software/polybench/">Polybench
+3.2</a> to the LLVM test suite
+</th><td class="done"> Done
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> Build against an installed LLVM
+</th><td class="done"> Done<br />
+</td><td>
+</td></tr>
+<tr>
+<th align="left"> Setup buildbot regression testers using LNT
+</th><td class="done"> Done
+</td><td> Tobias
+</td></tr>
+</tbody></table>
+<h3 id="llvm"> Polly as a LLVM Project (Finished February 2012)</h3>
+
+<table class="wikitable" cellpadding="2">
+
+<tbody>
+<tr style="background: rgb(239, 239, 239);">
+<th>Task
+</th><th> Status
+</th><th>Owner
+</th></tr>
+<tr>
+<th align="left"> Move to LLVM SVN
+</th><td class="done" align="center">
+<a
+href="http://llvm.org/svn/llvm-project/polly"
+>http://llvm.org/svn/llvm-project/polly</a>
+</td><td> Tobias
+
+</td></tr>
+<tr>
+<th align="left"> Git mirror
+</th><td class="done" align="center">
+git://llvm.org/git/polly.git
+</td><td> Tobias
+</td></tr>
+<tr>
+<th align="left"> Commit mails
+</th><td class="done" align="center">
+llvm-commits@cs.uiuc.edu
+</td><td> Tobias
+</td></tr>
+<tr>
+
+<th align="left"> LLVM Bugzilla category
+</th><td class="done" align="center">
+<a href="http://llvm.org/bugs/enter_bug.cgi?product=Projects">LLVM Bugzilla</a>
+<br />
+(Product is 'Projects', Component is 'Polly')
+</td><td> Tobias
+<tr>
+<th align="left"> Website
+</th><td class="done" align="center">
+<a href="http://polly.llvm.org">http://polly.llvm.org</a>
+</td><td> Tobias
+</td></tr>
+<tr>
+<th align="left">Buildbot that runs 'make polly-test'
+</th><td class="done" align="center">
+<a href="http://lab.llvm.org:8011/console">Buildbot</a>
+</td>
+<td> Tobias, Andreas
+</td></tr>
+</th><td>
+
+</td></tr>
+</tbody></table>
+<h3 id="phase2"> Phase 2 - First Optimizations and Enhanced User Experience (Finished
+February 2012)</h3>
+<p>
+
+First optimizations to show the usefullness of Polly and enhance the user
+experience. We also try to increase the amount of code we can optimize.
+</p>
+<table class="wikitable" cellpadding="2">
+
+<tbody>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Frontend </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<tr>
+<th align="left"> Allow parameters in access functions
+</th><td align="center" class='done'> Done
+</td><td> Tobias
+</td></tr>
+
+<tr>
+<th align="left"> Improved Scalar Evolution parsing
+</th><td align="center" class='done'> Done
+</td><td> Tobias
+</td></tr>
+<tr>
+<th align="left"> (Graphical) user feedback on Scop Detection
+</th><td align="center" class='done'> Done
+</td><td> Tobias
+</td></tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Optimizer </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Dependency Analysis
+</th><td class="done" align="center"> Done
+</td><td> Tobias
+</td></tr>
+<tr>
+<tr>
+<th align="left"> Optimizer - Connect Pluto (through PoCC)
+</th><td class="done" align="center"> Done
+</td><td> Tobias
+</td></tr>
+<tr>
+<tr>
+<th align="left"> Optimizer - Add ISL internal Pluto like optimizer
+</th><td class="done" align="center"> Done
+</td><td> Tobias
+</td></tr>
+
+<tr>
+<th align="left"> Import/Export - SCoPLib 0.2 (needed for PoCC)
+</th><td class="done" align="center">Done
+
+</td><td> Tobias
+</td></tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Back End</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left">SIMD code generation for trivially vectorizable loops
+</th><td class="done">Done
+</td><td>Tobias
+</td></tr>
+<tr>
+<th align="left">OpenMP code generation
+</th><td class="done">Done
+</td><td> Raghesh, Tobias
+
+</td></tr>
+<tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> General</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> clang integration
+</th><td class="done" align="center"> done
+
+</td><td> Tobias
+</td></tr>
+<tr>
+<th align="left"> Commit RegionPass patch upstream
+</th><td class="done" align="center"> done
+
+</td><td> Tobias
+</td></tr>
+<tr>
+</tbody></table>
+<h3 id="phase1">Phase 1 - Get Something Working (Finished October 2010)</h3>
+<p>Create a minimal version of Polly that can transform an LLVM-IR program to
+the polyhedral model and back to LLVM-IR. No transformations are performed.
+</p>
+<table class="wikitable" cellpadding="2">
+
+<tbody>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Front End</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+
+<th align="left"> Region detection
+</td><td class="done"> Done
+</td><td>Ether
+</td></tr>
+<tr>
+<th align="left"> Access Functions
+</td><td class="done"> Done
+</td><td>John, Ether
+</td></tr>
+<tr>
+<th align="left"> Alias sets
+</td><td class="done"> Done
+</td><td>Ether
+</td></tr>
+<tr>
+<th align="left"> Scalar evolution to affine expression
+</td><td class="done"> Done
+
+</td><td>
+Ether
+</td></tr>
+<tr>
+<th align="left"> SCoP extraction
+</td><td class="done"> Done
+</td><td>Tobias, Ether
+
+</td></tr>
+<tr>
+<th align="left"> SCoPs to polyhedral model
+</td><td class="done"> Done
+</td><td>Tobias, Ether
+</td></tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Optimizer </th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Define polyhedral description
+</td><td class="done"> Done
+</td><td>Tobias
+
+</td></tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> Back End</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Create LLVM-IR using CLooG
+</td><td class="done"> Done
+</td><td> Tobias
+
+</td></tr>
+<tr><td colspan='4'>&nbsp;</td></tr>
+<tr><th colspan="3" style="background: rgb(239, 239, 239);"> General</th></tr>
+<tr style="background: rgb(239, 239, 239)">
+  <th width="400px"> Task </th>
+  <th width="150px"> Status </th>
+  <th> Owner </th>
+</tr>
+<tr>
+<th align="left"> Setup git repositories
+
+</td><td class="done"> Done
+</td><td> Tobias
+</td></tr>
+<tr>
+<th align="left"> Add CLooG/isl to build system
+</td><td class="done"> Done
+</td><td> Tobias
+
+</td></tr>
+
+</tbody></table>
+</div>
+</div>
+</body>
+</html>
diff --git a/final/www/video-js/video-js.css b/final/www/video-js/video-js.css
new file mode 100644
index 0000000..c9c4823
--- /dev/null
+++ b/final/www/video-js/video-js.css
@@ -0,0 +1,242 @@
+/* 
+VideoJS Default Styles (http://videojs.com)
+Version 2.0.2
+
+REQUIRED STYLES (be careful overriding)
+================================================================================ */
+/* Box containing video, controls, and download links.
+   Will be set to the width of the video element through JS
+   If you want to add some kind of frame or special positioning, use another containing element, not video-js-box. */
+.video-js-box { text-align: left; position: relative; line-height: 0 !important; margin: 0; padding: 0 !important; border: none !important;  }
+
+/* Video Element */
+video.video-js { background-color: #000; position: relative; padding: 0; }
+
+.vjs-flash-fallback { display: block; }
+
+/* Poster Overlay Style */
+.video-js-box img.vjs-poster { display: block; position: absolute; left: 0; top: 0; width: 100%; height: 100%; margin: 0; padding: 0; cursor: pointer; }
+/* Subtiles Style */
+.video-js-box .vjs-subtitles { color: #fff; font-size: 20px; text-align: center; position: absolute; bottom: 40px; left: 0; right: 0; }
+
+/* Fullscreen styles for main elements */
+.video-js-box.vjs-fullscreen { position: fixed; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: 1000; }
+.video-js-box.vjs-fullscreen video.video-js,
+.video-js-box.vjs-fullscreen .vjs-flash-fallback { position: relative; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000; }
+.video-js-box.vjs-fullscreen img.vjs-poster { z-index: 1001; }
+.video-js-box.vjs-fullscreen .vjs-spinner { z-index: 1001; }
+.video-js-box.vjs-fullscreen .vjs-controls { z-index: 1003; }
+.video-js-box.vjs-fullscreen .vjs-big-play-button { z-index: 1004; }
+.video-js-box.vjs-fullscreen .vjs-subtitles { z-index: 1004; }
+
+/* Styles Loaded Check */
+.vjs-styles-check { height: 5px; position: absolute; }
+/* Controls Below Video */
+.video-js-box.vjs-controls-below .vjs-controls { position: relative; opacity: 1; background-color: #000; }
+.video-js-box.vjs-controls-below .vjs-subtitles { bottom: 75px; } /* Account for height of controls below video */
+
+/* DEFAULT SKIN (override in another file)
+================================================================================
+Using all CSS to draw the controls. Images could be used if desired.
+Instead of editing this file, I recommend creating your own skin CSS file to be included after this file,
+so you can upgrade to newer versions easier. */
+
+/* Controls Layout 
+  Using absolute positioning to position controls */
+.video-js-box .vjs-controls {
+  position: absolute; margin: 0; opacity: 0.85; color: #fff;
+  display: none; /* Start hidden */
+  left: 0; right: 0; /* 100% width of video-js-box */ 
+  width: 100%;
+  bottom: 0px; /* Distance from the bottom of the box/video. Keep 0. Use height to add more bottom margin. */
+  height: 35px; /* Including any margin you want above or below control items */
+  padding: 0; /* Controls are absolutely position, so no padding necessary */
+}
+
+.video-js-box .vjs-controls > div { /* Direct div children of control bar */
+  position: absolute; /* Use top, bottom, left, and right to specifically position the control. */
+  text-align: center; margin: 0; padding: 0;
+  height: 25px; /* Default height of individual controls */
+  top: 5px; /* Top margin to put space between video and controls when controls are below */
+
+  /* CSS Background Gradients 
+     Using to give the aqua-ish look. */
+  /* Default */ background-color: #0B151A;
+  /* Webkit  */ background: #1F3744 -webkit-gradient(linear, left top, left bottom, from(#0B151A), to(#1F3744)) left 12px;
+  /* Firefox */ background: #1F3744 -moz-linear-gradient(top,  #0B151A,  #1F3744) left 12px;
+
+  /* CSS Curved Corners */
+  border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px;
+
+  /* CSS Shadows */
+  box-shadow: 1px 1px 2px #000; -webkit-box-shadow: 1px 1px 2px #000; -moz-box-shadow: 1px 1px 2px #000;
+}
+
+/* Placement of Control Items 
+   - Left side of pogress bar, use left & width
+   - Rigth side of progress bar, use right & width
+   - Expand with the video (like progress bar) use left & right */
+.vjs-controls > div.vjs-play-control       { left: 5px;   width: 25px;  }
+.vjs-controls > div.vjs-progress-control   { left: 35px;  right: 165px; } /* Using left & right so it expands with the width of the video */
+.vjs-controls > div.vjs-time-control       { width: 75px; right: 90px;  } /* Time control and progress bar are combined to look like one */
+.vjs-controls > div.vjs-volume-control     { width: 50px; right: 35px;  }
+.vjs-controls > div.vjs-fullscreen-control { width: 25px; right: 5px;   }
+
+/* Removing curved corners on progress control and time control to join them. */
+.vjs-controls > div.vjs-progress-control {
+  border-top-right-radius: 0; -webkit-border-top-right-radius: 0; -moz-border-radius-topright: 0;
+  border-bottom-right-radius: 0; -webkit-border-bottom-right-radius: 0; -moz-border-radius-bottomright: 0;
+}
+.vjs-controls > div.vjs-time-control { 
+  border-top-left-radius: 0; -webkit-border-top-left-radius: 0; -moz-border-radius-topleft: 0;
+  border-bottom-left-radius: 0; -webkit-border-bottom-left-radius: 0; -moz-border-radius-bottomleft: 0;
+}
+
+/* Play/Pause
+-------------------------------------------------------------------------------- */
+.vjs-play-control { cursor: pointer !important; }
+/* Play Icon */
+.vjs-play-control span { display: block; font-size: 0; line-height: 0; }
+.vjs-paused .vjs-play-control span {
+  width: 0; height: 0; margin: 8px 0 0 8px;
+  /* Drawing the play triangle with borders - http://www.infimum.dk/HTML/slantinfo.html */
+  border-left: 10px solid #fff; /* Width & Color of play icon */
+  /* Height of play icon is total top & bottom border widths. Color is transparent. */
+  border-top: 5px solid rgba(0,0,0,0); border-bottom: 5px solid rgba(0,0,0,0);
+}
+.vjs-playing .vjs-play-control span {
+  width: 3px; height: 10px; margin: 8px auto 0;
+  /* Drawing the pause bars with borders */
+  border-top: 0px; border-left: 3px solid #fff; border-bottom: 0px; border-right: 3px solid #fff;
+}
+
+/* Progress
+-------------------------------------------------------------------------------- */
+.vjs-progress-holder { /* Box containing play and load progresses */
+  position: relative; padding: 0; overflow:hidden; cursor: pointer !important;
+  height: 9px; border: 1px solid #777;
+  margin: 7px 1px 0 5px; /* Placement within the progress control item */
+  border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px;
+}
+.vjs-progress-holder div { /* Progress Bars */
+  position: absolute; display: block; width: 0; height: 9px; margin: 0; padding: 0;
+  border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px;
+}
+.vjs-play-progress {
+  /* CSS Gradient */
+  /* Default */ background: #fff;
+  /* Webkit  */ background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#777));
+  /* Firefox */ background: -moz-linear-gradient(top,  #fff,  #777);
+}
+.vjs-load-progress {
+  opacity: 0.8;
+  /* CSS Gradient */
+  /* Default */ background-color: #555;
+  /* Webkit  */ background: -webkit-gradient(linear, left top, left bottom, from(#555), to(#aaa));
+  /* Firefox */ background: -moz-linear-gradient(top,  #555,  #aaa);
+}
+
+/* Time Display
+-------------------------------------------------------------------------------- */
+.vjs-controls .vjs-time-control { font-size: 10px; line-height: 1; font-weight: normal; font-family: Helvetica, Arial, sans-serif; }
+.vjs-controls .vjs-time-control span { line-height: 25px; /* Centering vertically */ }
+
+/* Volume
+-------------------------------------------------------------------------------- */
+.vjs-volume-control { cursor: pointer !important; }
+.vjs-volume-control div { display: block; margin: 0 5px 0 5px; padding: 4px 0 0 0; }
+/* Drawing the volume icon using 6 span elements */
+.vjs-volume-control div span { /* Individual volume bars */
+  float: left; padding: 0;
+  margin: 0 2px 0 0; /* Space between */
+  width: 5px; height: 0px; /* Total height is height + bottom border */
+  border-bottom: 18px solid #555; /* Default (off) color and height of visible portion */
+}
+.vjs-volume-control div span.vjs-volume-level-on { border-color: #fff; /* Volume on bar color */ }
+/* Creating differnt bar heights through height (transparent) and bottom border (visible). */
+.vjs-volume-control div span:nth-child(1) { border-bottom-width: 2px; height: 16px; }
+.vjs-volume-control div span:nth-child(2) { border-bottom-width: 4px; height: 14px; }
+.vjs-volume-control div span:nth-child(3) { border-bottom-width: 7px; height: 11px; }
+.vjs-volume-control div span:nth-child(4) { border-bottom-width: 10px; height: 8px; }
+.vjs-volume-control div span:nth-child(5) { border-bottom-width: 14px; height: 4px; }
+.vjs-volume-control div span:nth-child(6) { margin-right: 0; }
+
+/* Fullscreen
+-------------------------------------------------------------------------------- */
+.vjs-fullscreen-control { cursor: pointer !important; }
+.vjs-fullscreen-control div {
+  padding: 0; text-align: left; vertical-align: top; cursor: pointer !important; 
+  margin: 5px 0 0 5px; /* Placement within the fullscreen control item */
+  width: 20px; height: 20px;
+}
+/* Drawing the fullscreen icon using 4 span elements */
+.vjs-fullscreen-control div span { float: left; margin: 0; padding: 0; font-size: 0; line-height: 0; width: 0; text-align: left; vertical-align: top; }
+.vjs-fullscreen-control div span:nth-child(1) { /* Top-left triangle */
+  margin-right: 3px; /* Space between top-left and top-right */
+  margin-bottom: 3px; /* Space between top-left and bottom-left */
+  border-top: 6px solid #fff; /* Height and color */
+  border-right: 6px solid rgba(0,0,0,0);  /* Width */
+}
+.vjs-fullscreen-control div span:nth-child(2) { border-top: 6px solid #fff; border-left: 6px solid rgba(0,0,0,0); }
+.vjs-fullscreen-control div span:nth-child(3) { clear: both; margin: 0 3px 0 0; border-bottom: 6px solid #fff; border-right: 6px solid rgba(0,0,0,0); }
+.vjs-fullscreen-control div span:nth-child(4) { border-bottom: 6px solid #fff; border-left: 6px solid rgba(0,0,0,0); }
+/* Icon when video is in fullscreen mode */
+.vjs-fullscreen .vjs-fullscreen-control div span:nth-child(1) { border: none; border-bottom: 6px solid #fff; border-left: 6px solid rgba(0,0,0,0); }
+.vjs-fullscreen .vjs-fullscreen-control div span:nth-child(2) { border: none; border-bottom: 6px solid #fff; border-right: 6px solid rgba(0,0,0,0); }
+.vjs-fullscreen .vjs-fullscreen-control div span:nth-child(3) { border: none; border-top: 6px solid #fff; border-left: 6px solid rgba(0,0,0,0); }
+.vjs-fullscreen .vjs-fullscreen-control div span:nth-child(4) { border: none; border-top: 6px solid #fff; border-right: 6px solid rgba(0,0,0,0); }
+
+/* Download Links - Used for browsers that don't support any video.
+---------------------------------------------------------*/
+.vjs-no-video { font-size: small; line-height: 1.5; }
+
+/* Big Play Button (at start)
+---------------------------------------------------------*/
+div.vjs-big-play-button {
+  display: none; /* Start hidden */ z-index: 2;
+  position: absolute; top: 50%; left: 50%; width: 80px; height: 80px; margin: -43px 0 0 -43px; text-align: center; vertical-align: center; cursor: pointer !important;
+  border: 3px solid #fff; opacity: 0.9;
+  border-radius: 20px; -webkit-border-radius: 20px; -moz-border-radius: 20px;
+  
+  /* CSS Background Gradients */
+  /* Default */ background-color: #0B151A;
+  /* Webkit  */ background: #1F3744 -webkit-gradient(linear, left top, left bottom, from(#0B151A), to(#1F3744)) left 40px;
+  /* Firefox */ background: #1F3744 -moz-linear-gradient(top,  #0B151A,  #1F3744) left 40px;
+
+  /* CSS Shadows */
+  box-shadow: 4px 4px 8px #000; -webkit-box-shadow: 4px 4px 8px #000; -moz-box-shadow: 4px 4px 8px #000;
+}
+div.vjs-big-play-button:hover {
+  box-shadow: 0px 0px 80px #fff; -webkit-box-shadow: 0px 0px 80px #fff; -moz-box-shadow: 0px 0px 80px #fff;
+}
+
+div.vjs-big-play-button span {
+  display: block; font-size: 0; line-height: 0;
+  width: 0; height: 0; margin: 20px 0 0 23px;
+  /* Drawing the play triangle with borders - http://www.infimum.dk/HTML/slantinfo.html */
+  border-left: 40px solid #fff; /* Width & Color of play icon */
+  /* Height of play icon is total top & bottom border widths. Color is transparent. */
+  border-top: 20px solid rgba(0,0,0,0); border-bottom: 20px solid rgba(0,0,0,0);
+}
+
+/* Spinner Styles
+---------------------------------------------------------*/
+/* CSS Spinners by Kilian Valkhof - http://kilianvalkhof.com/2010/css-xhtml/css3-loading-spinners-without-images/ */
+.vjs-spinner { display: none; position: absolute; top: 50%; left: 50%; width: 100px; height: 100px; z-index: 1; margin: -50px 0 0 -50px;
+  /* Scaling makes the circles look smoother. */
+  transform: scale(0.5); -webkit-transform:scale(0.5); -moz-transform:scale(0.5);
+}
+/* Spinner circles */
+.vjs-spinner div { position:absolute; left: 40px; top: 40px; width: 20px; height: 20px; background: #fff;
+  border-radius: 20px; -webkit-border-radius: 20px; -moz-border-radius: 20px;
+  border: 1px solid #ccc; /* Added border so can be visible on white backgrounds */
+}
+/* Each circle */
+.vjs-spinner div:nth-child(1) { opacity: 0.12; transform: rotate(000deg) translate(0, -40px) scale(0.1); -webkit-transform: rotate(000deg) translate(0, -40px) scale(0.1); -moz-transform: rotate(000deg) translate(0, -40px) scale(0.1); }
+.vjs-spinner div:nth-child(2) { opacity: 0.25; transform: rotate(045deg) translate(0, -40px) scale(0.2); -webkit-transform: rotate(045deg) translate(0, -40px) scale(0.2); -moz-transform: rotate(045deg) translate(0, -40px) scale(0.2); }
+.vjs-spinner div:nth-child(3) { opacity: 0.37; transform: rotate(090deg) translate(0, -40px) scale(0.4); -webkit-transform: rotate(090deg) translate(0, -40px) scale(0.4); -moz-transform: rotate(090deg) translate(0, -40px) scale(0.4); }
+.vjs-spinner div:nth-child(4) { opacity: 0.50; transform: rotate(135deg) translate(0, -40px) scale(0.6); -webkit-transform: rotate(135deg) translate(0, -40px) scale(0.6); -moz-transform: rotate(135deg) translate(0, -40px) scale(0.6); }
+.vjs-spinner div:nth-child(5) { opacity: 0.62; transform: rotate(180deg) translate(0, -40px) scale(0.8); -webkit-transform: rotate(180deg) translate(0, -40px) scale(0.8); -moz-transform: rotate(180deg) translate(0, -40px) scale(0.8); }
+.vjs-spinner div:nth-child(6) { opacity: 0.75; transform: rotate(225deg) translate(0, -40px) scale(1.0); -webkit-transform: rotate(225deg) translate(0, -40px) scale(1.0); -moz-transform: rotate(225deg) translate(0, -40px) scale(1.0); }
+.vjs-spinner div:nth-child(7) { opacity: 0.87; transform: rotate(270deg) translate(0, -40px) scale(1.1); -webkit-transform: rotate(270deg) translate(0, -40px) scale(1.1); -moz-transform: rotate(270deg) translate(0, -40px) scale(1.1); }
+.vjs-spinner div:nth-child(8) { opacity: 1.00; transform: rotate(315deg) translate(0, -40px) scale(1.3); -webkit-transform: rotate(315deg) translate(0, -40px) scale(1.3); -moz-transform: rotate(315deg) translate(0, -40px) scale(1.3); }
\ No newline at end of file
diff --git a/final/www/video-js/video.js b/final/www/video-js/video.js
new file mode 100644
index 0000000..9571eeb
--- /dev/null
+++ b/final/www/video-js/video.js
@@ -0,0 +1,1758 @@
+/*
+VideoJS - HTML5 Video Player
+v2.0.2
+
+This file is part of VideoJS. Copyright 2010 Zencoder, Inc.
+
+VideoJS is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+VideoJS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with VideoJS.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// Self-executing function to prevent global vars and help with minification
+(function(window, undefined){
+  var document = window.document;
+
+// Using jresig's Class implementation http://ejohn.org/blog/simple-javascript-inheritance/
+(function(){var initializing=false, fnTest=/xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; this.JRClass = function(){}; JRClass.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function JRClass() { if ( !initializing && this.init ) this.init.apply(this, arguments); } JRClass.prototype = prototype; JRClass.constructor = JRClass; JRClass.extend = arguments.callee; return JRClass;};})();
+
+// Video JS Player Class
+var VideoJS = JRClass.extend({
+
+  // Initialize the player for the supplied video tag element
+  // element: video tag
+  init: function(element, setOptions){
+
+    // Allow an ID string or an element
+    if (typeof element == 'string') {
+      this.video = document.getElementById(element);
+    } else {
+      this.video = element;
+    }
+    // Store reference to player on the video element.
+    // So you can access the player later: document.getElementById("video_id").player.play();
+    this.video.player = this;
+    this.values = {}; // Cache video values.
+    this.elements = {}; // Store refs to controls elements.
+
+    // Default Options
+    this.options = {
+      autoplay: false,
+      preload: true,
+      useBuiltInControls: false, // Use the browser's controls (iPhone)
+      controlsBelow: false, // Display control bar below video vs. in front of
+      controlsAtStart: false, // Make controls visible when page loads
+      controlsHiding: true, // Hide controls when not over the video
+      defaultVolume: 0.85, // Will be overridden by localStorage volume if available
+      playerFallbackOrder: ["html5", "flash", "links"], // Players and order to use them
+      flashPlayer: "htmlObject",
+      flashPlayerVersion: false // Required flash version for fallback
+    };
+    // Override default options with global options
+    if (typeof VideoJS.options == "object") { _V_.merge(this.options, VideoJS.options); }
+    // Override default & global options with options specific to this player
+    if (typeof setOptions == "object") { _V_.merge(this.options, setOptions); }
+    // Override preload & autoplay with video attributes
+    if (this.getPreloadAttribute() !== undefined) { this.options.preload = this.getPreloadAttribute(); }
+    if (this.getAutoplayAttribute() !== undefined) { this.options.autoplay = this.getAutoplayAttribute(); }
+
+    // Store reference to embed code pieces
+    this.box = this.video.parentNode;
+    this.linksFallback = this.getLinksFallback();
+    this.hideLinksFallback(); // Will be shown again if "links" player is used
+
+    // Loop through the player names list in options, "html5" etc.
+    // For each player name, initialize the player with that name under VideoJS.players
+    // If the player successfully initializes, we're done
+    // If not, try the next player in the list
+    this.each(this.options.playerFallbackOrder, function(playerType){
+      if (this[playerType+"Supported"]()) { // Check if player type is supported
+        this[playerType+"Init"](); // Initialize player type
+        return true; // Stop looping though players
+      }
+    });
+
+    // Start Global Listeners - API doesn't exist before now
+    this.activateElement(this, "player");
+    this.activateElement(this.box, "box");
+  },
+  /* Behaviors
+  ================================================================================ */
+  behaviors: {},
+  newBehavior: function(name, activate, functions){
+    this.behaviors[name] = activate;
+    this.extend(functions);
+  },
+  activateElement: function(element, behavior){
+    // Allow passing and ID string
+    if (typeof element == "string") { element = document.getElementById(element); }
+    this.behaviors[behavior].call(this, element);
+  },
+  /* Errors/Warnings
+  ================================================================================ */
+  errors: [], // Array to track errors
+  warnings: [],
+  warning: function(warning){
+    this.warnings.push(warning);
+    this.log(warning);
+  },
+  /* History of errors/events (not quite there yet)
+  ================================================================================ */
+  history: [],
+  log: function(event){
+    if (!event) { return; }
+    if (typeof event == "string") { event = { type: event }; }
+    if (event.type) { this.history.push(event.type); }
+    if (this.history.length >= 50) { this.history.shift(); }
+    try { console.log(event.type); } catch(e) { try { opera.postError(event.type); } catch(e){} }
+  },
+  /* Local Storage
+  ================================================================================ */
+  setLocalStorage: function(key, value){
+    if (!localStorage) { return; }
+    try {
+      localStorage[key] = value;
+    } catch(e) {
+      if (e.code == 22 || e.code == 1014) { // Webkit == 22 / Firefox == 1014
+        this.warning(VideoJS.warnings.localStorageFull);
+      }
+    }
+  },
+  /* Helpers
+  ================================================================================ */
+  getPreloadAttribute: function(){
+    if (typeof this.video.hasAttribute == "function" && this.video.hasAttribute("preload")) {
+      var preload = this.video.getAttribute("preload");
+      // Only included the attribute, thinking it was boolean
+      if (preload === "" || preload === "true") { return "auto"; }
+      if (preload === "false") { return "none"; }
+      return preload;
+    }
+  },
+  getAutoplayAttribute: function(){
+    if (typeof this.video.hasAttribute == "function" && this.video.hasAttribute("autoplay")) {
+      var autoplay = this.video.getAttribute("autoplay");
+      if (autoplay === "false") { return false; }
+      return true;
+    }
+  },
+  // Calculates amoutn of buffer is full
+  bufferedPercent: function(){ return (this.duration()) ? this.buffered()[1] / this.duration() : 0; },
+  // Each that maintains player as context
+  // Break if true is returned
+  each: function(arr, fn){
+    if (!arr || arr.length === 0) { return; }
+    for (var i=0,j=arr.length; i<j; i++) {
+      if (fn.call(this, arr[i], i)) { break; }
+    }
+  },
+  extend: function(obj){
+    for (var attrname in obj) {
+      if (obj.hasOwnProperty(attrname)) { this[attrname]=obj[attrname]; }
+    }
+  }
+});
+VideoJS.player = VideoJS.prototype;
+
+////////////////////////////////////////////////////////////////////////////////
+// Player Types
+////////////////////////////////////////////////////////////////////////////////
+
+/* Flash Object Fallback (Player Type)
+================================================================================ */
+VideoJS.player.extend({
+  flashSupported: function(){
+    if (!this.flashElement) { this.flashElement = this.getFlashElement(); }
+    // Check if object exists & Flash Player version is supported
+    if (this.flashElement && this.flashPlayerVersionSupported()) {
+      return true;
+    } else {
+      return false;
+    }
+  },
+  flashInit: function(){
+    this.replaceWithFlash();
+    this.element = this.flashElement;
+    this.video.src = ""; // Stop video from downloading if HTML5 is still supported
+    var flashPlayerType = VideoJS.flashPlayers[this.options.flashPlayer];
+    this.extend(VideoJS.flashPlayers[this.options.flashPlayer].api);
+    (flashPlayerType.init.context(this))();
+  },
+  // Get Flash Fallback object element from Embed Code
+  getFlashElement: function(){
+    var children = this.video.children;
+    for (var i=0,j=children.length; i<j; i++) {
+      if (children[i].className == "vjs-flash-fallback") {
+        return children[i];
+      }
+    }
+  },
+  // Used to force a browser to fall back when it's an HTML5 browser but there's no supported sources
+  replaceWithFlash: function(){
+    // this.flashElement = this.video.removeChild(this.flashElement);
+    if (this.flashElement) {
+      this.box.insertBefore(this.flashElement, this.video);
+      this.video.style.display = "none"; // Removing it was breaking later players
+    }
+  },
+  // Check if browser can use this flash player
+  flashPlayerVersionSupported: function(){
+    var playerVersion = (this.options.flashPlayerVersion) ? this.options.flashPlayerVersion : VideoJS.flashPlayers[this.options.flashPlayer].flashPlayerVersion;
+    return VideoJS.getFlashVersion() >= playerVersion;
+  }
+});
+VideoJS.flashPlayers = {};
+VideoJS.flashPlayers.htmlObject = {
+  flashPlayerVersion: 9,
+  init: function() { return true; },
+  api: { // No video API available with HTML Object embed method
+    width: function(width){
+      if (width !== undefined) {
+        this.element.width = width;
+        this.box.style.width = width+"px";
+        this.triggerResizeListeners();
+        return this;
+      }
+      return this.element.width;
+    },
+    height: function(height){
+      if (height !== undefined) {
+        this.element.height = height;
+        this.box.style.height = height+"px";
+        this.triggerResizeListeners();
+        return this;
+      }
+      return this.element.height;
+    }
+  }
+};
+
+
+/* Download Links Fallback (Player Type)
+================================================================================ */
+VideoJS.player.extend({
+  linksSupported: function(){ return true; },
+  linksInit: function(){
+    this.showLinksFallback();
+    this.element = this.video;
+  },
+  // Get the download links block element
+  getLinksFallback: function(){ return this.box.getElementsByTagName("P")[0]; },
+  // Hide no-video download paragraph
+  hideLinksFallback: function(){
+    if (this.linksFallback) { this.linksFallback.style.display = "none"; }
+  },
+  // Hide no-video download paragraph
+  showLinksFallback: function(){
+    if (this.linksFallback) { this.linksFallback.style.display = "block"; }
+  }
+});
+
+////////////////////////////////////////////////////////////////////////////////
+// Class Methods
+// Functions that don't apply to individual videos.
+////////////////////////////////////////////////////////////////////////////////
+
+// Combine Objects - Use "safe" to protect from overwriting existing items
+VideoJS.merge = function(obj1, obj2, safe){
+  for (var attrname in obj2){
+    if (obj2.hasOwnProperty(attrname) && (!safe || !obj1.hasOwnProperty(attrname))) { obj1[attrname]=obj2[attrname]; }
+  }
+  return obj1;
+};
+VideoJS.extend = function(obj){ this.merge(this, obj, true); };
+
+VideoJS.extend({
+  // Add VideoJS to all video tags with the video-js class when the DOM is ready
+  setupAllWhenReady: function(options){
+    // Options is stored globally, and added ot any new player on init
+    VideoJS.options = options;
+    VideoJS.DOMReady(VideoJS.setup);
+  },
+
+  // Run the supplied function when the DOM is ready
+  DOMReady: function(fn){
+    VideoJS.addToDOMReady(fn);
+  },
+
+  // Set up a specific video or array of video elements
+  // "video" can be:
+  //    false, undefined, or "All": set up all videos with the video-js class
+  //    A video tag ID or video tag element: set up one video and return one player
+  //    An array of video tag elements/IDs: set up each and return an array of players
+  setup: function(videos, options){
+    var returnSingular = false,
+    playerList = [],
+    videoElement;
+
+    // If videos is undefined or "All", set up all videos with the video-js class
+    if (!videos || videos == "All") {
+      videos = VideoJS.getVideoJSTags();
+    // If videos is not an array, add to an array
+    } else if (typeof videos != 'object' || videos.nodeType == 1) {
+      videos = [videos];
+      returnSingular = true;
+    }
+
+    // Loop through videos and create players for them
+    for (var i=0; i<videos.length; i++) {
+      if (typeof videos[i] == 'string') {
+        videoElement = document.getElementById(videos[i]);
+      } else { // assume DOM object
+        videoElement = videos[i];
+      }
+      playerList.push(new VideoJS(videoElement, options));
+    }
+
+    // Return one or all depending on what was passed in
+    return (returnSingular) ? playerList[0] : playerList;
+  },
+
+  // Find video tags with the video-js class
+  getVideoJSTags: function() {
+    var videoTags = document.getElementsByTagName("video"),
+    videoJSTags = [], videoTag;
+
+    for (var i=0,j=videoTags.length; i<j; i++) {
+      videoTag = videoTags[i];
+      if (videoTag.className.indexOf("video-js") != -1) {
+        videoJSTags.push(videoTag);
+      }
+    }
+    return videoJSTags;
+  },
+
+  // Check if the browser supports video.
+  browserSupportsVideo: function() {
+    if (typeof VideoJS.videoSupport != "undefined") { return VideoJS.videoSupport; }
+    VideoJS.videoSupport = !!document.createElement('video').canPlayType;
+    return VideoJS.videoSupport;
+  },
+
+  getFlashVersion: function(){
+    // Cache Version
+    if (typeof VideoJS.flashVersion != "undefined") { return VideoJS.flashVersion; }
+    var version = 0, desc;
+    if (typeof navigator.plugins != "undefined" && typeof navigator.plugins["Shockwave Flash"] == "object") {
+      desc = navigator.plugins["Shockwave Flash"].description;
+      if (desc && !(typeof navigator.mimeTypes != "undefined" && navigator.mimeTypes["application/x-shockwave-flash"] && !navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)) {
+        version = parseInt(desc.match(/^.*\s+([^\s]+)\.[^\s]+\s+[^\s]+$/)[1], 10);
+      }
+    } else if (typeof window.ActiveXObject != "undefined") {
+      try {
+        var testObject = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+        if (testObject) {
+          version = parseInt(testObject.GetVariable("$version").match(/^[^\s]+\s(\d+)/)[1], 10);
+        }
+      }
+      catch(e) {}
+    }
+    VideoJS.flashVersion = version;
+    return VideoJS.flashVersion;
+  },
+
+  // Browser & Device Checks
+  isIE: function(){ return !+"\v1"; },
+  isIPad: function(){ return navigator.userAgent.match(/iPad/i) !== null; },
+  isIPhone: function(){ return navigator.userAgent.match(/iPhone/i) !== null; },
+  isIOS: function(){ return VideoJS.isIPhone() || VideoJS.isIPad(); },
+  iOSVersion: function() {
+    var match = navigator.userAgent.match(/OS (\d+)_/i);
+    if (match && match[1]) { return match[1]; }
+  },
+  isAndroid: function(){ return navigator.userAgent.match(/Android/i) !== null; },
+  androidVersion: function() {
+    var match = navigator.userAgent.match(/Android (\d+)\./i);
+    if (match && match[1]) { return match[1]; }
+  },
+
+  warnings: {
+    // Safari errors if you call functions on a video that hasn't loaded yet
+    videoNotReady: "Video is not ready yet (try playing the video first).",
+    // Getting a QUOTA_EXCEEDED_ERR when setting local storage occasionally
+    localStorageFull: "Local Storage is Full"
+  }
+});
+
+// Shim to make Video tag valid in IE
+if(VideoJS.isIE()) { document.createElement("video"); }
+
+// Expose to global
+window.VideoJS = window._V_ = VideoJS;
+
+/* HTML5 Player Type
+================================================================================ */
+VideoJS.player.extend({
+  html5Supported: function(){
+    if (VideoJS.browserSupportsVideo() && this.canPlaySource()) {
+      return true;
+    } else {
+      return false;
+    }
+  },
+  html5Init: function(){
+    this.element = this.video;
+
+    this.fixPreloading(); // Support old browsers that used autobuffer
+    this.supportProgressEvents(); // Support browsers that don't use 'buffered'
+
+    // Set to stored volume OR 85%
+    this.volume((localStorage && localStorage.volume) || this.options.defaultVolume);
+
+    // Update interface for device needs
+    if (VideoJS.isIOS()) {
+      this.options.useBuiltInControls = true;
+      this.iOSInterface();
+    } else if (VideoJS.isAndroid()) {
+      this.options.useBuiltInControls = true;
+      this.androidInterface();
+    }
+
+    // Add VideoJS Controls
+    if (!this.options.useBuiltInControls) {
+      this.video.controls = false;
+
+      if (this.options.controlsBelow) { _V_.addClass(this.box, "vjs-controls-below"); }
+
+      // Make a click on th video act as a play button
+      this.activateElement(this.video, "playToggle");
+
+      // Build Interface
+      this.buildStylesCheckDiv(); // Used to check if style are loaded
+      this.buildAndActivatePoster();
+      this.buildBigPlayButton();
+      this.buildAndActivateSpinner();
+      this.buildAndActivateControlBar();
+      this.loadInterface(); // Show everything once styles are loaded
+      this.getSubtitles();
+    }
+  },
+  /* Source Managemet
+  ================================================================================ */
+  canPlaySource: function(){
+    // Cache Result
+    if (this.canPlaySourceResult) { return this.canPlaySourceResult; }
+    // Loop through sources and check if any can play
+    var children = this.video.children;
+    for (var i=0,j=children.length; i<j; i++) {
+      if (children[i].tagName.toUpperCase() == "SOURCE") {
+        var canPlay = this.video.canPlayType(children[i].type) || this.canPlayExt(children[i].src);
+        if (canPlay == "probably" || canPlay == "maybe") {
+          this.firstPlayableSource = children[i];
+          this.canPlaySourceResult = true;
+          return true;
+        }
+      }
+    }
+    this.canPlaySourceResult = false;
+    return false;
+  },
+  // Check if the extension is compatible, for when type won't work
+  canPlayExt: function(src){
+    if (!src) { return ""; }
+    var match = src.match(/\.([^\.]+)$/);
+    if (match && match[1]) {
+      var ext = match[1].toLowerCase();
+      // Android canPlayType doesn't work
+      if (VideoJS.isAndroid()) {
+        if (ext == "mp4" || ext == "m4v") { return "maybe"; }
+      // Allow Apple HTTP Streaming for iOS
+      } else if (VideoJS.isIOS()) {
+        if (ext == "m3u8") { return "maybe"; }
+      }
+    }
+    return "";
+  },
+  // Force the video source - Helps fix loading bugs in a handful of devices, like the iPad/iPhone poster bug
+  // And iPad/iPhone javascript include location bug. And Android type attribute bug
+  forceTheSource: function(){
+    this.video.src = this.firstPlayableSource.src; // From canPlaySource()
+    this.video.load();
+  },
+  /* Device Fixes
+  ================================================================================ */
+  // Support older browsers that used "autobuffer"
+  fixPreloading: function(){
+    if (typeof this.video.hasAttribute == "function" && this.video.hasAttribute("preload") && this.video.preload != "none") {
+      this.video.autobuffer = true; // Was a boolean
+    } else {
+      this.video.autobuffer = false;
+      this.video.preload = "none";
+    }
+  },
+
+  // Listen for Video Load Progress (currently does not if html file is local)
+  // Buffered does't work in all browsers, so watching progress as well
+  supportProgressEvents: function(e){
+    _V_.addListener(this.video, 'progress', this.playerOnVideoProgress.context(this));
+  },
+  playerOnVideoProgress: function(event){
+    this.setBufferedFromProgress(event);
+  },
+  setBufferedFromProgress: function(event){ // HTML5 Only
+    if(event.total > 0) {
+      var newBufferEnd = (event.loaded / event.total) * this.duration();
+      if (newBufferEnd > this.values.bufferEnd) { this.values.bufferEnd = newBufferEnd; }
+    }
+  },
+
+  iOSInterface: function(){
+    if(VideoJS.iOSVersion() < 4) { this.forceTheSource(); } // Fix loading issues
+    if(VideoJS.isIPad()) { // iPad could work with controlsBelow
+      this.buildAndActivateSpinner(); // Spinner still works well on iPad, since iPad doesn't have one
+    }
+  },
+
+  // Fix android specific quirks
+  // Use built-in controls, but add the big play button, since android doesn't have one.
+  androidInterface: function(){
+    this.forceTheSource(); // Fix loading issues
+    _V_.addListener(this.video, "click", function(){ this.play(); }); // Required to play
+    this.buildBigPlayButton(); // But don't activate the normal way. Pause doesn't work right on android.
+    _V_.addListener(this.bigPlayButton, "click", function(){ this.play(); }.context(this));
+    this.positionBox();
+    this.showBigPlayButtons();
+  },
+  /* Wait for styles (TODO: move to _V_)
+  ================================================================================ */
+  loadInterface: function(){
+    if(!this.stylesHaveLoaded()) {
+      // Don't want to create an endless loop either.
+      if (!this.positionRetries) { this.positionRetries = 1; }
+      if (this.positionRetries++ < 100) {
+        setTimeout(this.loadInterface.context(this),10);
+        return;
+      }
+    }
+    this.hideStylesCheckDiv();
+    this.showPoster();
+    if (this.video.paused !== false) { this.showBigPlayButtons(); }
+    if (this.options.controlsAtStart) { this.showControlBars(); }
+    this.positionAll();
+  },
+  /* Control Bar
+  ================================================================================ */
+  buildAndActivateControlBar: function(){
+    /* Creating this HTML
+      <div class="vjs-controls">
+        <div class="vjs-play-control">
+          <span></span>
+        </div>
+        <div class="vjs-progress-control">
+          <div class="vjs-progress-holder">
+            <div class="vjs-load-progress"></div>
+            <div class="vjs-play-progress"></div>
+          </div>
+        </div>
+        <div class="vjs-time-control">
+          <span class="vjs-current-time-display">00:00</span><span> / </span><span class="vjs-duration-display">00:00</span>
+        </div>
+        <div class="vjs-volume-control">
+          <div>
+            <span></span><span></span><span></span><span></span><span></span><span></span>
+          </div>
+        </div>
+        <div class="vjs-fullscreen-control">
+          <div>
+            <span></span><span></span><span></span><span></span>
+          </div>
+        </div>
+      </div>
+    */
+
+    // Create a div to hold the different controls
+    this.controls = _V_.createElement("div", { className: "vjs-controls" });
+    // Add the controls to the video's container
+    this.box.appendChild(this.controls);
+    this.activateElement(this.controls, "controlBar");
+    this.activateElement(this.controls, "mouseOverVideoReporter");
+
+    // Build the play control
+    this.playControl = _V_.createElement("div", { className: "vjs-play-control", innerHTML: "<span></span>" });
+    this.controls.appendChild(this.playControl);
+    this.activateElement(this.playControl, "playToggle");
+
+    // Build the progress control
+    this.progressControl = _V_.createElement("div", { className: "vjs-progress-control" });
+    this.controls.appendChild(this.progressControl);
+
+    // Create a holder for the progress bars
+    this.progressHolder = _V_.createElement("div", { className: "vjs-progress-holder" });
+    this.progressControl.appendChild(this.progressHolder);
+    this.activateElement(this.progressHolder, "currentTimeScrubber");
+
+    // Create the loading progress display
+    this.loadProgressBar = _V_.createElement("div", { className: "vjs-load-progress" });
+    this.progressHolder.appendChild(this.loadProgressBar);
+    this.activateElement(this.loadProgressBar, "loadProgressBar");
+
+    // Create the playing progress display
+    this.playProgressBar = _V_.createElement("div", { className: "vjs-play-progress" });
+    this.progressHolder.appendChild(this.playProgressBar);
+    this.activateElement(this.playProgressBar, "playProgressBar");
+
+    // Create the progress time display (00:00 / 00:00)
+    this.timeControl = _V_.createElement("div", { className: "vjs-time-control" });
+    this.controls.appendChild(this.timeControl);
+
+    // Create the current play time display
+    this.currentTimeDisplay = _V_.createElement("span", { className: "vjs-current-time-display", innerHTML: "00:00" });
+    this.timeControl.appendChild(this.currentTimeDisplay);
+    this.activateElement(this.currentTimeDisplay, "currentTimeDisplay");
+
+    // Add time separator
+    this.timeSeparator = _V_.createElement("span", { innerHTML: " / " });
+    this.timeControl.appendChild(this.timeSeparator);
+
+    // Create the total duration display
+    this.durationDisplay = _V_.createElement("span", { className: "vjs-duration-display", innerHTML: "00:00" });
+    this.timeControl.appendChild(this.durationDisplay);
+    this.activateElement(this.durationDisplay, "durationDisplay");
+
+    // Create the volumne control
+    this.volumeControl = _V_.createElement("div", {
+      className: "vjs-volume-control",
+      innerHTML: "<div><span></span><span></span><span></span><span></span><span></span><span></span></div>"
+    });
+    this.controls.appendChild(this.volumeControl);
+    this.activateElement(this.volumeControl, "volumeScrubber");
+
+    this.volumeDisplay = this.volumeControl.children[0];
+    this.activateElement(this.volumeDisplay, "volumeDisplay");
+
+    // Crete the fullscreen control
+    this.fullscreenControl = _V_.createElement("div", {
+      className: "vjs-fullscreen-control",
+      innerHTML: "<div><span></span><span></span><span></span><span></span></div>"
+    });
+    this.controls.appendChild(this.fullscreenControl);
+    this.activateElement(this.fullscreenControl, "fullscreenToggle");
+  },
+  /* Poster Image
+  ================================================================================ */
+  buildAndActivatePoster: function(){
+    this.updatePosterSource();
+    if (this.video.poster) {
+      this.poster = document.createElement("img");
+      // Add poster to video box
+      this.box.appendChild(this.poster);
+
+      // Add poster image data
+      this.poster.src = this.video.poster;
+      // Add poster styles
+      this.poster.className = "vjs-poster";
+      this.activateElement(this.poster, "poster");
+    } else {
+      this.poster = false;
+    }
+  },
+  /* Big Play Button
+  ================================================================================ */
+  buildBigPlayButton: function(){
+    /* Creating this HTML
+      <div class="vjs-big-play-button"><span></span></div>
+    */
+    this.bigPlayButton = _V_.createElement("div", {
+      className: "vjs-big-play-button",
+      innerHTML: "<span></span>"
+    });
+    this.box.appendChild(this.bigPlayButton);
+    this.activateElement(this.bigPlayButton, "bigPlayButton");
+  },
+  /* Spinner (Loading)
+  ================================================================================ */
+  buildAndActivateSpinner: function(){
+    this.spinner = _V_.createElement("div", {
+      className: "vjs-spinner",
+      innerHTML: "<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>"
+    });
+    this.box.appendChild(this.spinner);
+    this.activateElement(this.spinner, "spinner");
+  },
+  /* Styles Check - Check if styles are loaded (move ot _V_)
+  ================================================================================ */
+  // Sometimes the CSS styles haven't been applied to the controls yet
+  // when we're trying to calculate the height and position them correctly.
+  // This causes a flicker where the controls are out of place.
+  buildStylesCheckDiv: function(){
+    this.stylesCheckDiv = _V_.createElement("div", { className: "vjs-styles-check" });
+    this.stylesCheckDiv.style.position = "absolute";
+    this.box.appendChild(this.stylesCheckDiv);
+  },
+  hideStylesCheckDiv: function(){ this.stylesCheckDiv.style.display = "none"; },
+  stylesHaveLoaded: function(){
+    if (this.stylesCheckDiv.offsetHeight != 5) {
+       return false;
+    } else {
+      return true;
+    }
+  },
+  /* VideoJS Box - Holds all elements
+  ================================================================================ */
+  positionAll: function(){
+    this.positionBox();
+    this.positionControlBars();
+    this.positionPoster();
+  },
+  positionBox: function(){
+    // Set width based on fullscreen or not.
+    if (this.videoIsFullScreen) {
+      this.box.style.width = "";
+      this.element.style.height="";
+      if (this.options.controlsBelow) {
+        this.box.style.height = "";
+        this.element.style.height = (this.box.offsetHeight - this.controls.offsetHeight) + "px";
+      }
+    } else {
+      this.box.style.width = this.width() + "px";
+      this.element.style.height=this.height()+"px";
+      if (this.options.controlsBelow) {
+        this.element.style.height = "";
+        // this.box.style.height = this.video.offsetHeight + this.controls.offsetHeight + "px";
+      }
+    }
+  },
+  /* Subtitles
+  ================================================================================ */
+  getSubtitles: function(){
+    var tracks = this.video.getElementsByTagName("TRACK");
+    for (var i=0,j=tracks.length; i<j; i++) {
+      if (tracks[i].getAttribute("kind") == "subtitles" && tracks[i].getAttribute("src")) {
+        this.subtitlesSource = tracks[i].getAttribute("src");
+        this.loadSubtitles();
+        this.buildSubtitles();
+      }
+    }
+  },
+  loadSubtitles: function() { _V_.get(this.subtitlesSource, this.parseSubtitles.context(this)); },
+  parseSubtitles: function(subText) {
+    var lines = subText.split("\n"),
+        line = "",
+        subtitle, time, text;
+    this.subtitles = [];
+    this.currentSubtitle = false;
+    this.lastSubtitleIndex = 0;
+
+    for (var i=0; i<lines.length; i++) {
+      line = _V_.trim(lines[i]); // Trim whitespace and linebreaks
+      if (line) { // Loop until a line with content
+
+        // First line - Number
+        subtitle = {
+          id: line, // Subtitle Number
+          index: this.subtitles.length // Position in Array
+        };
+
+        // Second line - Time
+        line = _V_.trim(lines[++i]);
+        time = line.split(" --> ");
+        subtitle.start = this.parseSubtitleTime(time[0]);
+        subtitle.end = this.parseSubtitleTime(time[1]);
+
+        // Additional lines - Subtitle Text
+        text = [];
+        for (var j=i; j<lines.length; j++) { // Loop until a blank line or end of lines
+          line = _V_.trim(lines[++i]);
+          if (!line) { break; }
+          text.push(line);
+        }
+        subtitle.text = text.join('<br/>');
+
+        // Add this subtitle
+        this.subtitles.push(subtitle);
+      }
+    }
+  },
+
+  parseSubtitleTime: function(timeText) {
+    var parts = timeText.split(':'),
+        time = 0;
+    // hours => seconds
+    time += parseFloat(parts[0])*60*60;
+    // minutes => seconds
+    time += parseFloat(parts[1])*60;
+    // get seconds
+    var seconds = parts[2].split(/\.|,/); // Either . or ,
+    time += parseFloat(seconds[0]);
+    // add miliseconds
+    ms = parseFloat(seconds[1]);
+    if (ms) { time += ms/1000; }
+    return time;
+  },
+
+  buildSubtitles: function(){
+    /* Creating this HTML
+      <div class="vjs-subtitles"></div>
+    */
+    this.subtitlesDisplay = _V_.createElement("div", { className: 'vjs-subtitles' });
+    this.box.appendChild(this.subtitlesDisplay);
+    this.activateElement(this.subtitlesDisplay, "subtitlesDisplay");
+  },
+
+  /* Player API - Translate functionality from player to video
+  ================================================================================ */
+  addVideoListener: function(type, fn){ _V_.addListener(this.video, type, fn.rEvtContext(this)); },
+
+  play: function(){
+    this.video.play();
+    return this;
+  },
+  onPlay: function(fn){ this.addVideoListener("play", fn); return this; },
+
+  pause: function(){
+    this.video.pause();
+    return this;
+  },
+  onPause: function(fn){ this.addVideoListener("pause", fn); return this; },
+  paused: function() { return this.video.paused; },
+
+  currentTime: function(seconds){
+    if (seconds !== undefined) {
+      try { this.video.currentTime = seconds; }
+      catch(e) { this.warning(VideoJS.warnings.videoNotReady); }
+      this.values.currentTime = seconds;
+      return this;
+    }
+    return this.video.currentTime;
+  },
+  onCurrentTimeUpdate: function(fn){
+    this.currentTimeListeners.push(fn);
+  },
+
+  duration: function(){
+    return this.video.duration;
+  },
+
+  buffered: function(){
+    // Storing values allows them be overridden by setBufferedFromProgress
+    if (this.values.bufferStart === undefined) {
+      this.values.bufferStart = 0;
+      this.values.bufferEnd = 0;
+    }
+    if (this.video.buffered && this.video.buffered.length > 0) {
+      var newEnd = this.video.buffered.end(0);
+      if (newEnd > this.values.bufferEnd) { this.values.bufferEnd = newEnd; }
+    }
+    return [this.values.bufferStart, this.values.bufferEnd];
+  },
+
+  volume: function(percentAsDecimal){
+    if (percentAsDecimal !== undefined) {
+      // Force value to between 0 and 1
+      this.values.volume = Math.max(0, Math.min(1, parseFloat(percentAsDecimal)));
+      this.video.volume = this.values.volume;
+      this.setLocalStorage("volume", this.values.volume);
+      return this;
+    }
+    if (this.values.volume) { return this.values.volume; }
+    return this.video.volume;
+  },
+  onVolumeChange: function(fn){ _V_.addListener(this.video, 'volumechange', fn.rEvtContext(this)); },
+
+  width: function(width){
+    if (width !== undefined) {
+      this.video.width = width; // Not using style so it can be overridden on fullscreen.
+      this.box.style.width = width+"px";
+      this.triggerResizeListeners();
+      return this;
+    }
+    return this.video.offsetWidth;
+  },
+  height: function(height){
+    if (height !== undefined) {
+      this.video.height = height;
+      this.box.style.height = height+"px";
+      this.triggerResizeListeners();
+      return this;
+    }
+    return this.video.offsetHeight;
+  },
+
+  supportsFullScreen: function(){
+    if(typeof this.video.webkitEnterFullScreen == 'function') {
+      // Seems to be broken in Chromium/Chrome
+      if (!navigator.userAgent.match("Chrome") && !navigator.userAgent.match("Mac OS X 10.5")) {
+        return true;
+      }
+    }
+    return false;
+  },
+
+  html5EnterNativeFullScreen: function(){
+    try {
+      this.video.webkitEnterFullScreen();
+    } catch (e) {
+      if (e.code == 11) { this.warning(VideoJS.warnings.videoNotReady); }
+    }
+    return this;
+  },
+
+  // Turn on fullscreen (window) mode
+  // Real fullscreen isn't available in browsers quite yet.
+  enterFullScreen: function(){
+    if (this.supportsFullScreen()) {
+      this.html5EnterNativeFullScreen();
+    } else {
+      this.enterFullWindow();
+    }
+  },
+
+  exitFullScreen: function(){
+    if (this.supportsFullScreen()) {
+      // Shouldn't be called
+    } else {
+      this.exitFullWindow();
+    }
+  },
+
+  enterFullWindow: function(){
+    this.videoIsFullScreen = true;
+    // Storing original doc overflow value to return to when fullscreen is off
+    this.docOrigOverflow = document.documentElement.style.overflow;
+    // Add listener for esc key to exit fullscreen
+    _V_.addListener(document, "keydown", this.fullscreenOnEscKey.rEvtContext(this));
+    // Add listener for a window resize
+    _V_.addListener(window, "resize", this.fullscreenOnWindowResize.rEvtContext(this));
+    // Hide any scroll bars
+    document.documentElement.style.overflow = 'hidden';
+    // Apply fullscreen styles
+    _V_.addClass(this.box, "vjs-fullscreen");
+    // Resize the box, controller, and poster
+    this.positionAll();
+  },
+
+  // Turn off fullscreen (window) mode
+  exitFullWindow: function(){
+    this.videoIsFullScreen = false;
+    document.removeEventListener("keydown", this.fullscreenOnEscKey, false);
+    window.removeEventListener("resize", this.fullscreenOnWindowResize, false);
+    // Unhide scroll bars.
+    document.documentElement.style.overflow = this.docOrigOverflow;
+    // Remove fullscreen styles
+    _V_.removeClass(this.box, "vjs-fullscreen");
+    // Resize the box, controller, and poster to original sizes
+    this.positionAll();
+  },
+
+  onError: function(fn){ this.addVideoListener("error", fn); return this; },
+  onEnded: function(fn){
+    this.addVideoListener("ended", fn); return this;
+  }
+});
+
+////////////////////////////////////////////////////////////////////////////////
+// Element Behaviors
+// Tell elements how to act or react
+////////////////////////////////////////////////////////////////////////////////
+
+/* Player Behaviors - How VideoJS reacts to what the video is doing.
+================================================================================ */
+VideoJS.player.newBehavior("player", function(player){
+    this.onError(this.playerOnVideoError);
+    // Listen for when the video is played
+    this.onPlay(this.playerOnVideoPlay);
+    this.onPlay(this.trackCurrentTime);
+    // Listen for when the video is paused
+    this.onPause(this.playerOnVideoPause);
+    this.onPause(this.stopTrackingCurrentTime);
+    // Listen for when the video ends
+    this.onEnded(this.playerOnVideoEnded);
+    // Set interval for load progress using buffer watching method
+    // this.trackCurrentTime();
+    this.trackBuffered();
+    // Buffer Full
+    this.onBufferedUpdate(this.isBufferFull);
+  },{
+    playerOnVideoError: function(event){
+      this.log(event);
+      this.log(this.video.error);
+    },
+    playerOnVideoPlay: function(event){ this.hasPlayed = true; },
+    playerOnVideoPause: function(event){},
+    playerOnVideoEnded: function(event){
+      this.currentTime(0);
+      this.pause();
+    },
+
+    /* Load Tracking -------------------------------------------------------------- */
+    // Buffer watching method for load progress.
+    // Used for browsers that don't support the progress event
+    trackBuffered: function(){
+      this.bufferedInterval = setInterval(this.triggerBufferedListeners.context(this), 500);
+    },
+    stopTrackingBuffered: function(){ clearInterval(this.bufferedInterval); },
+    bufferedListeners: [],
+    onBufferedUpdate: function(fn){
+      this.bufferedListeners.push(fn);
+    },
+    triggerBufferedListeners: function(){
+      this.isBufferFull();
+      this.each(this.bufferedListeners, function(listener){
+        (listener.context(this))();
+      });
+    },
+    isBufferFull: function(){
+      if (this.bufferedPercent() == 1) { this.stopTrackingBuffered(); }
+    },
+
+    /* Time Tracking -------------------------------------------------------------- */
+    trackCurrentTime: function(){
+      if (this.currentTimeInterval) { clearInterval(this.currentTimeInterval); }
+      this.currentTimeInterval = setInterval(this.triggerCurrentTimeListeners.context(this), 100); // 42 = 24 fps
+      this.trackingCurrentTime = true;
+    },
+    // Turn off play progress tracking (when paused or dragging)
+    stopTrackingCurrentTime: function(){
+      clearInterval(this.currentTimeInterval);
+      this.trackingCurrentTime = false;
+    },
+    currentTimeListeners: [],
+    // onCurrentTimeUpdate is in API section now
+    triggerCurrentTimeListeners: function(late, newTime){ // FF passes milliseconds late as the first argument
+      this.each(this.currentTimeListeners, function(listener){
+        (listener.context(this))(newTime || this.currentTime());
+      });
+    },
+
+    /* Resize Tracking -------------------------------------------------------------- */
+    resizeListeners: [],
+    onResize: function(fn){
+      this.resizeListeners.push(fn);
+    },
+    // Trigger anywhere the video/box size is changed.
+    triggerResizeListeners: function(){
+      this.each(this.resizeListeners, function(listener){
+        (listener.context(this))();
+      });
+    }
+  }
+);
+/* Mouse Over Video Reporter Behaviors - i.e. Controls hiding based on mouse location
+================================================================================ */
+VideoJS.player.newBehavior("mouseOverVideoReporter", function(element){
+    // Listen for the mouse move the video. Used to reveal the controller.
+    _V_.addListener(element, "mousemove", this.mouseOverVideoReporterOnMouseMove.context(this));
+    // Listen for the mouse moving out of the video. Used to hide the controller.
+    _V_.addListener(element, "mouseout", this.mouseOverVideoReporterOnMouseOut.context(this));
+  },{
+    mouseOverVideoReporterOnMouseMove: function(){
+      this.showControlBars();
+      clearInterval(this.mouseMoveTimeout);
+      this.mouseMoveTimeout = setTimeout(this.hideControlBars.context(this), 4000);
+    },
+    mouseOverVideoReporterOnMouseOut: function(event){
+      // Prevent flicker by making sure mouse hasn't left the video
+      var parent = event.relatedTarget;
+      while (parent && parent !== this.box) {
+        parent = parent.parentNode;
+      }
+      if (parent !== this.box) {
+        this.hideControlBars();
+      }
+    }
+  }
+);
+/* Mouse Over Video Reporter Behaviors - i.e. Controls hiding based on mouse location
+================================================================================ */
+VideoJS.player.newBehavior("box", function(element){
+    this.positionBox();
+    _V_.addClass(element, "vjs-paused");
+    this.activateElement(element, "mouseOverVideoReporter");
+    this.onPlay(this.boxOnVideoPlay);
+    this.onPause(this.boxOnVideoPause);
+  },{
+    boxOnVideoPlay: function(){
+      _V_.removeClass(this.box, "vjs-paused");
+      _V_.addClass(this.box, "vjs-playing");
+    },
+    boxOnVideoPause: function(){
+      _V_.removeClass(this.box, "vjs-playing");
+      _V_.addClass(this.box, "vjs-paused");
+    }
+  }
+);
+/* Poster Image Overlay
+================================================================================ */
+VideoJS.player.newBehavior("poster", function(element){
+    this.activateElement(element, "mouseOverVideoReporter");
+    this.activateElement(element, "playButton");
+    this.onPlay(this.hidePoster);
+    this.onEnded(this.showPoster);
+    this.onResize(this.positionPoster);
+  },{
+    showPoster: function(){
+      if (!this.poster) { return; }
+      this.poster.style.display = "block";
+      this.positionPoster();
+    },
+    positionPoster: function(){
+      // Only if the poster is visible
+      if (!this.poster || this.poster.style.display == 'none') { return; }
+      this.poster.style.height = this.height() + "px"; // Need incase controlsBelow
+      this.poster.style.width = this.width() + "px"; // Could probably do 100% of box
+    },
+    hidePoster: function(){
+      if (!this.poster) { return; }
+      this.poster.style.display = "none";
+    },
+    // Update poster source from attribute or fallback image
+    // iPad breaks if you include a poster attribute, so this fixes that
+    updatePosterSource: function(){
+      if (!this.video.poster) {
+        var images = this.video.getElementsByTagName("img");
+        if (images.length > 0) { this.video.poster = images[0].src; }
+      }
+    }
+  }
+);
+/* Control Bar Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("controlBar", function(element){
+    if (!this.controlBars) {
+      this.controlBars = [];
+      this.onResize(this.positionControlBars);
+    }
+    this.controlBars.push(element);
+    _V_.addListener(element, "mousemove", this.onControlBarsMouseMove.context(this));
+    _V_.addListener(element, "mouseout", this.onControlBarsMouseOut.context(this));
+  },{
+    showControlBars: function(){
+      if (!this.options.controlsAtStart && !this.hasPlayed) { return; }
+      this.each(this.controlBars, function(bar){
+        bar.style.display = "block";
+      });
+    },
+    // Place controller relative to the video's position (now just resizing bars)
+    positionControlBars: function(){
+      this.updatePlayProgressBars();
+      this.updateLoadProgressBars();
+    },
+    hideControlBars: function(){
+      if (this.options.controlsHiding && !this.mouseIsOverControls) {
+        this.each(this.controlBars, function(bar){
+          bar.style.display = "none";
+        });
+      }
+    },
+    // Block controls from hiding when mouse is over them.
+    onControlBarsMouseMove: function(){ this.mouseIsOverControls = true; },
+    onControlBarsMouseOut: function(event){
+      this.mouseIsOverControls = false;
+    }
+  }
+);
+/* PlayToggle, PlayButton, PauseButton Behaviors
+================================================================================ */
+// Play Toggle
+VideoJS.player.newBehavior("playToggle", function(element){
+    if (!this.elements.playToggles) {
+      this.elements.playToggles = [];
+      this.onPlay(this.playTogglesOnPlay);
+      this.onPause(this.playTogglesOnPause);
+    }
+    this.elements.playToggles.push(element);
+    _V_.addListener(element, "click", this.onPlayToggleClick.context(this));
+  },{
+    onPlayToggleClick: function(event){
+      if (this.paused()) {
+        this.play();
+      } else {
+        this.pause();
+      }
+    },
+    playTogglesOnPlay: function(event){
+      this.each(this.elements.playToggles, function(toggle){
+        _V_.removeClass(toggle, "vjs-paused");
+        _V_.addClass(toggle, "vjs-playing");
+      });
+    },
+    playTogglesOnPause: function(event){
+      this.each(this.elements.playToggles, function(toggle){
+        _V_.removeClass(toggle, "vjs-playing");
+        _V_.addClass(toggle, "vjs-paused");
+      });
+    }
+  }
+);
+// Play
+VideoJS.player.newBehavior("playButton", function(element){
+    _V_.addListener(element, "click", this.onPlayButtonClick.context(this));
+  },{
+    onPlayButtonClick: function(event){ this.play(); }
+  }
+);
+// Pause
+VideoJS.player.newBehavior("pauseButton", function(element){
+    _V_.addListener(element, "click", this.onPauseButtonClick.context(this));
+  },{
+    onPauseButtonClick: function(event){ this.pause(); }
+  }
+);
+/* Play Progress Bar Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("playProgressBar", function(element){
+    if (!this.playProgressBars) {
+      this.playProgressBars = [];
+      this.onCurrentTimeUpdate(this.updatePlayProgressBars);
+    }
+    this.playProgressBars.push(element);
+  },{
+    // Ajust the play progress bar's width based on the current play time
+    updatePlayProgressBars: function(newTime){
+      var progress = (newTime !== undefined) ? newTime / this.duration() : this.currentTime() / this.duration();
+      if (isNaN(progress)) { progress = 0; }
+      this.each(this.playProgressBars, function(bar){
+        if (bar.style) { bar.style.width = _V_.round(progress * 100, 2) + "%"; }
+      });
+    }
+  }
+);
+/* Load Progress Bar Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("loadProgressBar", function(element){
+    if (!this.loadProgressBars) { this.loadProgressBars = []; }
+    this.loadProgressBars.push(element);
+    this.onBufferedUpdate(this.updateLoadProgressBars);
+  },{
+    updateLoadProgressBars: function(){
+      this.each(this.loadProgressBars, function(bar){
+        if (bar.style) { bar.style.width = _V_.round(this.bufferedPercent() * 100, 2) + "%"; }
+      });
+    }
+  }
+);
+
+/* Current Time Display Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("currentTimeDisplay", function(element){
+    if (!this.currentTimeDisplays) {
+      this.currentTimeDisplays = [];
+      this.onCurrentTimeUpdate(this.updateCurrentTimeDisplays);
+    }
+    this.currentTimeDisplays.push(element);
+  },{
+    // Update the displayed time (00:00)
+    updateCurrentTimeDisplays: function(newTime){
+      if (!this.currentTimeDisplays) { return; }
+      // Allows for smooth scrubbing, when player can't keep up.
+      var time = (newTime) ? newTime : this.currentTime();
+      this.each(this.currentTimeDisplays, function(dis){
+        dis.innerHTML = _V_.formatTime(time);
+      });
+    }
+  }
+);
+
+/* Duration Display Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("durationDisplay", function(element){
+    if (!this.durationDisplays) {
+      this.durationDisplays = [];
+      this.onCurrentTimeUpdate(this.updateDurationDisplays);
+    }
+    this.durationDisplays.push(element);
+  },{
+    updateDurationDisplays: function(){
+      if (!this.durationDisplays) { return; }
+      this.each(this.durationDisplays, function(dis){
+        if (this.duration()) { dis.innerHTML = _V_.formatTime(this.duration()); }
+      });
+    }
+  }
+);
+
+/* Current Time Scrubber Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("currentTimeScrubber", function(element){
+    _V_.addListener(element, "mousedown", this.onCurrentTimeScrubberMouseDown.rEvtContext(this));
+  },{
+    // Adjust the play position when the user drags on the progress bar
+    onCurrentTimeScrubberMouseDown: function(event, scrubber){
+      event.preventDefault();
+      this.currentScrubber = scrubber;
+
+      this.stopTrackingCurrentTime(); // Allows for smooth scrubbing
+
+      this.videoWasPlaying = !this.paused();
+      this.pause();
+
+      _V_.blockTextSelection();
+      this.setCurrentTimeWithScrubber(event);
+      _V_.addListener(document, "mousemove", this.onCurrentTimeScrubberMouseMove.rEvtContext(this));
+      _V_.addListener(document, "mouseup", this.onCurrentTimeScrubberMouseUp.rEvtContext(this));
+    },
+    onCurrentTimeScrubberMouseMove: function(event){ // Removable
+      this.setCurrentTimeWithScrubber(event);
+    },
+    onCurrentTimeScrubberMouseUp: function(event){ // Removable
+      _V_.unblockTextSelection();
+      document.removeEventListener("mousemove", this.onCurrentTimeScrubberMouseMove, false);
+      document.removeEventListener("mouseup", this.onCurrentTimeScrubberMouseUp, false);
+      if (this.videoWasPlaying) {
+        this.play();
+        this.trackCurrentTime();
+      }
+    },
+    setCurrentTimeWithScrubber: function(event){
+      var newProgress = _V_.getRelativePosition(event.pageX, this.currentScrubber);
+      var newTime = newProgress * this.duration();
+      this.triggerCurrentTimeListeners(0, newTime); // Allows for smooth scrubbing
+      // Don't let video end while scrubbing.
+      if (newTime == this.duration()) { newTime = newTime - 0.1; }
+      this.currentTime(newTime);
+    }
+  }
+);
+/* Volume Display Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("volumeDisplay", function(element){
+    if (!this.volumeDisplays) {
+      this.volumeDisplays = [];
+      this.onVolumeChange(this.updateVolumeDisplays);
+    }
+    this.volumeDisplays.push(element);
+    this.updateVolumeDisplay(element); // Set the display to the initial volume
+  },{
+    // Update the volume control display
+    // Unique to these default controls. Uses borders to create the look of bars.
+    updateVolumeDisplays: function(){
+      if (!this.volumeDisplays) { return; }
+      this.each(this.volumeDisplays, function(dis){
+        this.updateVolumeDisplay(dis);
+      });
+    },
+    updateVolumeDisplay: function(display){
+      var volNum = Math.ceil(this.volume() * 6);
+      this.each(display.children, function(child, num){
+        if (num < volNum) {
+          _V_.addClass(child, "vjs-volume-level-on");
+        } else {
+          _V_.removeClass(child, "vjs-volume-level-on");
+        }
+      });
+    }
+  }
+);
+/* Volume Scrubber Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("volumeScrubber", function(element){
+    _V_.addListener(element, "mousedown", this.onVolumeScrubberMouseDown.rEvtContext(this));
+  },{
+    // Adjust the volume when the user drags on the volume control
+    onVolumeScrubberMouseDown: function(event, scrubber){
+      // event.preventDefault();
+      _V_.blockTextSelection();
+      this.currentScrubber = scrubber;
+      this.setVolumeWithScrubber(event);
+      _V_.addListener(document, "mousemove", this.onVolumeScrubberMouseMove.rEvtContext(this));
+      _V_.addListener(document, "mouseup", this.onVolumeScrubberMouseUp.rEvtContext(this));
+    },
+    onVolumeScrubberMouseMove: function(event){
+      this.setVolumeWithScrubber(event);
+    },
+    onVolumeScrubberMouseUp: function(event){
+      this.setVolumeWithScrubber(event);
+      _V_.unblockTextSelection();
+      document.removeEventListener("mousemove", this.onVolumeScrubberMouseMove, false);
+      document.removeEventListener("mouseup", this.onVolumeScrubberMouseUp, false);
+    },
+    setVolumeWithScrubber: function(event){
+      var newVol = _V_.getRelativePosition(event.pageX, this.currentScrubber);
+      this.volume(newVol);
+    }
+  }
+);
+/* Fullscreen Toggle Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("fullscreenToggle", function(element){
+    _V_.addListener(element, "click", this.onFullscreenToggleClick.context(this));
+  },{
+    // When the user clicks on the fullscreen button, update fullscreen setting
+    onFullscreenToggleClick: function(event){
+      if (!this.videoIsFullScreen) {
+        this.enterFullScreen();
+      } else {
+        this.exitFullScreen();
+      }
+    },
+
+    fullscreenOnWindowResize: function(event){ // Removable
+      this.positionControlBars();
+    },
+    // Create listener for esc key while in full screen mode
+    fullscreenOnEscKey: function(event){ // Removable
+      if (event.keyCode == 27) {
+        this.exitFullScreen();
+      }
+    }
+  }
+);
+/* Big Play Button Behaviors
+================================================================================ */
+VideoJS.player.newBehavior("bigPlayButton", function(element){
+    if (!this.elements.bigPlayButtons) {
+      this.elements.bigPlayButtons = [];
+      this.onPlay(this.bigPlayButtonsOnPlay);
+      this.onEnded(this.bigPlayButtonsOnEnded);
+    }
+    this.elements.bigPlayButtons.push(element);
+    this.activateElement(element, "playButton");
+  },{
+    bigPlayButtonsOnPlay: function(event){ this.hideBigPlayButtons(); },
+    bigPlayButtonsOnEnded: function(event){ this.showBigPlayButtons(); },
+    showBigPlayButtons: function(){
+      this.each(this.elements.bigPlayButtons, function(element){
+        element.style.display = "block";
+      });
+    },
+    hideBigPlayButtons: function(){
+      this.each(this.elements.bigPlayButtons, function(element){
+        element.style.display = "none";
+      });
+    }
+  }
+);
+/* Spinner
+================================================================================ */
+VideoJS.player.newBehavior("spinner", function(element){
+    if (!this.spinners) {
+      this.spinners = [];
+      _V_.addListener(this.video, "loadeddata", this.spinnersOnVideoLoadedData.context(this));
+      _V_.addListener(this.video, "loadstart", this.spinnersOnVideoLoadStart.context(this));
+      _V_.addListener(this.video, "seeking", this.spinnersOnVideoSeeking.context(this));
+      _V_.addListener(this.video, "seeked", this.spinnersOnVideoSeeked.context(this));
+      _V_.addListener(this.video, "canplay", this.spinnersOnVideoCanPlay.context(this));
+      _V_.addListener(this.video, "canplaythrough", this.spinnersOnVideoCanPlayThrough.context(this));
+      _V_.addListener(this.video, "waiting", this.spinnersOnVideoWaiting.context(this));
+      _V_.addListener(this.video, "stalled", this.spinnersOnVideoStalled.context(this));
+      _V_.addListener(this.video, "suspend", this.spinnersOnVideoSuspend.context(this));
+      _V_.addListener(this.video, "playing", this.spinnersOnVideoPlaying.context(this));
+      _V_.addListener(this.video, "timeupdate", this.spinnersOnVideoTimeUpdate.context(this));
+    }
+    this.spinners.push(element);
+  },{
+    showSpinners: function(){
+      this.each(this.spinners, function(spinner){
+        spinner.style.display = "block";
+      });
+      clearInterval(this.spinnerInterval);
+      this.spinnerInterval = setInterval(this.rotateSpinners.context(this), 100);
+    },
+    hideSpinners: function(){
+      this.each(this.spinners, function(spinner){
+        spinner.style.display = "none";
+      });
+      clearInterval(this.spinnerInterval);
+    },
+    spinnersRotated: 0,
+    rotateSpinners: function(){
+      this.each(this.spinners, function(spinner){
+        // spinner.style.transform =       'scale(0.5) rotate('+this.spinnersRotated+'deg)';
+        spinner.style.WebkitTransform = 'scale(0.5) rotate('+this.spinnersRotated+'deg)';
+        spinner.style.MozTransform =    'scale(0.5) rotate('+this.spinnersRotated+'deg)';
+      });
+      if (this.spinnersRotated == 360) { this.spinnersRotated = 0; }
+      this.spinnersRotated += 45;
+    },
+    spinnersOnVideoLoadedData: function(event){ this.hideSpinners(); },
+    spinnersOnVideoLoadStart: function(event){ this.showSpinners(); },
+    spinnersOnVideoSeeking: function(event){ /* this.showSpinners(); */ },
+    spinnersOnVideoSeeked: function(event){ /* this.hideSpinners(); */ },
+    spinnersOnVideoCanPlay: function(event){ /* this.hideSpinners(); */ },
+    spinnersOnVideoCanPlayThrough: function(event){ this.hideSpinners(); },
+    spinnersOnVideoWaiting: function(event){
+      // Safari sometimes triggers waiting inappropriately
+      // Like after video has played, any you play again.
+      this.showSpinners();
+    },
+    spinnersOnVideoStalled: function(event){},
+    spinnersOnVideoSuspend: function(event){},
+    spinnersOnVideoPlaying: function(event){ this.hideSpinners(); },
+    spinnersOnVideoTimeUpdate: function(event){
+      // Safari sometimes calls waiting and doesn't recover
+      if(this.spinner.style.display == "block") { this.hideSpinners(); }
+    }
+  }
+);
+/* Subtitles
+================================================================================ */
+VideoJS.player.newBehavior("subtitlesDisplay", function(element){
+    if (!this.subtitleDisplays) {
+      this.subtitleDisplays = [];
+      this.onCurrentTimeUpdate(this.subtitleDisplaysOnVideoTimeUpdate);
+      this.onEnded(function() { this.lastSubtitleIndex = 0; }.context(this));
+    }
+    this.subtitleDisplays.push(element);
+  },{
+    subtitleDisplaysOnVideoTimeUpdate: function(time){
+      // Assuming all subtitles are in order by time, and do not overlap
+      if (this.subtitles) {
+        // If current subtitle should stay showing, don't do anything. Otherwise, find new subtitle.
+        if (!this.currentSubtitle || this.currentSubtitle.start >= time || this.currentSubtitle.end < time) {
+          var newSubIndex = false,
+              // Loop in reverse if lastSubtitle is after current time (optimization)
+              // Meaning the user is scrubbing in reverse or rewinding
+              reverse = (this.subtitles[this.lastSubtitleIndex].start > time),
+              // If reverse, step back 1 becase we know it's not the lastSubtitle
+              i = this.lastSubtitleIndex - (reverse) ? 1 : 0;
+          while (true) { // Loop until broken
+            if (reverse) { // Looping in reverse
+              // Stop if no more, or this subtitle ends before the current time (no earlier subtitles should apply)
+              if (i < 0 || this.subtitles[i].end < time) { break; }
+              // End is greater than time, so if start is less, show this subtitle
+              if (this.subtitles[i].start < time) {
+                newSubIndex = i;
+                break;
+              }
+              i--;
+            } else { // Looping forward
+              // Stop if no more, or this subtitle starts after time (no later subtitles should apply)
+              if (i >= this.subtitles.length || this.subtitles[i].start > time) { break; }
+              // Start is less than time, so if end is later, show this subtitle
+              if (this.subtitles[i].end > time) {
+                newSubIndex = i;
+                break;
+              }
+              i++;
+            }
+          }
+
+          // Set or clear current subtitle
+          if (newSubIndex !== false) {
+            this.currentSubtitle = this.subtitles[newSubIndex];
+            this.lastSubtitleIndex = newSubIndex;
+            this.updateSubtitleDisplays(this.currentSubtitle.text);
+          } else if (this.currentSubtitle) {
+            this.currentSubtitle = false;
+            this.updateSubtitleDisplays("");
+          }
+        }
+      }
+    },
+    updateSubtitleDisplays: function(val){
+      this.each(this.subtitleDisplays, function(disp){
+        disp.innerHTML = val;
+      });
+    }
+  }
+);
+
+////////////////////////////////////////////////////////////////////////////////
+// Convenience Functions (mini library)
+// Functions not specific to video or VideoJS and could probably be replaced with a library like jQuery
+////////////////////////////////////////////////////////////////////////////////
+
+VideoJS.extend({
+
+  addClass: function(element, classToAdd){
+    if ((" "+element.className+" ").indexOf(" "+classToAdd+" ") == -1) {
+      element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd;
+    }
+  },
+  removeClass: function(element, classToRemove){
+    if (element.className.indexOf(classToRemove) == -1) { return; }
+    var classNames = element.className.split(/\s+/);
+    classNames.splice(classNames.lastIndexOf(classToRemove),1);
+    element.className = classNames.join(" ");
+  },
+  createElement: function(tagName, attributes){
+    return this.merge(document.createElement(tagName), attributes);
+  },
+
+  // Attempt to block the ability to select text while dragging controls
+  blockTextSelection: function(){
+    document.body.focus();
+    document.onselectstart = function () { return false; };
+  },
+  // Turn off text selection blocking
+  unblockTextSelection: function(){ document.onselectstart = function () { return true; }; },
+
+  // Return seconds as MM:SS
+  formatTime: function(secs) {
+    var seconds = Math.round(secs);
+    var minutes = Math.floor(seconds / 60);
+    minutes = (minutes >= 10) ? minutes : "0" + minutes;
+    seconds = Math.floor(seconds % 60);
+    seconds = (seconds >= 10) ? seconds : "0" + seconds;
+    return minutes + ":" + seconds;
+  },
+
+  // Return the relative horizonal position of an event as a value from 0-1
+  getRelativePosition: function(x, relativeElement){
+    return Math.max(0, Math.min(1, (x - this.findPosX(relativeElement)) / relativeElement.offsetWidth));
+  },
+  // Get an objects position on the page
+  findPosX: function(obj) {
+    var curleft = obj.offsetLeft;
+    while(obj = obj.offsetParent) {
+      curleft += obj.offsetLeft;
+    }
+    return curleft;
+  },
+  getComputedStyleValue: function(element, style){
+    return window.getComputedStyle(element, null).getPropertyValue(style);
+  },
+
+  round: function(num, dec) {
+    if (!dec) { dec = 0; }
+    return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+  },
+
+  addListener: function(element, type, handler){
+    if (element.addEventListener) {
+      element.addEventListener(type, handler, false);
+    } else if (element.attachEvent) {
+      element.attachEvent("on"+type, handler);
+    }
+  },
+  removeListener: function(element, type, handler){
+    if (element.removeEventListener) {
+      element.removeEventListener(type, handler, false);
+    } else if (element.attachEvent) {
+      element.detachEvent("on"+type, handler);
+    }
+  },
+
+  get: function(url, onSuccess){
+    if (typeof XMLHttpRequest == "undefined") {
+      XMLHttpRequest = function () {
+        try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
+        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (f) {}
+        try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (g) {}
+        //Microsoft.XMLHTTP points to Msxml2.XMLHTTP.3.0 and is redundant
+        throw new Error("This browser does not support XMLHttpRequest.");
+      };
+    }
+    var request = new XMLHttpRequest();
+    request.open("GET",url);
+    request.onreadystatechange = function() {
+      if (request.readyState == 4 && request.status == 200) {
+        onSuccess(request.responseText);
+      }
+    }.context(this);
+    request.send();
+  },
+
+  trim: function(string){ return string.toString().replace(/^\s+/, "").replace(/\s+$/, ""); },
+
+  // DOM Ready functionality adapted from jQuery. http://jquery.com/
+  bindDOMReady: function(){
+    if (document.readyState === "complete") {
+      return VideoJS.onDOMReady();
+    }
+    if (document.addEventListener) {
+      document.addEventListener("DOMContentLoaded", VideoJS.DOMContentLoaded, false);
+      window.addEventListener("load", VideoJS.onDOMReady, false);
+    } else if (document.attachEvent) {
+      document.attachEvent("onreadystatechange", VideoJS.DOMContentLoaded);
+      window.attachEvent("onload", VideoJS.onDOMReady);
+    }
+  },
+
+  DOMContentLoaded: function(){
+    if (document.addEventListener) {
+      document.removeEventListener( "DOMContentLoaded", VideoJS.DOMContentLoaded, false);
+      VideoJS.onDOMReady();
+    } else if ( document.attachEvent ) {
+      if ( document.readyState === "complete" ) {
+        document.detachEvent("onreadystatechange", VideoJS.DOMContentLoaded);
+        VideoJS.onDOMReady();
+      }
+    }
+  },
+
+  // Functions to be run once the DOM is loaded
+  DOMReadyList: [],
+  addToDOMReady: function(fn){
+    if (VideoJS.DOMIsReady) {
+      fn.call(document);
+    } else {
+      VideoJS.DOMReadyList.push(fn);
+    }
+  },
+
+  DOMIsReady: false,
+  onDOMReady: function(){
+    if (VideoJS.DOMIsReady) { return; }
+    if (!document.body) { return setTimeout(VideoJS.onDOMReady, 13); }
+    VideoJS.DOMIsReady = true;
+    if (VideoJS.DOMReadyList) {
+      for (var i=0; i<VideoJS.DOMReadyList.length; i++) {
+        VideoJS.DOMReadyList[i].call(document);
+      }
+      VideoJS.DOMReadyList = null;
+    }
+  }
+});
+VideoJS.bindDOMReady();
+
+// Allows for binding context to functions
+// when using in event listeners and timeouts
+Function.prototype.context = function(obj){
+  var method = this,
+  temp = function(){
+    return method.apply(obj, arguments);
+  };
+  return temp;
+};
+
+// Like context, in that it creates a closure
+// But insteaad keep "this" intact, and passes the var as the second argument of the function
+// Need for event listeners where you need to know what called the event
+// Only use with event callbacks
+Function.prototype.evtContext = function(obj){
+  var method = this,
+  temp = function(){
+    var origContext = this;
+    return method.call(obj, arguments[0], origContext);
+  };
+  return temp;
+};
+
+// Removable Event listener with Context
+// Replaces the original function with a version that has context
+// So it can be removed using the original function name.
+// In order to work, a version of the function must already exist in the player/prototype
+Function.prototype.rEvtContext = function(obj, funcParent){
+  if (this.hasContext === true) { return this; }
+  if (!funcParent) { funcParent = obj; }
+  for (var attrname in funcParent) {
+    if (funcParent[attrname] == this) {
+      funcParent[attrname] = this.evtContext(obj);
+      funcParent[attrname].hasContext = true;
+      return funcParent[attrname];
+    }
+  }
+  return this.evtContext(obj);
+};
+
+// jQuery Plugin
+if (window.jQuery) {
+  (function($) {
+    $.fn.VideoJS = function(options) {
+      this.each(function() {
+        VideoJS.setup(this, options);
+      });
+      return this;
+    };
+    $.fn.player = function() {
+      return this[0].player;
+    };
+  })(jQuery);
+}
+
+
+// Expose to global
+window.VideoJS = window._V_ = VideoJS;
+
+// End self-executing function
+})(window);
\ No newline at end of file