Creating release candidate rc4 from release_360 branch
git-svn-id: https://llvm.org/svn/llvm-project/polly/tags/RELEASE_360@229779 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/rc4/.arcconfig b/rc4/.arcconfig
new file mode 100644
index 0000000..d64a648
--- /dev/null
+++ b/rc4/.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/rc4/.arclint b/rc4/.arclint
new file mode 100644
index 0000000..84546f5
--- /dev/null
+++ b/rc4/.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/rc4/.gitattributes b/rc4/.gitattributes
new file mode 100644
index 0000000..7105fff
--- /dev/null
+++ b/rc4/.gitattributes
@@ -0,0 +1,4 @@
+# Auto detect text files and perform LF normalization
+* text eol=lf
+*.png -text
+*.pdf -text
diff --git a/rc4/.gitignore b/rc4/.gitignore
new file mode 100644
index 0000000..8618b3d
--- /dev/null
+++ b/rc4/.gitignore
@@ -0,0 +1 @@
+test/lit.site.cfg
diff --git a/rc4/CMakeLists.txt b/rc4/CMakeLists.txt
new file mode 100644
index 0000000..6e72fba
--- /dev/null
+++ b/rc4/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/rc4/CREDITS.txt b/rc4/CREDITS.txt
new file mode 100644
index 0000000..98fb9cd
--- /dev/null
+++ b/rc4/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/rc4/LICENSE.txt b/rc4/LICENSE.txt
new file mode 100644
index 0000000..86d29f5
--- /dev/null
+++ b/rc4/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/rc4/Makefile b/rc4/Makefile
new file mode 100644
index 0000000..2ad5b36
--- /dev/null
+++ b/rc4/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/rc4/Makefile.common.in b/rc4/Makefile.common.in
new file mode 100644
index 0000000..8a5b945
--- /dev/null
+++ b/rc4/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/rc4/Makefile.config.in b/rc4/Makefile.config.in
new file mode 100644
index 0000000..c84be0b
--- /dev/null
+++ b/rc4/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/rc4/README b/rc4/README
new file mode 100644
index 0000000..09a4a54
--- /dev/null
+++ b/rc4/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/rc4/autoconf/AutoRegen.sh b/rc4/autoconf/AutoRegen.sh
new file mode 100755
index 0000000..bafef34
--- /dev/null
+++ b/rc4/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/rc4/autoconf/LICENSE.TXT b/rc4/autoconf/LICENSE.TXT
new file mode 100644
index 0000000..72fdd39
--- /dev/null
+++ b/rc4/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/rc4/autoconf/aclocal.m4 b/rc4/autoconf/aclocal.m4
new file mode 100644
index 0000000..d503064
--- /dev/null
+++ b/rc4/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/rc4/autoconf/config.guess b/rc4/autoconf/config.guess
new file mode 100644
index 0000000..cc726cd
--- /dev/null
+++ b/rc4/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/rc4/autoconf/config.sub b/rc4/autoconf/config.sub
new file mode 100644
index 0000000..9772e87
--- /dev/null
+++ b/rc4/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/rc4/autoconf/configure.ac b/rc4/autoconf/configure.ac
new file mode 100644
index 0000000..15008f8
--- /dev/null
+++ b/rc4/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/rc4/autoconf/configure.bak b/rc4/autoconf/configure.bak
new file mode 100644
index 0000000..f1cac90
--- /dev/null
+++ b/rc4/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/rc4/autoconf/m4/find_lib_and_headers.m4 b/rc4/autoconf/m4/find_lib_and_headers.m4
new file mode 100644
index 0000000..e872819
--- /dev/null
+++ b/rc4/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/rc4/cmake/FindCUDA.cmake b/rc4/cmake/FindCUDA.cmake
new file mode 100644
index 0000000..37592f9
--- /dev/null
+++ b/rc4/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/rc4/cmake/FindGmp.cmake b/rc4/cmake/FindGmp.cmake
new file mode 100644
index 0000000..60def58
--- /dev/null
+++ b/rc4/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/rc4/cmake/FindIsl.cmake b/rc4/cmake/FindIsl.cmake
new file mode 100644
index 0000000..1c46e72
--- /dev/null
+++ b/rc4/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/rc4/cmake/FindPluto.cmake b/rc4/cmake/FindPluto.cmake
new file mode 100644
index 0000000..78d8563
--- /dev/null
+++ b/rc4/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/rc4/cmake/polly_macros.cmake b/rc4/cmake/polly_macros.cmake
new file mode 100644
index 0000000..386eb64
--- /dev/null
+++ b/rc4/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/rc4/configure b/rc4/configure
new file mode 100755
index 0000000..591ee39
--- /dev/null
+++ b/rc4/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/rc4/include/CMakeLists.txt b/rc4/include/CMakeLists.txt
new file mode 100644
index 0000000..abe73d1
--- /dev/null
+++ b/rc4/include/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(polly)
diff --git a/rc4/include/polly/CMakeLists.txt b/rc4/include/polly/CMakeLists.txt
new file mode 100644
index 0000000..ef92163
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Canonicalization.h b/rc4/include/polly/Canonicalization.h
new file mode 100644
index 0000000..c69bf13
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/BlockGenerators.h b/rc4/include/polly/CodeGen/BlockGenerators.h
new file mode 100644
index 0000000..cb56898
--- /dev/null
+++ b/rc4/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 <S, 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 <S, Loop *L) const;
+
+ void copyInstScalar(const Instruction *Inst, ValueMapT &BBMap,
+ ValueMapT &GlobalMap, LoopToScevMapT <S);
+
+ /// @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 <S);
+
+ Value *generateScalarLoad(const LoadInst *load, ValueMapT &BBMap,
+ ValueMapT &GlobalMap, LoopToScevMapT <S);
+
+ Value *generateScalarStore(const StoreInst *store, ValueMapT &BBMap,
+ ValueMapT &GlobalMap, LoopToScevMapT <S);
+
+ /// @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 <S);
+
+ /// @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 <S);
+};
+
+/// @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/rc4/include/polly/CodeGen/CodeGeneration.h b/rc4/include/polly/CodeGen/CodeGeneration.h
new file mode 100644
index 0000000..f87c396
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/IRBuilder.h b/rc4/include/polly/CodeGen/IRBuilder.h
new file mode 100644
index 0000000..fb56d8a
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/IslAst.h b/rc4/include/polly/CodeGen/IslAst.h
new file mode 100644
index 0000000..dfd949f
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/IslExprBuilder.h b/rc4/include/polly/CodeGen/IslExprBuilder.h
new file mode 100644
index 0000000..74b1a09
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/LoopGenerators.h b/rc4/include/polly/CodeGen/LoopGenerators.h
new file mode 100644
index 0000000..db48f7e
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/PTXGenerator.h b/rc4/include/polly/CodeGen/PTXGenerator.h
new file mode 100644
index 0000000..f4c5038
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/RuntimeDebugBuilder.h b/rc4/include/polly/CodeGen/RuntimeDebugBuilder.h
new file mode 100644
index 0000000..5d8d4c6
--- /dev/null
+++ b/rc4/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/rc4/include/polly/CodeGen/Utils.h b/rc4/include/polly/CodeGen/Utils.h
new file mode 100644
index 0000000..0752aa3
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Config/config.h.cmake b/rc4/include/polly/Config/config.h.cmake
new file mode 100644
index 0000000..ea58925
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Config/config.h.in b/rc4/include/polly/Config/config.h.in
new file mode 100644
index 0000000..295e10a
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Dependences.h b/rc4/include/polly/Dependences.h
new file mode 100644
index 0000000..df03d2c
--- /dev/null
+++ b/rc4/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/rc4/include/polly/LinkAllPasses.h b/rc4/include/polly/LinkAllPasses.h
new file mode 100644
index 0000000..3853b55
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Options.h b/rc4/include/polly/Options.h
new file mode 100644
index 0000000..62e0960
--- /dev/null
+++ b/rc4/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/rc4/include/polly/RegisterPasses.h b/rc4/include/polly/RegisterPasses.h
new file mode 100644
index 0000000..91e1e9c
--- /dev/null
+++ b/rc4/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/rc4/include/polly/ScheduleOptimizer.h b/rc4/include/polly/ScheduleOptimizer.h
new file mode 100644
index 0000000..80272d2
--- /dev/null
+++ b/rc4/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/rc4/include/polly/ScopDetection.h b/rc4/include/polly/ScopDetection.h
new file mode 100644
index 0000000..9753e38
--- /dev/null
+++ b/rc4/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/rc4/include/polly/ScopDetectionDiagnostic.h b/rc4/include/polly/ScopDetectionDiagnostic.h
new file mode 100644
index 0000000..c463597
--- /dev/null
+++ b/rc4/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/rc4/include/polly/ScopInfo.h b/rc4/include/polly/ScopInfo.h
new file mode 100644
index 0000000..df13781
--- /dev/null
+++ b/rc4/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/rc4/include/polly/ScopPass.h b/rc4/include/polly/ScopPass.h
new file mode 100644
index 0000000..3d5373a
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Support/GICHelper.h b/rc4/include/polly/Support/GICHelper.h
new file mode 100644
index 0000000..c5fb4a1
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Support/SCEVValidator.h b/rc4/include/polly/Support/SCEVValidator.h
new file mode 100644
index 0000000..17294ce
--- /dev/null
+++ b/rc4/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/rc4/include/polly/Support/ScopHelper.h b/rc4/include/polly/Support/ScopHelper.h
new file mode 100644
index 0000000..9277c22
--- /dev/null
+++ b/rc4/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/rc4/include/polly/TempScopInfo.h b/rc4/include/polly/TempScopInfo.h
new file mode 100644
index 0000000..cc23ccc
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/Dependences.cpp b/rc4/lib/Analysis/Dependences.cpp
new file mode 100644
index 0000000..d4d092a
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/ScopDetection.cpp b/rc4/lib/Analysis/ScopDetection.cpp
new file mode 100644
index 0000000..abcf2c1
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/ScopDetectionDiagnostic.cpp b/rc4/lib/Analysis/ScopDetectionDiagnostic.cpp
new file mode 100644
index 0000000..fef69b3
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/ScopGraphPrinter.cpp b/rc4/lib/Analysis/ScopGraphPrinter.cpp
new file mode 100644
index 0000000..740e122
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/ScopInfo.cpp b/rc4/lib/Analysis/ScopInfo.cpp
new file mode 100644
index 0000000..b130099
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/ScopPass.cpp b/rc4/lib/Analysis/ScopPass.cpp
new file mode 100644
index 0000000..053f3d1
--- /dev/null
+++ b/rc4/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/rc4/lib/Analysis/TempScopInfo.cpp b/rc4/lib/Analysis/TempScopInfo.cpp
new file mode 100644
index 0000000..6f7a9d9
--- /dev/null
+++ b/rc4/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/rc4/lib/CMakeLists.txt b/rc4/lib/CMakeLists.txt
new file mode 100644
index 0000000..9625458
--- /dev/null
+++ b/rc4/lib/CMakeLists.txt
@@ -0,0 +1,68 @@
+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}
+ )
+
+# 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/rc4/lib/CodeGen/BlockGenerators.cpp b/rc4/lib/CodeGen/BlockGenerators.cpp
new file mode 100644
index 0000000..4c0762c
--- /dev/null
+++ b/rc4/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 <S,
+ 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 <S) {
+ // 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 <S) {
+ 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 <S) {
+ 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 <S) {
+ 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 <S) {
+ // 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 <S) {
+ 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/rc4/lib/CodeGen/IRBuilder.cpp b/rc4/lib/CodeGen/IRBuilder.cpp
new file mode 100644
index 0000000..cbd1626
--- /dev/null
+++ b/rc4/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/rc4/lib/CodeGen/IslAst.cpp b/rc4/lib/CodeGen/IslAst.cpp
new file mode 100644
index 0000000..d7973e4
--- /dev/null
+++ b/rc4/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/rc4/lib/CodeGen/IslCodeGeneration.cpp b/rc4/lib/CodeGen/IslCodeGeneration.cpp
new file mode 100644
index 0000000..935f0a7
--- /dev/null
+++ b/rc4/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 <S);
+ 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 <S) {
+ 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/rc4/lib/CodeGen/IslExprBuilder.cpp b/rc4/lib/CodeGen/IslExprBuilder.cpp
new file mode 100644
index 0000000..1dc2ba6
--- /dev/null
+++ b/rc4/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/rc4/lib/CodeGen/LoopGenerators.cpp b/rc4/lib/CodeGen/LoopGenerators.cpp
new file mode 100644
index 0000000..af04137
--- /dev/null
+++ b/rc4/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/rc4/lib/CodeGen/PTXGenerator.cpp b/rc4/lib/CodeGen/PTXGenerator.cpp
new file mode 100644
index 0000000..16da662
--- /dev/null
+++ b/rc4/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/rc4/lib/CodeGen/RuntimeDebugBuilder.cpp b/rc4/lib/CodeGen/RuntimeDebugBuilder.cpp
new file mode 100644
index 0000000..7794c91
--- /dev/null
+++ b/rc4/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/rc4/lib/CodeGen/Utils.cpp b/rc4/lib/CodeGen/Utils.cpp
new file mode 100644
index 0000000..8ea9a4a
--- /dev/null
+++ b/rc4/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/rc4/lib/Exchange/JSONExporter.cpp b/rc4/lib/Exchange/JSONExporter.cpp
new file mode 100644
index 0000000..21f7bf8
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/LICENSE.txt b/rc4/lib/JSON/LICENSE.txt
new file mode 100644
index 0000000..1c37b11
--- /dev/null
+++ b/rc4/lib/JSON/LICENSE.txt
@@ -0,0 +1 @@
+The json-cpp library and this documentation are in Public Domain.
diff --git a/rc4/lib/JSON/include/json/autolink.h b/rc4/lib/JSON/include/json/autolink.h
new file mode 100644
index 0000000..37c9258
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/include/json/config.h b/rc4/lib/JSON/include/json/config.h
new file mode 100644
index 0000000..b6dde91
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/include/json/features.h b/rc4/lib/JSON/include/json/features.h
new file mode 100644
index 0000000..5a9adec
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/include/json/forwards.h b/rc4/lib/JSON/include/json/forwards.h
new file mode 100644
index 0000000..d0ce830
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/include/json/json.h b/rc4/lib/JSON/include/json/json.h
new file mode 100644
index 0000000..c71ed65
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/include/json/reader.h b/rc4/lib/JSON/include/json/reader.h
new file mode 100644
index 0000000..0fea022
--- /dev/null
+++ b/rc4/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 ¤t,
+ Location end,
+ unsigned int &unicode );
+ bool decodeUnicodeEscapeSequence( Token &token,
+ Location ¤t,
+ 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 ¤tValue();
+ 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/rc4/lib/JSON/include/json/value.h b/rc4/lib/JSON/include/json/value.h
new file mode 100644
index 0000000..aa25e3b
--- /dev/null
+++ b/rc4/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 ¤t );
+#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 ¤t );
+#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 ¤t );
+#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/rc4/lib/JSON/include/json/writer.h b/rc4/lib/JSON/include/json/writer.h
new file mode 100644
index 0000000..83def71
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/json_batchallocator.h b/rc4/lib/JSON/json_batchallocator.h
new file mode 100644
index 0000000..87ea5ed
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/json_internalarray.inl b/rc4/lib/JSON/json_internalarray.inl
new file mode 100644
index 0000000..9b985d2
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/json_internalmap.inl b/rc4/lib/JSON/json_internalmap.inl
new file mode 100644
index 0000000..1977148
--- /dev/null
+++ b/rc4/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 ¤t->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 = ¤t->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/rc4/lib/JSON/json_reader.cpp b/rc4/lib/JSON/json_reader.cpp
new file mode 100644
index 0000000..680c2b6
--- /dev/null
+++ b/rc4/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_ = ¤tValue();
+ }
+
+ 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 ¤t,
+ 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 ¤t,
+ 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/rc4/lib/JSON/json_value.cpp b/rc4/lib/JSON/json_value.cpp
new file mode 100644
index 0000000..691e418
--- /dev/null
+++ b/rc4/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/rc4/lib/JSON/json_valueiterator.inl b/rc4/lib/JSON/json_valueiterator.inl
new file mode 100644
index 0000000..736e260
--- /dev/null
+++ b/rc4/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 ¤t )
+ : 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 ¤t )
+ : 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 ¤t )
+ : 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/rc4/lib/JSON/json_writer.cpp b/rc4/lib/JSON/json_writer.cpp
new file mode 100644
index 0000000..bf475c3
--- /dev/null
+++ b/rc4/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 *¤t )
+{
+ *--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/rc4/lib/JSON/sconscript b/rc4/lib/JSON/sconscript
new file mode 100644
index 0000000..6e7c6c8
--- /dev/null
+++ b/rc4/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/rc4/lib/Makefile b/rc4/lib/Makefile
new file mode 100644
index 0000000..eb9ed85
--- /dev/null
+++ b/rc4/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/rc4/lib/Polly.cpp b/rc4/lib/Polly.cpp
new file mode 100644
index 0000000..c879fd9
--- /dev/null
+++ b/rc4/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/rc4/lib/Support/GICHelper.cpp b/rc4/lib/Support/GICHelper.cpp
new file mode 100644
index 0000000..0b7abc2
--- /dev/null
+++ b/rc4/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/rc4/lib/Support/RegisterPasses.cpp b/rc4/lib/Support/RegisterPasses.cpp
new file mode 100644
index 0000000..47b6b61
--- /dev/null
+++ b/rc4/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/rc4/lib/Support/SCEVValidator.cpp b/rc4/lib/Support/SCEVValidator.cpp
new file mode 100644
index 0000000..40f1d91
--- /dev/null
+++ b/rc4/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/rc4/lib/Support/ScopHelper.cpp b/rc4/lib/Support/ScopHelper.cpp
new file mode 100644
index 0000000..1b7b9a2
--- /dev/null
+++ b/rc4/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/rc4/lib/Transform/Canonicalization.cpp b/rc4/lib/Transform/Canonicalization.cpp
new file mode 100644
index 0000000..40903c6
--- /dev/null
+++ b/rc4/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/rc4/lib/Transform/CodePreparation.cpp b/rc4/lib/Transform/CodePreparation.cpp
new file mode 100644
index 0000000..67e111b
--- /dev/null
+++ b/rc4/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/rc4/lib/Transform/DeadCodeElimination.cpp b/rc4/lib/Transform/DeadCodeElimination.cpp
new file mode 100644
index 0000000..497999f
--- /dev/null
+++ b/rc4/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/rc4/lib/Transform/IndependentBlocks.cpp b/rc4/lib/Transform/IndependentBlocks.cpp
new file mode 100644
index 0000000..f74c4b8
--- /dev/null
+++ b/rc4/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/rc4/lib/Transform/Pluto.cpp b/rc4/lib/Transform/Pluto.cpp
new file mode 100644
index 0000000..e0ab060
--- /dev/null
+++ b/rc4/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/rc4/lib/Transform/ScheduleOptimizer.cpp b/rc4/lib/Transform/ScheduleOptimizer.cpp
new file mode 100644
index 0000000..c8d9fe0
--- /dev/null
+++ b/rc4/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/rc4/test/CMakeLists.txt b/rc4/test/CMakeLists.txt
new file mode 100644
index 0000000..a31562b
--- /dev/null
+++ b/rc4/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/rc4/test/CodePreparation/if_condition.ll b/rc4/test/CodePreparation/if_condition.ll
new file mode 100644
index 0000000..d29d1df
--- /dev/null
+++ b/rc4/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/rc4/test/CodePreparation/multiple_loops_trivial_phis.ll b/rc4/test/CodePreparation/multiple_loops_trivial_phis.ll
new file mode 100644
index 0000000..f8964ae
--- /dev/null
+++ b/rc4/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/rc4/test/CodePreparation/single_loop_trivial_phi.ll b/rc4/test/CodePreparation/single_loop_trivial_phi.ll
new file mode 100644
index 0000000..e404da5
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/chained_iterations.ll b/rc4/test/DeadCodeElimination/chained_iterations.ll
new file mode 100644
index 0000000..5df2a59
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/chained_iterations_2.ll b/rc4/test/DeadCodeElimination/chained_iterations_2.ll
new file mode 100644
index 0000000..5c84057
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/computeout.ll b/rc4/test/DeadCodeElimination/computeout.ll
new file mode 100644
index 0000000..a908c4e
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/dead_iteration_elimination.ll b/rc4/test/DeadCodeElimination/dead_iteration_elimination.ll
new file mode 100644
index 0000000..8549a0c
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/non-affine-affine-mix.ll b/rc4/test/DeadCodeElimination/non-affine-affine-mix.ll
new file mode 100644
index 0000000..24b04a1
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/non-affine.ll b/rc4/test/DeadCodeElimination/non-affine.ll
new file mode 100644
index 0000000..5f9e953
--- /dev/null
+++ b/rc4/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/rc4/test/DeadCodeElimination/null_schedule.ll b/rc4/test/DeadCodeElimination/null_schedule.ll
new file mode 100644
index 0000000..106eac2
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/computeout.ll b/rc4/test/Dependences/computeout.ll
new file mode 100644
index 0000000..c2339d2
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/do_pluto_matmult.ll b/rc4/test/Dependences/do_pluto_matmult.ll
new file mode 100644
index 0000000..7d9799e
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_complex_location.ll b/rc4/test/Dependences/reduction_complex_location.ll
new file mode 100644
index 0000000..8ed46b7
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll b/rc4/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll
new file mode 100644
index 0000000..ef79880
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll b/rc4/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll
new file mode 100644
index 0000000..b114fe6
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_multiple_loops_array_sum.ll b/rc4/test/Dependences/reduction_multiple_loops_array_sum.ll
new file mode 100644
index 0000000..20903fb
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_multiple_loops_array_sum_2.ll b/rc4/test/Dependences/reduction_multiple_loops_array_sum_2.ll
new file mode 100644
index 0000000..3398292
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_multiple_loops_array_sum_3.ll b/rc4/test/Dependences/reduction_multiple_loops_array_sum_3.ll
new file mode 100644
index 0000000..4b699a1
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_multiple_reductions.ll b/rc4/test/Dependences/reduction_multiple_reductions.ll
new file mode 100644
index 0000000..461f9e4
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_multiple_reductions_2.ll b/rc4/test/Dependences/reduction_multiple_reductions_2.ll
new file mode 100644
index 0000000..6d1053b
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_only_reduction_like_access.ll b/rc4/test/Dependences/reduction_only_reduction_like_access.ll
new file mode 100644
index 0000000..c12949a
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_partially_escaping_intermediate_in_other_stmt.ll b/rc4/test/Dependences/reduction_partially_escaping_intermediate_in_other_stmt.ll
new file mode 100644
index 0000000..c48d8f0
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_privatization_deps.ll b/rc4/test/Dependences/reduction_privatization_deps.ll
new file mode 100644
index 0000000..a4f0895
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_privatization_deps_2.ll b/rc4/test/Dependences/reduction_privatization_deps_2.ll
new file mode 100644
index 0000000..979b0ea
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_privatization_deps_3.ll b/rc4/test/Dependences/reduction_privatization_deps_3.ll
new file mode 100644
index 0000000..8924492
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_privatization_deps_4.ll b/rc4/test/Dependences/reduction_privatization_deps_4.ll
new file mode 100644
index 0000000..190bd94
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_privatization_deps_5.ll b/rc4/test/Dependences/reduction_privatization_deps_5.ll
new file mode 100644
index 0000000..b6b4dbd
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_simple_iv.ll b/rc4/test/Dependences/reduction_simple_iv.ll
new file mode 100644
index 0000000..1dd9d51
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_simple_iv_debug_wrapped_dependences.ll b/rc4/test/Dependences/reduction_simple_iv_debug_wrapped_dependences.ll
new file mode 100644
index 0000000..eb255d6
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_simple_privatization_deps_2.ll b/rc4/test/Dependences/reduction_simple_privatization_deps_2.ll
new file mode 100644
index 0000000..46b32c0
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_simple_privatization_deps_w_parameter.ll b/rc4/test/Dependences/reduction_simple_privatization_deps_w_parameter.ll
new file mode 100644
index 0000000..f223619
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/reduction_two_reductions_different_rloops.ll b/rc4/test/Dependences/reduction_two_reductions_different_rloops.ll
new file mode 100644
index 0000000..4470e4e
--- /dev/null
+++ b/rc4/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/rc4/test/Dependences/sequential_loops.ll b/rc4/test/Dependences/sequential_loops.ll
new file mode 100644
index 0000000..772eb48
--- /dev/null
+++ b/rc4/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/rc4/test/IndependentBlocks/inter_bb_scalar_dep.ll b/rc4/test/IndependentBlocks/inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..376fe5e
--- /dev/null
+++ b/rc4/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/rc4/test/IndependentBlocks/intra_and_inter_bb_scalar_dep.ll b/rc4/test/IndependentBlocks/intra_and_inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..9f080fa
--- /dev/null
+++ b/rc4/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/rc4/test/IndependentBlocks/intra_bb_scalar_dep.ll b/rc4/test/IndependentBlocks/intra_bb_scalar_dep.ll
new file mode 100644
index 0000000..f167a89
--- /dev/null
+++ b/rc4/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/rc4/test/IndependentBlocks/phi_outside_scop.ll b/rc4/test/IndependentBlocks/phi_outside_scop.ll
new file mode 100644
index 0000000..f56b087
--- /dev/null
+++ b/rc4/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/rc4/test/IndependentBlocks/scalar_to_array.ll b/rc4/test/IndependentBlocks/scalar_to_array.ll
new file mode 100644
index 0000000..8358a87
--- /dev/null
+++ b/rc4/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/rc4/test/IndependentBlocks/scev-invalidated.ll b/rc4/test/IndependentBlocks/scev-invalidated.ll
new file mode 100644
index 0000000..0a95c87
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/multiple_loops_outer_parallel.ll b/rc4/test/Isl/Ast/OpenMP/multiple_loops_outer_parallel.ll
new file mode 100644
index 0000000..f7cea3d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/nested_loop_both_parallel.ll b/rc4/test/Isl/Ast/OpenMP/nested_loop_both_parallel.ll
new file mode 100644
index 0000000..08cfe0d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll b/rc4/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll
new file mode 100644
index 0000000..9bb8f24
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll b/rc4/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll
new file mode 100644
index 0000000..6626a5c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/nested_loop_outer_parallel.ll b/rc4/test/Isl/Ast/OpenMP/nested_loop_outer_parallel.ll
new file mode 100644
index 0000000..b8ca8ff
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/single_loop_param_non_parallel.ll b/rc4/test/Isl/Ast/OpenMP/single_loop_param_non_parallel.ll
new file mode 100644
index 0000000..1b6dd62
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll b/rc4/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll
new file mode 100644
index 0000000..1480579
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/OpenMP/single_loop_param_parallel_computeout.ll b/rc4/test/Isl/Ast/OpenMP/single_loop_param_parallel_computeout.ll
new file mode 100644
index 0000000..29a0bc4
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/alias_simple_1.ll b/rc4/test/Isl/Ast/alias_simple_1.ll
new file mode 100644
index 0000000..d66a896
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/alias_simple_2.ll b/rc4/test/Isl/Ast/alias_simple_2.ll
new file mode 100644
index 0000000..3c4f513
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/alias_simple_3.ll b/rc4/test/Isl/Ast/alias_simple_3.ll
new file mode 100644
index 0000000..10ff3f0
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/aliasing_multiple_alias_groups.ll b/rc4/test/Isl/Ast/aliasing_multiple_alias_groups.ll
new file mode 100644
index 0000000..a54a9cd
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/aliasing_parametric_simple_1.ll b/rc4/test/Isl/Ast/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..64bf9af
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/aliasing_parametric_simple_2.ll b/rc4/test/Isl/Ast/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..e8add3a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_constant.ll b/rc4/test/Isl/Ast/dependence_distance_constant.ll
new file mode 100644
index 0000000..36eec43
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_multiple_constant.ll b/rc4/test/Isl/Ast/dependence_distance_multiple_constant.ll
new file mode 100644
index 0000000..f7a9ba5
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_parametric.ll b/rc4/test/Isl/Ast/dependence_distance_parametric.ll
new file mode 100644
index 0000000..4478662
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_parametric_expr.ll b/rc4/test/Isl/Ast/dependence_distance_parametric_expr.ll
new file mode 100644
index 0000000..d225fad
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_varying.ll b/rc4/test/Isl/Ast/dependence_distance_varying.ll
new file mode 100644
index 0000000..3d9bdb0
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_varying_in_outer_loop.ll b/rc4/test/Isl/Ast/dependence_distance_varying_in_outer_loop.ll
new file mode 100644
index 0000000..932612e
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/dependence_distance_varying_multiple.ll b/rc4/test/Isl/Ast/dependence_distance_varying_multiple.ll
new file mode 100644
index 0000000..23a261a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_clauses_multidimensional_access.ll b/rc4/test/Isl/Ast/reduction_clauses_multidimensional_access.ll
new file mode 100644
index 0000000..3ecc54a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_clauses_onedimensional_access.ll b/rc4/test/Isl/Ast/reduction_clauses_onedimensional_access.ll
new file mode 100644
index 0000000..a5143c7
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_dependences_equal_non_reduction_dependences.ll b/rc4/test/Isl/Ast/reduction_dependences_equal_non_reduction_dependences.ll
new file mode 100644
index 0000000..1c84308
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_different_reduction_clauses.ll b/rc4/test/Isl/Ast/reduction_different_reduction_clauses.ll
new file mode 100644
index 0000000..664692e
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_in_one_dimension.ll b/rc4/test/Isl/Ast/reduction_in_one_dimension.ll
new file mode 100644
index 0000000..ed21d61
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_loop_reversal.ll b/rc4/test/Isl/Ast/reduction_loop_reversal.ll
new file mode 100644
index 0000000..25ee3d7
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule.ll b/rc4/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule.ll
new file mode 100644
index 0000000..0285dbb
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule_2.ll b/rc4/test/Isl/Ast/reduction_modulo_and_loop_reversal_schedule_2.ll
new file mode 100644
index 0000000..7d99cc9
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_schedule.ll b/rc4/test/Isl/Ast/reduction_modulo_schedule.ll
new file mode 100644
index 0000000..f4dfef6
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll b/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll
new file mode 100644
index 0000000..4360ea6
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll b/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll
new file mode 100644
index 0000000..5b33b4e
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll b/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll
new file mode 100644
index 0000000..52bc242
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll b/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll
new file mode 100644
index 0000000..1ecc549
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_5.ll b/rc4/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_5.ll
new file mode 100644
index 0000000..23b26a2
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_multiple_dimensions.ll b/rc4/test/Isl/Ast/reduction_multiple_dimensions.ll
new file mode 100644
index 0000000..aefc507
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_multiple_dimensions_2.ll b/rc4/test/Isl/Ast/reduction_multiple_dimensions_2.ll
new file mode 100644
index 0000000..404040f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_multiple_dimensions_3.ll b/rc4/test/Isl/Ast/reduction_multiple_dimensions_3.ll
new file mode 100644
index 0000000..b37b9a5
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/reduction_multiple_dimensions_4.ll b/rc4/test/Isl/Ast/reduction_multiple_dimensions_4.ll
new file mode 100644
index 0000000..3445dbe
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rlr___%for.cond---%for.end10.jscop b/rc4/test/Isl/Ast/rlr___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..fc50d5c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmalrs2___%for.cond---%for.end10.jscop b/rc4/test/Isl/Ast/rmalrs2___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..c84f0a0
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmalrs___%for.cond---%for.end10.jscop b/rc4/test/Isl/Ast/rmalrs___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..9740b57
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmd2___%for.cond---%for.end12.jscop b/rc4/test/Isl/Ast/rmd2___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..bca9793
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmd3___%for.cond---%for.end12.jscop b/rc4/test/Isl/Ast/rmd3___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..7cd7570
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmd4___%for.cond---%for.end12.jscop b/rc4/test/Isl/Ast/rmd4___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..b29c322
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmd___%for.cond---%for.end12.jscop b/rc4/test/Isl/Ast/rmd___%for.cond---%for.end12.jscop
new file mode 100644
index 0000000..be7cdc2
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rms___%for.cond---%for.end10.jscop b/rc4/test/Isl/Ast/rms___%for.cond---%for.end10.jscop
new file mode 100644
index 0000000..15a6930
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmsmd2___%for.cond---%for.end6.jscop b/rc4/test/Isl/Ast/rmsmd2___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..38cb44b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmsmd3___%for.cond---%for.end6.jscop b/rc4/test/Isl/Ast/rmsmd3___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..44d71a3
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmsmd4___%for.cond---%for.end6.jscop b/rc4/test/Isl/Ast/rmsmd4___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..9bfd4aa
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmsmd5___%for.cond---%for.end6.jscop b/rc4/test/Isl/Ast/rmsmd5___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..ee1c3dd
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/rmsmd___%for.cond---%for.end6.jscop b/rc4/test/Isl/Ast/rmsmd___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..8a8678a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/run-time-condition.ll b/rc4/test/Isl/Ast/run-time-condition.ll
new file mode 100644
index 0000000..fedada1
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/simple-run-time-condition.ll b/rc4/test/Isl/Ast/simple-run-time-condition.ll
new file mode 100644
index 0000000..9bf52f2
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/single_loop_strip_mine.ll b/rc4/test/Isl/Ast/single_loop_strip_mine.ll
new file mode 100644
index 0000000..e61c2a8
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/Ast/single_loop_strip_mine___%for.cond---%for.end.jscop b/rc4/test/Isl/Ast/single_loop_strip_mine___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..7dcf837
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100617.ll b/rc4/test/Isl/CodeGen/20100617.ll
new file mode 100644
index 0000000..d34b43a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100622.ll b/rc4/test/Isl/CodeGen/20100622.ll
new file mode 100644
index 0000000..2e02404
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100707.ll b/rc4/test/Isl/CodeGen/20100707.ll
new file mode 100644
index 0000000..c34e668
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100707_2.ll b/rc4/test/Isl/CodeGen/20100707_2.ll
new file mode 100644
index 0000000..fb1e85b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100708.ll b/rc4/test/Isl/CodeGen/20100708.ll
new file mode 100644
index 0000000..3d660e5
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100708_2.ll b/rc4/test/Isl/CodeGen/20100708_2.ll
new file mode 100644
index 0000000..9b758f1
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100713.ll b/rc4/test/Isl/CodeGen/20100713.ll
new file mode 100644
index 0000000..54714fd
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100713_2.ll b/rc4/test/Isl/CodeGen/20100713_2.ll
new file mode 100644
index 0000000..5d59e85
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100717.ll b/rc4/test/Isl/CodeGen/20100717.ll
new file mode 100644
index 0000000..5652ff2
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100718-DomInfo-2.ll b/rc4/test/Isl/CodeGen/20100718-DomInfo-2.ll
new file mode 100644
index 0000000..a51d3e3
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100718-DomInfo.ll b/rc4/test/Isl/CodeGen/20100718-DomInfo.ll
new file mode 100644
index 0000000..afc9db0
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100720-MultipleConditions.ll b/rc4/test/Isl/CodeGen/20100720-MultipleConditions.ll
new file mode 100644
index 0000000..ba28c32
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100809-IndependentBlock.ll b/rc4/test/Isl/CodeGen/20100809-IndependentBlock.ll
new file mode 100644
index 0000000..2cafc00
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll b/rc4/test/Isl/CodeGen/20100811-ScalarDependencyBetweenBrAndCnd.ll
new file mode 100644
index 0000000..e975995
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20101030-Overflow.ll b/rc4/test/Isl/CodeGen/20101030-Overflow.ll
new file mode 100644
index 0000000..9303c26
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20101103-Overflow3.ll b/rc4/test/Isl/CodeGen/20101103-Overflow3.ll
new file mode 100644
index 0000000..11661b0
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20101103-signmissmatch.ll b/rc4/test/Isl/CodeGen/20101103-signmissmatch.ll
new file mode 100644
index 0000000..48bb30d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20110226-Ignore-Dead-Code.ll b/rc4/test/Isl/CodeGen/20110226-Ignore-Dead-Code.ll
new file mode 100644
index 0000000..f890a85
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20110226-PHI-Node-removed.ll b/rc4/test/Isl/CodeGen/20110226-PHI-Node-removed.ll
new file mode 100644
index 0000000..a786530
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20110312-Fail-without-basicaa.ll b/rc4/test/Isl/CodeGen/20110312-Fail-without-basicaa.ll
new file mode 100644
index 0000000..d1936ff
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20120316-InvalidCast.ll b/rc4/test/Isl/CodeGen/20120316-InvalidCast.ll
new file mode 100644
index 0000000..e3f09b6
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20120403-RHS-type-mismatch.ll b/rc4/test/Isl/CodeGen/20120403-RHS-type-mismatch.ll
new file mode 100644
index 0000000..fd797ca
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20130211-getNumberOfIterations.ll b/rc4/test/Isl/CodeGen/20130211-getNumberOfIterations.ll
new file mode 100644
index 0000000..ce2a984
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/20130221.ll b/rc4/test/Isl/CodeGen/20130221.ll
new file mode 100644
index 0000000..22a079c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll b/rc4/test/Isl/CodeGen/LoopParallelMD/do_not_mutate_debug_info.ll
new file mode 100644
index 0000000..f3b3551
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll b/rc4/test/Isl/CodeGen/LoopParallelMD/loop_nest_param_parallel.ll
new file mode 100644
index 0000000..a0afac3
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/LoopParallelMD/single_loop_param_parallel.ll b/rc4/test/Isl/CodeGen/LoopParallelMD/single_loop_param_parallel.ll
new file mode 100644
index 0000000..28858c0
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/bad_alignment.ll b/rc4/test/Isl/CodeGen/MemAccess/bad_alignment.ll
new file mode 100644
index 0000000..aeff96a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/bad_alignment___%for.cond---%for.end.jscop b/rc4/test/Isl/CodeGen/MemAccess/bad_alignment___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..7f4fb66
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_constant_offset.ll b/rc4/test/Isl/CodeGen/MemAccess/codegen_constant_offset.ll
new file mode 100644
index 0000000..36dbf12
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop b/rc4/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..034183d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop.transformed b/rc4/test/Isl/CodeGen/MemAccess/codegen_constant_offset___%for.cond---%for.end.jscop.transformed
new file mode 100644
index 0000000..424137c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple.ll b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple.ll
new file mode 100644
index 0000000..0afcff8
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..034183d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop.transformed b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple___%for.cond---%for.end.jscop.transformed
new file mode 100644
index 0000000..320c3cb
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll
new file mode 100644
index 0000000..ccc01df
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md.ll b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md.ll
new file mode 100644
index 0000000..6d1de11
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop
new file mode 100644
index 0000000..180c44f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withconst b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withconst
new file mode 100644
index 0000000..0894776
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withoutconst b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md___%for.cond---%for.end6.jscop.transformed+withoutconst
new file mode 100644
index 0000000..e1fa4ed
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll b/rc4/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll
new file mode 100644
index 0000000..7db1e1f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/default_aligned_new_access_function.ll b/rc4/test/Isl/CodeGen/MemAccess/default_aligned_new_access_function.ll
new file mode 100644
index 0000000..9e89550
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple.ll b/rc4/test/Isl/CodeGen/MemAccess/simple.ll
new file mode 100644
index 0000000..f665652
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop b/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..4742285
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop.transformed b/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end.jscop.transformed
new file mode 100644
index 0000000..0a33fe8
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop b/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop
new file mode 100644
index 0000000..88fafec
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed b/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed
new file mode 100644
index 0000000..b1808f1
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop b/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop
new file mode 100644
index 0000000..56289bf
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop.transformed b/rc4/test/Isl/CodeGen/MemAccess/simple___%for.cond4---%for.end14.jscop.transformed
new file mode 100644
index 0000000..6152943
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple_analyze.ll b/rc4/test/Isl/CodeGen/MemAccess/simple_analyze.ll
new file mode 100644
index 0000000..2ebf7eb
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple_stride___%for.cond---%for.end.jscop b/rc4/test/Isl/CodeGen/MemAccess/simple_stride___%for.cond---%for.end.jscop
new file mode 100644
index 0000000..0fe6461
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/MemAccess/simple_stride_test.ll b/rc4/test/Isl/CodeGen/MemAccess/simple_stride_test.ll
new file mode 100644
index 0000000..7ca8fc5
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-iv.ll b/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-iv.ll
new file mode 100644
index 0000000..9226d60
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-2.ll b/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-2.ll
new file mode 100644
index 0000000..2593228
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-3.ll b/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values-3.ll
new file mode 100644
index 0000000..7ecc27d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values.ll b/rc4/test/Isl/CodeGen/OpenMP/loop-body-references-outer-values.ll
new file mode 100644
index 0000000..1a31995
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll b/rc4/test/Isl/CodeGen/OpenMP/loop-bounds-reference-outer-ids.ll
new file mode 100644
index 0000000..222e45b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/reference-other-bb.ll b/rc4/test/Isl/CodeGen/OpenMP/reference-other-bb.ll
new file mode 100644
index 0000000..aaecff7
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/reference-preceeding-loop.ll b/rc4/test/Isl/CodeGen/OpenMP/reference-preceeding-loop.ll
new file mode 100644
index 0000000..54f89e1
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/single_loop.ll b/rc4/test/Isl/CodeGen/OpenMP/single_loop.ll
new file mode 100644
index 0000000..8b211c3
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll b/rc4/test/Isl/CodeGen/OpenMP/single_loop_with_loop_invariant_baseptr.ll
new file mode 100644
index 0000000..7a4192f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/single_parallel_loop___%for.i---%exit.jscop b/rc4/test/Isl/CodeGen/OpenMP/single_parallel_loop___%for.i---%exit.jscop
new file mode 100644
index 0000000..971f196
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll b/rc4/test/Isl/CodeGen/OpenMP/two-parallel-loops-reference-outer-indvar.ll
new file mode 100644
index 0000000..f861209
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/PHIInExit.ll b/rc4/test/Isl/CodeGen/PHIInExit.ll
new file mode 100644
index 0000000..7753dba
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/aliasing_different_base_and_access_type.ll b/rc4/test/Isl/CodeGen/aliasing_different_base_and_access_type.ll
new file mode 100644
index 0000000..3ab242d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/aliasing_different_pointer_types.ll b/rc4/test/Isl/CodeGen/aliasing_different_pointer_types.ll
new file mode 100644
index 0000000..90e8d2b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/aliasing_multidimensional_access.ll b/rc4/test/Isl/CodeGen/aliasing_multidimensional_access.ll
new file mode 100644
index 0000000..95238af
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/aliasing_parametric_simple_1.ll b/rc4/test/Isl/CodeGen/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..1e716f3
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/aliasing_parametric_simple_2.ll b/rc4/test/Isl/CodeGen/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..2665134
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/aliasing_struct_element.ll b/rc4/test/Isl/CodeGen/aliasing_struct_element.ll
new file mode 100644
index 0000000..cb75d2e
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/alignment.ll b/rc4/test/Isl/CodeGen/alignment.ll
new file mode 100644
index 0000000..f4038c9
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/annotated_alias_scopes.ll b/rc4/test/Isl/CodeGen/annotated_alias_scopes.ll
new file mode 100644
index 0000000..d1a2655
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/blas_sscal_simplified.ll b/rc4/test/Isl/CodeGen/blas_sscal_simplified.ll
new file mode 100644
index 0000000..af847b6
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/constant_condition.ll b/rc4/test/Isl/CodeGen/constant_condition.ll
new file mode 100644
index 0000000..c62d59a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/create-conditional-scop.ll b/rc4/test/Isl/CodeGen/create-conditional-scop.ll
new file mode 100644
index 0000000..d0e6e94
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/debug-intrinsics.ll b/rc4/test/Isl/CodeGen/debug-intrinsics.ll
new file mode 100644
index 0000000..53c48ef
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/loop_with_condition.ll b/rc4/test/Isl/CodeGen/loop_with_condition.ll
new file mode 100644
index 0000000..d8e0ab9
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/loop_with_condition_2.ll b/rc4/test/Isl/CodeGen/loop_with_condition_2.ll
new file mode 100644
index 0000000..fc75121
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/loop_with_condition_ineq.ll b/rc4/test/Isl/CodeGen/loop_with_condition_ineq.ll
new file mode 100644
index 0000000..df923bc
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/loop_with_condition_nested.ll b/rc4/test/Isl/CodeGen/loop_with_condition_nested.ll
new file mode 100644
index 0000000..5d4a61c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/loop_with_conditional_entry_edge_splited_hard_case.ll b/rc4/test/Isl/CodeGen/loop_with_conditional_entry_edge_splited_hard_case.ll
new file mode 100644
index 0000000..997a24c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll b/rc4/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll
new file mode 100644
index 0000000..a49151c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/multidim_alias_check.ll b/rc4/test/Isl/CodeGen/multidim_alias_check.ll
new file mode 100644
index 0000000..e692f27
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/no_guard_bb.ll b/rc4/test/Isl/CodeGen/no_guard_bb.ll
new file mode 100644
index 0000000..b5bf88b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/openmp_limit_threads.ll b/rc4/test/Isl/CodeGen/openmp_limit_threads.ll
new file mode 100644
index 0000000..fff0155
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/reduction.ll b/rc4/test/Isl/CodeGen/reduction.ll
new file mode 100644
index 0000000..d40e3bc
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/reduction_2.ll b/rc4/test/Isl/CodeGen/reduction_2.ll
new file mode 100644
index 0000000..1bcff98
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/reduction_simple_binary.ll b/rc4/test/Isl/CodeGen/reduction_simple_binary.ll
new file mode 100644
index 0000000..2d2812b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll b/rc4/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll
new file mode 100644
index 0000000..a4dbbcd
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/run-time-condition.ll b/rc4/test/Isl/CodeGen/run-time-condition.ll
new file mode 100644
index 0000000..77af3a4
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/scalar-references-used-in-scop-compute.ll b/rc4/test/Isl/CodeGen/scalar-references-used-in-scop-compute.ll
new file mode 100644
index 0000000..fdf9139
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/scev.ll b/rc4/test/Isl/CodeGen/scev.ll
new file mode 100644
index 0000000..7bfe862
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/scop_never_executed_runtime_check_location.ll b/rc4/test/Isl/CodeGen/scop_never_executed_runtime_check_location.ll
new file mode 100644
index 0000000..5a31940
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/sequential_loops.ll b/rc4/test/Isl/CodeGen/sequential_loops.ll
new file mode 100644
index 0000000..51d7613
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_loop_non_single_exit.ll b/rc4/test/Isl/CodeGen/simple_loop_non_single_exit.ll
new file mode 100644
index 0000000..ab4c2b9
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_loop_non_single_exit_2.ll b/rc4/test/Isl/CodeGen/simple_loop_non_single_exit_2.ll
new file mode 100644
index 0000000..4f09802
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_non_single_entry.ll b/rc4/test/Isl/CodeGen/simple_non_single_entry.ll
new file mode 100644
index 0000000..c0c90ec
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_nonaffine_loop.ll b/rc4/test/Isl/CodeGen/simple_nonaffine_loop.ll
new file mode 100644
index 0000000..bfed04b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_assign_scalar.ll b/rc4/test/Isl/CodeGen/simple_vec_assign_scalar.ll
new file mode 100644
index 0000000..df91b6c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_assign_scalar_2.ll b/rc4/test/Isl/CodeGen/simple_vec_assign_scalar_2.ll
new file mode 100644
index 0000000..7aa9d61
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_call.ll b/rc4/test/Isl/CodeGen/simple_vec_call.ll
new file mode 100644
index 0000000..6a77824
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_call_2.ll b/rc4/test/Isl/CodeGen/simple_vec_call_2.ll
new file mode 100644
index 0000000..ee7f50e
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_cast.ll b/rc4/test/Isl/CodeGen/simple_vec_cast.ll
new file mode 100644
index 0000000..f13d06b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_const.ll b/rc4/test/Isl/CodeGen/simple_vec_const.ll
new file mode 100644
index 0000000..df40ccc
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_large_width.ll b/rc4/test/Isl/CodeGen/simple_vec_large_width.ll
new file mode 100644
index 0000000..0ec8650
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_ptr_ptr_ty.ll b/rc4/test/Isl/CodeGen/simple_vec_ptr_ptr_ty.ll
new file mode 100644
index 0000000..cca14df
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_stride_negative_one.ll b/rc4/test/Isl/CodeGen/simple_vec_stride_negative_one.ll
new file mode 100644
index 0000000..30398e8
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_stride_x.ll b/rc4/test/Isl/CodeGen/simple_vec_stride_x.ll
new file mode 100644
index 0000000..7f56abe
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/simple_vec_two_stmts.ll b/rc4/test/Isl/CodeGen/simple_vec_two_stmts.ll
new file mode 100644
index 0000000..b77ab23
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_do_loop_int_max_iterations.ll b/rc4/test/Isl/CodeGen/single_do_loop_int_max_iterations.ll
new file mode 100644
index 0000000..081d323
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_do_loop_int_max_iterations___%do.body---%do.end.jscop b/rc4/test/Isl/CodeGen/single_do_loop_int_max_iterations___%do.body---%do.end.jscop
new file mode 100644
index 0000000..fcd78fc
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_do_loop_int_param_iterations.ll b/rc4/test/Isl/CodeGen/single_do_loop_int_param_iterations.ll
new file mode 100644
index 0000000..7a8d4cf
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_do_loop_ll_max_iterations.ll b/rc4/test/Isl/CodeGen/single_do_loop_ll_max_iterations.ll
new file mode 100644
index 0000000..365ac07
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_do_loop_one_iteration.ll b/rc4/test/Isl/CodeGen/single_do_loop_one_iteration.ll
new file mode 100644
index 0000000..f8afce7
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_do_loop_scev_replace.ll b/rc4/test/Isl/CodeGen/single_do_loop_scev_replace.ll
new file mode 100644
index 0000000..a5b8ed8
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_loop.ll b/rc4/test/Isl/CodeGen/single_loop.ll
new file mode 100644
index 0000000..c80e225
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_loop_int_max_iterations.ll b/rc4/test/Isl/CodeGen/single_loop_int_max_iterations.ll
new file mode 100644
index 0000000..c76c18a
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_loop_ll_max_iterations.ll b/rc4/test/Isl/CodeGen/single_loop_ll_max_iterations.ll
new file mode 100644
index 0000000..7d34b2f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_loop_one_iteration.ll b/rc4/test/Isl/CodeGen/single_loop_one_iteration.ll
new file mode 100644
index 0000000..9e973a9
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_loop_param.ll b/rc4/test/Isl/CodeGen/single_loop_param.ll
new file mode 100644
index 0000000..402b683
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/single_loop_zero_iterations.ll b/rc4/test/Isl/CodeGen/single_loop_zero_iterations.ll
new file mode 100644
index 0000000..e4c336c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/split_edges.ll b/rc4/test/Isl/CodeGen/split_edges.ll
new file mode 100644
index 0000000..93ffa9b
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/split_edges_2.ll b/rc4/test/Isl/CodeGen/split_edges_2.ll
new file mode 100644
index 0000000..386845f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/test-invalid-operands-for-select-2.ll b/rc4/test/Isl/CodeGen/test-invalid-operands-for-select-2.ll
new file mode 100644
index 0000000..fd8589d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/test-invalid-operands-for-select.ll b/rc4/test/Isl/CodeGen/test-invalid-operands-for-select.ll
new file mode 100644
index 0000000..b838b5c
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/test.ll b/rc4/test/Isl/CodeGen/test.ll
new file mode 100644
index 0000000..6b76682
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/CodeGen/two-scops-in-row.ll b/rc4/test/Isl/CodeGen/two-scops-in-row.ll
new file mode 100644
index 0000000..e4e4270
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/single_loop_param_less_equal.ll b/rc4/test/Isl/single_loop_param_less_equal.ll
new file mode 100644
index 0000000..5d6f733
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/single_loop_param_less_than.ll b/rc4/test/Isl/single_loop_param_less_than.ll
new file mode 100644
index 0000000..b8a673d
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/single_loop_uint_max_iterations.ll b/rc4/test/Isl/single_loop_uint_max_iterations.ll
new file mode 100644
index 0000000..de1982f
--- /dev/null
+++ b/rc4/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/rc4/test/Isl/single_loop_ull_max_iterations.ll b/rc4/test/Isl/single_loop_ull_max_iterations.ll
new file mode 100644
index 0000000..78e1b86
--- /dev/null
+++ b/rc4/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/rc4/test/Makefile b/rc4/test/Makefile
new file mode 100644
index 0000000..bab51fe
--- /dev/null
+++ b/rc4/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/rc4/test/README b/rc4/test/README
new file mode 100644
index 0000000..e8470c6
--- /dev/null
+++ b/rc4/test/README
@@ -0,0 +1 @@
+place tests here
\ No newline at end of file
diff --git a/rc4/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll b/rc4/test/ScheduleOptimizer/2012-03-16-Empty-Domain.ll
new file mode 100644
index 0000000..1df2d84
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/2012-04-16-Trivially-vectorizable-loops.ll b/rc4/test/ScheduleOptimizer/2012-04-16-Trivially-vectorizable-loops.ll
new file mode 100644
index 0000000..71b82f7
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/2012-10-14-Zero-Bands.ll b/rc4/test/ScheduleOptimizer/2012-10-14-Zero-Bands.ll
new file mode 100644
index 0000000..894d57d
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll b/rc4/test/ScheduleOptimizer/2013-04-11-Empty-Domain-two.ll
new file mode 100644
index 0000000..e81033a
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/computeout.ll b/rc4/test/ScheduleOptimizer/computeout.ll
new file mode 100644
index 0000000..578478c
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/line-tiling-2.ll b/rc4/test/ScheduleOptimizer/line-tiling-2.ll
new file mode 100644
index 0000000..7b4aa9c
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/line-tiling.ll b/rc4/test/ScheduleOptimizer/line-tiling.ll
new file mode 100644
index 0000000..b9d1f8e
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/prevectorization.ll b/rc4/test/ScheduleOptimizer/prevectorization.ll
new file mode 100644
index 0000000..8eb7511
--- /dev/null
+++ b/rc4/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/rc4/test/ScheduleOptimizer/rectangular-tiling.ll b/rc4/test/ScheduleOptimizer/rectangular-tiling.ll
new file mode 100644
index 0000000..e2e21ba
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/aliasing_parametric_simple_1.ll b/rc4/test/ScopDetect/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..dcd4241
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/aliasing_parametric_simple_2.ll b/rc4/test/ScopDetect/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..8016f74
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/aliasing_simple_1.ll b/rc4/test/ScopDetect/aliasing_simple_1.ll
new file mode 100644
index 0000000..ec16930
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/aliasing_simple_2.ll b/rc4/test/ScopDetect/aliasing_simple_2.ll
new file mode 100644
index 0000000..79c1600
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/base_pointer.ll b/rc4/test/ScopDetect/base_pointer.ll
new file mode 100644
index 0000000..92c76cd
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/cross_loop_non_single_exit.ll b/rc4/test/ScopDetect/cross_loop_non_single_exit.ll
new file mode 100644
index 0000000..cedee28
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/cross_loop_non_single_exit_2.ll b/rc4/test/ScopDetect/cross_loop_non_single_exit_2.ll
new file mode 100644
index 0000000..f6c16d6
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll b/rc4/test/ScopDetect/dependency_to_phi_node_outside_of_region.ll
new file mode 100644
index 0000000..2a67dd6
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/indvars.ll b/rc4/test/ScopDetect/indvars.ll
new file mode 100644
index 0000000..432ad10
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/invalidate_scalar_evolution.ll b/rc4/test/ScopDetect/invalidate_scalar_evolution.ll
new file mode 100644
index 0000000..314c79c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/keep_going_expansion.ll b/rc4/test/ScopDetect/keep_going_expansion.ll
new file mode 100644
index 0000000..9cdecfa
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/multidim_two_accesses_different_delinearization.ll b/rc4/test/ScopDetect/multidim_two_accesses_different_delinearization.ll
new file mode 100644
index 0000000..ebddf3f
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/nested_loop_single_exit.ll b/rc4/test/ScopDetect/nested_loop_single_exit.ll
new file mode 100644
index 0000000..5a616d7
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/parametric-multiply-in-scev.ll b/rc4/test/ScopDetect/parametric-multiply-in-scev.ll
new file mode 100644
index 0000000..3234822
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/remove_all_children.ll b/rc4/test/ScopDetect/remove_all_children.ll
new file mode 100644
index 0000000..2c01701
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/report-scop-location.ll b/rc4/test/ScopDetect/report-scop-location.ll
new file mode 100644
index 0000000..5c5bfda
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/run_time_alias_check.ll b/rc4/test/ScopDetect/run_time_alias_check.ll
new file mode 100644
index 0000000..15b1c9b
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/sequential_loops.ll b/rc4/test/ScopDetect/sequential_loops.ll
new file mode 100644
index 0000000..b9526bf
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop.ll b/rc4/test/ScopDetect/simple_loop.ll
new file mode 100644
index 0000000..9670f4e
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop_non_single_entry.ll b/rc4/test/ScopDetect/simple_loop_non_single_entry.ll
new file mode 100644
index 0000000..346bf1c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop_non_single_exit.ll b/rc4/test/ScopDetect/simple_loop_non_single_exit.ll
new file mode 100644
index 0000000..270336c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop_non_single_exit_2.ll b/rc4/test/ScopDetect/simple_loop_non_single_exit_2.ll
new file mode 100644
index 0000000..9201739
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop_two_phi_nodes.ll b/rc4/test/ScopDetect/simple_loop_two_phi_nodes.ll
new file mode 100644
index 0000000..249deb3
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop_with_param.ll b/rc4/test/ScopDetect/simple_loop_with_param.ll
new file mode 100644
index 0000000..aa5a9b3
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_loop_with_param_2.ll b/rc4/test/ScopDetect/simple_loop_with_param_2.ll
new file mode 100644
index 0000000..15ec620
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/simple_non_single_entry.ll b/rc4/test/ScopDetect/simple_non_single_entry.ll
new file mode 100644
index 0000000..7465971
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetect/skip_function_attribute.ll b/rc4/test/ScopDetect/skip_function_attribute.ll
new file mode 100644
index 0000000..9d181fe
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportAlias-01.ll b/rc4/test/ScopDetectionDiagnostics/ReportAlias-01.ll
new file mode 100644
index 0000000..ad65128
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll b/rc4/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll
new file mode 100644
index 0000000..040e343
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll b/rc4/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll
new file mode 100644
index 0000000..823c487
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll b/rc4/test/ScopDetectionDiagnostics/ReportLoopBound-01.ll
new file mode 100644
index 0000000..1d24864
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll b/rc4/test/ScopDetectionDiagnostics/ReportMultipleNonAffineAccesses.ll
new file mode 100644
index 0000000..4e6727e
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll b/rc4/test/ScopDetectionDiagnostics/ReportNonAffineAccess-01.ll
new file mode 100644
index 0000000..dab633b
--- /dev/null
+++ b/rc4/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/rc4/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll b/rc4/test/ScopDetectionDiagnostics/ReportVariantBasePtr-01.ll
new file mode 100644
index 0000000..eb6cd8b
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/20111108-Parameter-not-detected.ll b/rc4/test/ScopInfo/20111108-Parameter-not-detected.ll
new file mode 100644
index 0000000..c4f62ea
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll b/rc4/test/ScopInfo/2012-03-16-Crash-because-of-unsigned-in-scev.ll
new file mode 100644
index 0000000..64cff17
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/Alias-0.ll b/rc4/test/ScopInfo/Alias-0.ll
new file mode 100644
index 0000000..5faa9b6
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/Alias-1.ll b/rc4/test/ScopInfo/Alias-1.ll
new file mode 100644
index 0000000..aeb0c15
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/Alias-2.ll b/rc4/test/ScopInfo/Alias-2.ll
new file mode 100644
index 0000000..cd27ebf
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/Alias-3.ll b/rc4/test/ScopInfo/Alias-3.ll
new file mode 100644
index 0000000..440ea55
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/Alias-4.ll b/rc4/test/ScopInfo/Alias-4.ll
new file mode 100644
index 0000000..85a6158
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/aliasing_conditional_alias_groups_1.ll b/rc4/test/ScopInfo/aliasing_conditional_alias_groups_1.ll
new file mode 100644
index 0000000..0614af3
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/aliasing_conditional_alias_groups_2.ll b/rc4/test/ScopInfo/aliasing_conditional_alias_groups_2.ll
new file mode 100644
index 0000000..7b5660c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/aliasing_dead_access.ll b/rc4/test/ScopInfo/aliasing_dead_access.ll
new file mode 100644
index 0000000..b59e196
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll b/rc4/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll
new file mode 100644
index 0000000..fe36741
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/aliasing_multiple_alias_groups.ll b/rc4/test/ScopInfo/aliasing_multiple_alias_groups.ll
new file mode 100644
index 0000000..b656de5
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/assume_gep_bounds.ll b/rc4/test/ScopInfo/assume_gep_bounds.ll
new file mode 100644
index 0000000..8422dad
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/assume_gep_bounds_2.ll b/rc4/test/ScopInfo/assume_gep_bounds_2.ll
new file mode 100644
index 0000000..3c27e53
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/bug_2010_10_22.ll b/rc4/test/ScopInfo/bug_2010_10_22.ll
new file mode 100644
index 0000000..54b0a5f
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/bug_2011_1_5.ll b/rc4/test/ScopInfo/bug_2011_1_5.ll
new file mode 100644
index 0000000..9253d5a
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/bug_scev_not_fully_eval.ll b/rc4/test/ScopInfo/bug_scev_not_fully_eval.ll
new file mode 100644
index 0000000..fa8098c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/cond_constant_in_loop.ll b/rc4/test/ScopInfo/cond_constant_in_loop.ll
new file mode 100644
index 0000000..a71ec46
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/cond_in_loop.ll b/rc4/test/ScopInfo/cond_in_loop.ll
new file mode 100644
index 0000000..55ab6dc
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/constant_start_integer.ll b/rc4/test/ScopInfo/constant_start_integer.ll
new file mode 100644
index 0000000..f28b9d8
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/delinearize-together-all-data-refs.ll b/rc4/test/ScopInfo/delinearize-together-all-data-refs.ll
new file mode 100644
index 0000000..fc98b2e
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/independent-blocks-never-stop-on-big-scop.ll b/rc4/test/ScopInfo/independent-blocks-never-stop-on-big-scop.ll
new file mode 100644
index 0000000..871f9ec
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/integers.ll b/rc4/test/ScopInfo/integers.ll
new file mode 100644
index 0000000..f36bf1f
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/isl_aff_out_of_bounds.ll b/rc4/test/ScopInfo/isl_aff_out_of_bounds.ll
new file mode 100644
index 0000000..94dc395
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/loop_affine_bound_0.ll b/rc4/test/ScopInfo/loop_affine_bound_0.ll
new file mode 100644
index 0000000..6f5778b
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/loop_affine_bound_1.ll b/rc4/test/ScopInfo/loop_affine_bound_1.ll
new file mode 100644
index 0000000..3c2fe35
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/loop_affine_bound_2.ll b/rc4/test/ScopInfo/loop_affine_bound_2.ll
new file mode 100644
index 0000000..f686c78
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/loop_carry.ll b/rc4/test/ScopInfo/loop_carry.ll
new file mode 100644
index 0000000..d72316c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/max-loop-depth.ll b/rc4/test/ScopInfo/max-loop-depth.ll
new file mode 100644
index 0000000..3e0f806
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multi-scop.ll b/rc4/test/ScopInfo/multi-scop.ll
new file mode 100644
index 0000000..09998a3
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_2d-diagonal-matrix.ll b/rc4/test/ScopInfo/multidim_2d-diagonal-matrix.ll
new file mode 100644
index 0000000..964724a
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_2d_outer_parametric_offset.ll b/rc4/test/ScopInfo/multidim_2d_outer_parametric_offset.ll
new file mode 100644
index 0000000..176cbfe
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll b/rc4/test/ScopInfo/multidim_2d_parametric_array_static_loop_bounds.ll
new file mode 100644
index 0000000..f19d649
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll b/rc4/test/ScopInfo/multidim_3d_parametric_array_static_loop_bounds.ll
new file mode 100644
index 0000000..08a17d7
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll b/rc4/test/ScopInfo/multidim_ivs_and_integer_offsets_3d.ll
new file mode 100644
index 0000000..d275457
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll b/rc4/test/ScopInfo/multidim_ivs_and_parameteric_offsets_3d.ll
new file mode 100644
index 0000000..8b17ab0
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_nested_start_integer.ll b/rc4/test/ScopInfo/multidim_nested_start_integer.ll
new file mode 100644
index 0000000..bd78a76
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_nested_start_share_parameter.ll b/rc4/test/ScopInfo/multidim_nested_start_share_parameter.ll
new file mode 100644
index 0000000..76ca349
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_only_ivs_2d.ll b/rc4/test/ScopInfo/multidim_only_ivs_2d.ll
new file mode 100644
index 0000000..1c8b363
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_only_ivs_3d.ll b/rc4/test/ScopInfo/multidim_only_ivs_3d.ll
new file mode 100644
index 0000000..6d682a7
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_only_ivs_3d_cast.ll b/rc4/test/ScopInfo/multidim_only_ivs_3d_cast.ll
new file mode 100644
index 0000000..2dd2f1b
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_only_ivs_3d_reverse.ll b/rc4/test/ScopInfo/multidim_only_ivs_3d_reverse.ll
new file mode 100644
index 0000000..babe759
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/multidim_single_and_multidim_array.ll b/rc4/test/ScopInfo/multidim_single_and_multidim_array.ll
new file mode 100644
index 0000000..1190b20
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/non_affine_access.ll b/rc4/test/ScopInfo/non_affine_access.ll
new file mode 100644
index 0000000..f06ad6f
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/non_affine_parametric_loop.ll b/rc4/test/ScopInfo/non_affine_parametric_loop.ll
new file mode 100644
index 0000000..d78f18c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/parameter_product.ll b/rc4/test/ScopInfo/parameter_product.ll
new file mode 100644
index 0000000..2bd9793
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/phi_not_grouped_at_top.ll b/rc4/test/ScopInfo/phi_not_grouped_at_top.ll
new file mode 100644
index 0000000..49613ab
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/phi_with_invoke_edge.ll b/rc4/test/ScopInfo/phi_with_invoke_edge.ll
new file mode 100644
index 0000000..8fb74e6
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_alternating_base.ll b/rc4/test/ScopInfo/reduction_alternating_base.ll
new file mode 100644
index 0000000..ce98f01
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll b/rc4/test/ScopInfo/reduction_chain_partially_outside_the_scop.ll
new file mode 100644
index 0000000..42d768e
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_disabled_multiplicative.ll b/rc4/test/ScopInfo/reduction_disabled_multiplicative.ll
new file mode 100644
index 0000000..5e32129
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_escaping_intermediate.ll b/rc4/test/ScopInfo/reduction_escaping_intermediate.ll
new file mode 100644
index 0000000..2c4f74c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_escaping_intermediate_2.ll b/rc4/test/ScopInfo/reduction_escaping_intermediate_2.ll
new file mode 100644
index 0000000..2d8c09e
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_invalid_different_operators.ll b/rc4/test/ScopInfo/reduction_invalid_different_operators.ll
new file mode 100644
index 0000000..9f477fe
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_invalid_overlapping_accesses.ll b/rc4/test/ScopInfo/reduction_invalid_overlapping_accesses.ll
new file mode 100644
index 0000000..2c765f7
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_multiple_loops_array_sum.ll b/rc4/test/ScopInfo/reduction_multiple_loops_array_sum.ll
new file mode 100644
index 0000000..d61f521
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll b/rc4/test/ScopInfo/reduction_multiple_loops_array_sum_1.ll
new file mode 100644
index 0000000..19147fe
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_multiple_simple_binary.ll b/rc4/test/ScopInfo/reduction_multiple_simple_binary.ll
new file mode 100644
index 0000000..c701ed1
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_non_overlapping_chains.ll b/rc4/test/ScopInfo/reduction_non_overlapping_chains.ll
new file mode 100644
index 0000000..e9399ba
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_only_reduction_like_access.ll b/rc4/test/ScopInfo/reduction_only_reduction_like_access.ll
new file mode 100644
index 0000000..f0009ae
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_simple_fp.ll b/rc4/test/ScopInfo/reduction_simple_fp.ll
new file mode 100644
index 0000000..7918fcb
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_simple_w_constant.ll b/rc4/test/ScopInfo/reduction_simple_w_constant.ll
new file mode 100644
index 0000000..2cecb4d
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_simple_w_iv.ll b/rc4/test/ScopInfo/reduction_simple_w_iv.ll
new file mode 100644
index 0000000..982983c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/reduction_two_identical_reads.ll b/rc4/test/ScopInfo/reduction_two_identical_reads.ll
new file mode 100644
index 0000000..1d71d7d
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/run-time-check-many-parameters.ll b/rc4/test/ScopInfo/run-time-check-many-parameters.ll
new file mode 100644
index 0000000..65971b4
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/run-time-check-read-only-arrays.ll b/rc4/test/ScopInfo/run-time-check-read-only-arrays.ll
new file mode 100644
index 0000000..9d81337
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/scalar.ll b/rc4/test/ScopInfo/scalar.ll
new file mode 100644
index 0000000..5541b4c
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/simple_loop_1.ll b/rc4/test/ScopInfo/simple_loop_1.ll
new file mode 100644
index 0000000..10d248b
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/simple_nonaffine_loop_not.ll b/rc4/test/ScopInfo/simple_nonaffine_loop_not.ll
new file mode 100644
index 0000000..979eb15
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/smax.ll b/rc4/test/ScopInfo/smax.ll
new file mode 100644
index 0000000..73998df
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/undef_in_cond.ll b/rc4/test/ScopInfo/undef_in_cond.ll
new file mode 100644
index 0000000..815968e
--- /dev/null
+++ b/rc4/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/rc4/test/ScopInfo/unsigned-condition.ll b/rc4/test/ScopInfo/unsigned-condition.ll
new file mode 100644
index 0000000..407ede9
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/inter_bb_scalar_dep.ll b/rc4/test/TempScop/inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..4a7ceab
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/intra_and_inter_bb_scalar_dep.ll b/rc4/test/TempScop/intra_and_inter_bb_scalar_dep.ll
new file mode 100644
index 0000000..d9c8885
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/intra_bb_scalar_dep.ll b/rc4/test/TempScop/intra_bb_scalar_dep.ll
new file mode 100644
index 0000000..ce60978
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/nested-loops.ll b/rc4/test/TempScop/nested-loops.ll
new file mode 100644
index 0000000..318b5b8
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/not-a-reduction.ll b/rc4/test/TempScop/not-a-reduction.ll
new file mode 100644
index 0000000..1e1e328
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/scalar_to_array.ll b/rc4/test/TempScop/scalar_to_array.ll
new file mode 100644
index 0000000..d12b0e6
--- /dev/null
+++ b/rc4/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/rc4/test/TempScop/tempscop-printing.ll b/rc4/test/TempScop/tempscop-printing.ll
new file mode 100644
index 0000000..04b5c67
--- /dev/null
+++ b/rc4/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/rc4/test/create_ll.sh b/rc4/test/create_ll.sh
new file mode 100755
index 0000000..b0b56be
--- /dev/null
+++ b/rc4/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/rc4/test/lit.cfg b/rc4/test/lit.cfg
new file mode 100644
index 0000000..0d7eb3b
--- /dev/null
+++ b/rc4/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/rc4/test/lit.site.cfg.in b/rc4/test/lit.site.cfg.in
new file mode 100644
index 0000000..768a0e0
--- /dev/null
+++ b/rc4/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/rc4/test/polly.ll b/rc4/test/polly.ll
new file mode 100644
index 0000000..da2ef0e
--- /dev/null
+++ b/rc4/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/rc4/tools/CMakeLists.txt b/rc4/tools/CMakeLists.txt
new file mode 100644
index 0000000..4ce60e1
--- /dev/null
+++ b/rc4/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/rc4/tools/GPURuntime/CMakeLists.txt b/rc4/tools/GPURuntime/CMakeLists.txt
new file mode 100644
index 0000000..822e4de
--- /dev/null
+++ b/rc4/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/rc4/tools/GPURuntime/GPUJIT.c b/rc4/tools/GPURuntime/GPUJIT.c
new file mode 100644
index 0000000..a03ebe9
--- /dev/null
+++ b/rc4/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/rc4/tools/GPURuntime/GPUJIT.h b/rc4/tools/GPURuntime/GPUJIT.h
new file mode 100644
index 0000000..5ed41ce
--- /dev/null
+++ b/rc4/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/rc4/tools/GPURuntime/LICENSE.TXT b/rc4/tools/GPURuntime/LICENSE.TXT
new file mode 100644
index 0000000..e2461ab
--- /dev/null
+++ b/rc4/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/rc4/tools/GPURuntime/Makefile b/rc4/tools/GPURuntime/Makefile
new file mode 100644
index 0000000..4822f70
--- /dev/null
+++ b/rc4/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/rc4/tools/Makefile b/rc4/tools/Makefile
new file mode 100644
index 0000000..21b6a42
--- /dev/null
+++ b/rc4/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/rc4/utils/arcanist/LitTestEngine/__phutil_library_init__.php b/rc4/utils/arcanist/LitTestEngine/__phutil_library_init__.php
new file mode 100644
index 0000000..72dd4a7
--- /dev/null
+++ b/rc4/utils/arcanist/LitTestEngine/__phutil_library_init__.php
@@ -0,0 +1,3 @@
+<?php
+
+phutil_register_library('lit-test-engine', __FILE__);
diff --git a/rc4/utils/arcanist/LitTestEngine/__phutil_library_map__.php b/rc4/utils/arcanist/LitTestEngine/__phutil_library_map__.php
new file mode 100644
index 0000000..6607226
--- /dev/null
+++ b/rc4/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/rc4/utils/arcanist/LitTestEngine/src/LitTestEngine.php b/rc4/utils/arcanist/LitTestEngine/src/LitTestEngine.php
new file mode 100644
index 0000000..eb495be
--- /dev/null
+++ b/rc4/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/rc4/utils/argparse.py b/rc4/utils/argparse.py
new file mode 100644
index 0000000..a060129
--- /dev/null
+++ b/rc4/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/rc4/utils/check_format.sh b/rc4/utils/check_format.sh
new file mode 100755
index 0000000..4d7b033
--- /dev/null
+++ b/rc4/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/rc4/utils/checkout_cloog.sh b/rc4/utils/checkout_cloog.sh
new file mode 120000
index 0000000..40ad1b8
--- /dev/null
+++ b/rc4/utils/checkout_cloog.sh
@@ -0,0 +1 @@
+checkout_isl.sh
\ No newline at end of file
diff --git a/rc4/utils/checkout_isl.sh b/rc4/utils/checkout_isl.sh
new file mode 100755
index 0000000..ac7dc6f
--- /dev/null
+++ b/rc4/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/rc4/utils/jscop2cloog.py b/rc4/utils/jscop2cloog.py
new file mode 100755
index 0000000..668f085
--- /dev/null
+++ b/rc4/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/rc4/utils/pyscop/isl.py b/rc4/utils/pyscop/isl.py
new file mode 100644
index 0000000..0c8de2f
--- /dev/null
+++ b/rc4/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/rc4/utils/pyscop/jscop2iscc.py b/rc4/utils/pyscop/jscop2iscc.py
new file mode 100755
index 0000000..3267e8e
--- /dev/null
+++ b/rc4/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/rc4/utils/pyscop/pyscop.py b/rc4/utils/pyscop/pyscop.py
new file mode 100644
index 0000000..a7c3481
--- /dev/null
+++ b/rc4/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/rc4/utils/update_format.sh b/rc4/utils/update_format.sh
new file mode 100755
index 0000000..9226fc6
--- /dev/null
+++ b/rc4/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/rc4/www/.htaccess b/rc4/www/.htaccess
new file mode 100644
index 0000000..bfd0afc
--- /dev/null
+++ b/rc4/www/.htaccess
@@ -0,0 +1 @@
+AddHandler server-parsed .html
diff --git a/rc4/www/bugs.html b/rc4/www/bugs.html
new file mode 100644
index 0000000..87254a8
--- /dev/null
+++ b/rc4/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/rc4/www/changelog.html b/rc4/www/changelog.html
new file mode 100644
index 0000000..f9d1530
--- /dev/null
+++ b/rc4/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/rc4/www/content.css b/rc4/www/content.css
new file mode 100644
index 0000000..549b2a9
--- /dev/null
+++ b/rc4/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/rc4/www/contributors.html b/rc4/www/contributors.html
new file mode 100644
index 0000000..83c64f5
--- /dev/null
+++ b/rc4/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ü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/rc4/www/documentation.html b/rc4/www/documentation.html
new file mode 100644
index 0000000..eddf1cf
--- /dev/null
+++ b/rc4/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/rc4/www/documentation/architecture.html b/rc4/www/documentation/architecture.html
new file mode 100644
index 0000000..aa1c80f
--- /dev/null
+++ b/rc4/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/rc4/www/documentation/gpgpucodegen.html b/rc4/www/documentation/gpgpucodegen.html
new file mode 100644
index 0000000..7118171
--- /dev/null
+++ b/rc4/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 < 128; i++)
+ for(j = 0; j < 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] -> scattering[0, i0, 0, i1, 0] }"
+</pre>
+The jscop file describing the tiling transformation is:
+<pre>
+"schedule" : "{ Stmt_for_body3[i0, i1] -> scattering[0, o0, o1, o2, o3]:
+ o0 >= 0 and o0 <= 7 and o1 >= 0 and o1 <= 15 and
+ o2 >= 0 and o2 <= 7 and o3 >= 0 and o3 <= 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<=7;c2++) {
+ for (c3=0;c3<=15;c3++) {
+ for (c4=0;c4<=7;c4++) {
+ for (c5=0;c5<=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/rc4/www/documentation/memaccess.html b/rc4/www/documentation/memaccess.html
new file mode 100644
index 0000000..fa48771
--- /dev/null
+++ b/rc4/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/rc4/www/documentation/passes.html b/rc4/www/documentation/passes.html
new file mode 100644
index 0000000..c0c727d
--- /dev/null
+++ b/rc4/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/rc4/www/example_load_Polly_into_clang.html b/rc4/www/example_load_Polly_into_clang.html
new file mode 100644
index 0000000..a43e5bf
--- /dev/null
+++ b/rc4/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/rc4/www/example_load_Polly_into_dragonegg.html b/rc4/www/example_load_Polly_into_dragonegg.html
new file mode 100644
index 0000000..ef9f68b
--- /dev/null
+++ b/rc4/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/rc4/www/example_manual_matmul.html b/rc4/www/example_manual_matmul.html
new file mode 100644
index 0000000..5aa5934
--- /dev/null
+++ b/rc4/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 > 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<=1023;c2++) {
+ for (c4=0;c4<=1023;c4++) {
+ Stmt_5(c2,c4);
+ }
+}
+
+main():
+for (c2=0;c2<=1023;c2++) {
+ for (c4=0;c4<=1023;c4++) {
+ Stmt_4(c2,c4);
+ for (c6=0;c6<=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 => for.end19' in function 'init_array':
+ Context:
+ { [] }
+ Statements {
+ Stmt_5
+ Domain :=
+ { Stmt_5[i0, i1] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 };
+ Scattering :=
+ { Stmt_5[i0, i1] -> scattering[0, i0, 0, i1, 0] };
+ WriteAccess :=
+ { Stmt_5[i0, i1] -> MemRef_A[1037i0 + i1] };
+ WriteAccess :=
+ { Stmt_5[i0, i1] -> MemRef_B[1047i0 + i1] };
+ FinalRead
+ Domain :=
+ { FinalRead[0] };
+ Scattering :=
+ { FinalRead[i0] -> scattering[200000000, o1, o2, o3, o4] };
+ ReadAccess :=
+ { FinalRead[i0] -> MemRef_A[o0] };
+ ReadAccess :=
+ { FinalRead[i0] -> MemRef_B[o0] };
+ }
+[...]
+Printing analysis 'Polly - Create polyhedral description of Scops' for region:
+'for.cond => for.end30' in function 'main':
+ Context:
+ { [] }
+ Statements {
+ Stmt_4
+ Domain :=
+ { Stmt_4[i0, i1] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 };
+ Scattering :=
+ { Stmt_4[i0, i1] -> scattering[0, i0, 0, i1, 0, 0, 0] };
+ WriteAccess :=
+ { Stmt_4[i0, i1] -> MemRef_C[1067i0 + i1] };
+ Stmt_6
+ Domain :=
+ { Stmt_6[i0, i1, i2] : i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1023 };
+ Scattering :=
+ { Stmt_6[i0, i1, i2] -> scattering[0, i0, 0, i1, 1, i2, 0] };
+ ReadAccess :=
+ { Stmt_6[i0, i1, i2] -> MemRef_C[1067i0 + i1] };
+ ReadAccess :=
+ { Stmt_6[i0, i1, i2] -> MemRef_A[1037i0 + i2] };
+ ReadAccess :=
+ { Stmt_6[i0, i1, i2] -> MemRef_B[i1 + 1047i2] };
+ WriteAccess :=
+ { Stmt_6[i0, i1, i2] -> MemRef_C[1067i0 + i1] };
+ FinalRead
+ Domain :=
+ { FinalRead[0] };
+ Scattering :=
+ { FinalRead[i0] -> scattering[200000000, o1, o2, o3, o4, o5, o6] };
+ ReadAccess :=
+ { FinalRead[i0] -> MemRef_C[o0] };
+ ReadAccess :=
+ { FinalRead[i0] -> MemRef_A[o0] };
+ ReadAccess :=
+ { FinalRead[i0] -> 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 => 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 => for.end30' in function 'main':
+ Must dependences:
+ { Stmt_4[i0, i1] -> Stmt_6[i0, i1, 0] :
+ i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023;
+ Stmt_6[i0, i1, i2] -> Stmt_6[i0, i1, 1 + i2] :
+ i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1022;
+ Stmt_6[i0, i1, 1023] -> FinalRead[0] :
+ i1 <= 1091540 - 1067i0 and i1 >= -1067i0 and i1 >= 0 and i1 <= 1023;
+ Stmt_6[1023, i1, 1023] -> FinalRead[0] :
+ i1 >= 0 and i1 <= 1023
+ }
+ May dependences:
+ { }
+ Must no source:
+ { Stmt_6[i0, i1, i2] -> MemRef_A[1037i0 + i2] :
+ i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1023;
+ Stmt_6[i0, i1, i2] -> MemRef_B[i1 + 1047i2] :
+ i0 >= 0 and i0 <= 1023 and i1 >= 0 and i1 <= 1023 and i2 >= 0 and i2 <= 1023;
+ FinalRead[0] -> MemRef_A[o0];
+ FinalRead[0] -> MemRef_B[o0]
+ FinalRead[0] -> MemRef_C[o0] :
+ o0 >= 1092565 or (exists (e0 = [(o0)/1067]: o0 <= 1091540 and o0 >= 0
+ and 1067e0 <= -1024 + o0 and 1067e0 >= -1066 + o0)) or o0 <= -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 => for.end19' in function 'init_array' to './init_array___%for.cond---%for.end19.jscop'.
+Writing SCoP 'for.cond => 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<g;=1535;c2++) {
+ for (c4=0;c4<g;=1535;c4++) {
+ Stmt_4(c2,c4);
+ for (c6=0;c6<g;=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 => for.end30' in function 'main' from './main___%for.cond---%for.end30.jscop.interchanged+tiled'.
+[...]
+main():
+for (c2=0;c2<=1535;c2++) {
+ for (c4=0;c4<=1535;c4++) {
+ Stmt_4(c2,c4);
+ }
+}
+for (c2=0;c2<=1535;c2++) {
+ for (c4=0;c4<=1535;c4++) {
+ for (c6=0;c6<=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 => for.end30' in function 'main' from './main___%for.cond---%for.end30.jscop.interchanged+tiled'.
+[...]
+main():
+for (c2=0;c2<=1535;c2++) {
+ for (c4=0;c4<=1535;c4++) {
+ Stmt_4(c2,c4);
+ }
+}
+for (c2=0;c2<=1535;c2+=64) {
+ for (c3=0;c3<=1535;c3+=64) {
+ for (c4=0;c4<=1535;c4+=64) {
+ for (c5=c2;c5<=c2+63;c5++) {
+ for (c6=c4;c6<=c4+63;c6++) {
+ for (c7=c3;c7<=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 => for.end30' in function 'main' from './main___%for.cond---%for.end30.jscop.interchanged+tiled+vector'.
+[...]
+main():
+for (c2=0;c2<=1535;c2++) {
+ for (c4=0;c4<=1535;c4++) {
+ Stmt_4(c2,c4);
+ }
+}
+for (c2=0;c2<=1535;c2+=64) {
+ for (c3=0;c3<=1535;c3+=64) {
+ for (c4=0;c4<=1535;c4+=64) {
+ for (c5=c2;c5<=c2+63;c5++) {
+ for (c6=c4;c6<=c4+63;c6++) {
+ for (c7=c3;c7<=c3+63;c7+=4) {
+ for (c8=c7;c8<=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 > matmul.normalopt.ll</pre>
+<pre class="code">
+opt -basicaa \
+ -polly-import-jscop -polly-import-jscop-postfix=interchanged \
+ -polly-codegen matmul.preopt.ll \
+ | opt -O3 > matmul.polly.interchanged.ll</pre>
+<pre>
+Reading JScop 'for.cond => 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 => 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 > matmul.polly.interchanged+tiled.ll</pre>
+<pre>
+Reading JScop 'for.cond => 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 => 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 > matmul.polly.interchanged+tiled+vector.ll</pre>
+<pre>
+Reading JScop 'for.cond => 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 => 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 > matmul.polly.interchanged+tiled+openmp.ll</pre>
+<pre>
+Reading JScop 'for.cond => 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 => 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 && \
+ gcc matmul.normalopt.s -o matmul.normalopt.exe
+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 </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/rc4/www/examples.html b/rc4/www/examples.html
new file mode 100644
index 0000000..c8ceb65
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/init_array___%for.cond---%for.end19.jscop b/rc4/www/experiments/matmul/init_array___%for.cond---%for.end19.jscop
new file mode 100644
index 0000000..dfd1093
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop b/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop
new file mode 100644
index 0000000..4d6e463
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged b/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged
new file mode 100644
index 0000000..1d73c8a
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled b/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled
new file mode 100644
index 0000000..ab68b5e
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled+vector b/rc4/www/experiments/matmul/main___%for.cond---%for.end30.jscop.interchanged+tiled+vector
new file mode 100644
index 0000000..67a1cd9
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.c b/rc4/www/experiments/matmul/matmul.c
new file mode 100644
index 0000000..edb2455
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.normalopt.exe b/rc4/www/experiments/matmul/matmul.normalopt.exe
new file mode 100755
index 0000000..cdb9e67
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.normalopt.exe
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.normalopt.ll b/rc4/www/experiments/matmul/matmul.normalopt.ll
new file mode 100644
index 0000000..ba792c2
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.normalopt.ll
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.normalopt.s b/rc4/www/experiments/matmul/matmul.normalopt.s
new file mode 100644
index 0000000..079af70
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.exe b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.exe
new file mode 100755
index 0000000..feb2436
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.exe
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.ll b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.ll
new file mode 100644
index 0000000..593794e
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.ll
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.s b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector+openmp.s
new file mode 100644
index 0000000..ca87de1
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.exe b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.exe
new file mode 100755
index 0000000..36b788e
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.exe
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.ll b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.ll
new file mode 100644
index 0000000..9d1f9ad
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.ll
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.s b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled+vector.s
new file mode 100644
index 0000000..485d230
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.exe b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.exe
new file mode 100755
index 0000000..fbd8b12
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.exe
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.ll b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.ll
new file mode 100644
index 0000000..acdd95f
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.ll
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.s b/rc4/www/experiments/matmul/matmul.polly.interchanged+tiled.s
new file mode 100644
index 0000000..f7ab7fd
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.polly.interchanged.exe b/rc4/www/experiments/matmul/matmul.polly.interchanged.exe
new file mode 100755
index 0000000..240c95a
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged.exe
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged.ll b/rc4/www/experiments/matmul/matmul.polly.interchanged.ll
new file mode 100644
index 0000000..52fbccc
--- /dev/null
+++ b/rc4/www/experiments/matmul/matmul.polly.interchanged.ll
Binary files differ
diff --git a/rc4/www/experiments/matmul/matmul.polly.interchanged.s b/rc4/www/experiments/matmul/matmul.polly.interchanged.s
new file mode 100644
index 0000000..a764da0
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.preopt.ll b/rc4/www/experiments/matmul/matmul.preopt.ll
new file mode 100644
index 0000000..3931716
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/matmul.s b/rc4/www/experiments/matmul/matmul.s
new file mode 100644
index 0000000..22ea57b
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/runall.sh b/rc4/www/experiments/matmul/runall.sh
new file mode 100755
index 0000000..77ef6b4
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scops.init_array.dot b/rc4/www/experiments/matmul/scops.init_array.dot
new file mode 100644
index 0000000..10a0add
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scops.init_array.dot.png b/rc4/www/experiments/matmul/scops.init_array.dot.png
new file mode 100644
index 0000000..48a9f38
--- /dev/null
+++ b/rc4/www/experiments/matmul/scops.init_array.dot.png
Binary files differ
diff --git a/rc4/www/experiments/matmul/scops.main.dot b/rc4/www/experiments/matmul/scops.main.dot
new file mode 100644
index 0000000..2a1fc50
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scops.main.dot.png b/rc4/www/experiments/matmul/scops.main.dot.png
new file mode 100644
index 0000000..4e73701
--- /dev/null
+++ b/rc4/www/experiments/matmul/scops.main.dot.png
Binary files differ
diff --git a/rc4/www/experiments/matmul/scops.print_array.dot b/rc4/www/experiments/matmul/scops.print_array.dot
new file mode 100644
index 0000000..59f02e7
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scops.print_array.dot.png b/rc4/www/experiments/matmul/scops.print_array.dot.png
new file mode 100644
index 0000000..e3b973b
--- /dev/null
+++ b/rc4/www/experiments/matmul/scops.print_array.dot.png
Binary files differ
diff --git a/rc4/www/experiments/matmul/scopsonly.init_array.dot b/rc4/www/experiments/matmul/scopsonly.init_array.dot
new file mode 100644
index 0000000..4685c5b
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scopsonly.init_array.dot.png b/rc4/www/experiments/matmul/scopsonly.init_array.dot.png
new file mode 100644
index 0000000..f101d4d
--- /dev/null
+++ b/rc4/www/experiments/matmul/scopsonly.init_array.dot.png
Binary files differ
diff --git a/rc4/www/experiments/matmul/scopsonly.main.dot b/rc4/www/experiments/matmul/scopsonly.main.dot
new file mode 100644
index 0000000..3b3f328
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scopsonly.main.dot.png b/rc4/www/experiments/matmul/scopsonly.main.dot.png
new file mode 100644
index 0000000..3263424
--- /dev/null
+++ b/rc4/www/experiments/matmul/scopsonly.main.dot.png
Binary files differ
diff --git a/rc4/www/experiments/matmul/scopsonly.print_array.dot b/rc4/www/experiments/matmul/scopsonly.print_array.dot
new file mode 100644
index 0000000..c900d0f
--- /dev/null
+++ b/rc4/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/rc4/www/experiments/matmul/scopsonly.print_array.dot.png b/rc4/www/experiments/matmul/scopsonly.print_array.dot.png
new file mode 100644
index 0000000..b0d4b45
--- /dev/null
+++ b/rc4/www/experiments/matmul/scopsonly.print_array.dot.png
Binary files differ
diff --git a/rc4/www/favicon.ico b/rc4/www/favicon.ico
new file mode 100644
index 0000000..0638d5b
--- /dev/null
+++ b/rc4/www/favicon.ico
Binary files differ
diff --git a/rc4/www/get_started.html b/rc4/www/get_started.html
new file mode 100644
index 0000000..087a631
--- /dev/null
+++ b/rc4/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 && 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/rc4/www/images/architecture.png b/rc4/www/images/architecture.png
new file mode 100644
index 0000000..fdd26a0
--- /dev/null
+++ b/rc4/www/images/architecture.png
Binary files differ
diff --git a/rc4/www/images/header-background.png b/rc4/www/images/header-background.png
new file mode 100644
index 0000000..d736b99
--- /dev/null
+++ b/rc4/www/images/header-background.png
Binary files differ
diff --git a/rc4/www/images/iit-madras.png b/rc4/www/images/iit-madras.png
new file mode 100644
index 0000000..caf90ab
--- /dev/null
+++ b/rc4/www/images/iit-madras.png
Binary files differ
diff --git a/rc4/www/images/osu.png b/rc4/www/images/osu.png
new file mode 100644
index 0000000..154a04b
--- /dev/null
+++ b/rc4/www/images/osu.png
Binary files differ
diff --git a/rc4/www/images/performance/parallel-large.png b/rc4/www/images/performance/parallel-large.png
new file mode 100644
index 0000000..76261bb
--- /dev/null
+++ b/rc4/www/images/performance/parallel-large.png
Binary files differ
diff --git a/rc4/www/images/performance/parallel-small.png b/rc4/www/images/performance/parallel-small.png
new file mode 100644
index 0000000..3c9f6ba
--- /dev/null
+++ b/rc4/www/images/performance/parallel-small.png
Binary files differ
diff --git a/rc4/www/images/performance/sequential-large.png b/rc4/www/images/performance/sequential-large.png
new file mode 100644
index 0000000..5c88354
--- /dev/null
+++ b/rc4/www/images/performance/sequential-large.png
Binary files differ
diff --git a/rc4/www/images/performance/sequential-small.png b/rc4/www/images/performance/sequential-small.png
new file mode 100644
index 0000000..94b248d
--- /dev/null
+++ b/rc4/www/images/performance/sequential-small.png
Binary files differ
diff --git a/rc4/www/images/sys-uni.png b/rc4/www/images/sys-uni.png
new file mode 100644
index 0000000..e6b84e1
--- /dev/null
+++ b/rc4/www/images/sys-uni.png
Binary files differ
diff --git a/rc4/www/images/uni-passau.png b/rc4/www/images/uni-passau.png
new file mode 100644
index 0000000..4bbfa21
--- /dev/null
+++ b/rc4/www/images/uni-passau.png
Binary files differ
diff --git a/rc4/www/images/video-summit-2011.png b/rc4/www/images/video-summit-2011.png
new file mode 100644
index 0000000..dc72e7c
--- /dev/null
+++ b/rc4/www/images/video-summit-2011.png
Binary files differ
diff --git a/rc4/www/index.html b/rc4/www/index.html
new file mode 100644
index 0000000..bd869ed
--- /dev/null
+++ b/rc4/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/rc4/www/menu.css b/rc4/www/menu.css
new file mode 100644
index 0000000..a3e3ad7
--- /dev/null
+++ b/rc4/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/rc4/www/menu.html.incl b/rc4/www/menu.html.incl
new file mode 100644
index 0000000..44fab67
--- /dev/null
+++ b/rc4/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&rec=1" style="border:0" alt="" />
+</noscript>
+
diff --git a/rc4/www/performance.html b/rc4/www/performance.html
new file mode 100644
index 0000000..300a188
--- /dev/null
+++ b/rc4/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/rc4/www/phonecall.html b/rc4/www/phonecall.html
new file mode 100644
index 0000000..53f1a92
--- /dev/null
+++ b/rc4/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/rc4/www/polly.sh b/rc4/www/polly.sh
new file mode 100644
index 0000000..ae4c480
--- /dev/null
+++ b/rc4/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/rc4/www/publications.html b/rc4/www/publications.html
new file mode 100644
index 0000000..90d34a2
--- /dev/null
+++ b/rc4/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ürger, Armin
+ Größlinger, Louis-Noë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é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öß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ël Pouchet, Cé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ël Pouchet, Cé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ël Pouchet, Albert Cohen,
+ Cé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/rc4/www/publications/grosser-diploma-thesis.pdf b/rc4/www/publications/grosser-diploma-thesis.pdf
new file mode 100644
index 0000000..f7e8dd3
--- /dev/null
+++ b/rc4/www/publications/grosser-diploma-thesis.pdf
Binary files differ
diff --git a/rc4/www/publications/grosser-impact-2011-slides.pdf b/rc4/www/publications/grosser-impact-2011-slides.pdf
new file mode 100644
index 0000000..3e60410
--- /dev/null
+++ b/rc4/www/publications/grosser-impact-2011-slides.pdf
Binary files differ
diff --git a/rc4/www/publications/grosser-impact-2011.pdf b/rc4/www/publications/grosser-impact-2011.pdf
new file mode 100644
index 0000000..9b79bd2
--- /dev/null
+++ b/rc4/www/publications/grosser-impact-2011.pdf
Binary files differ
diff --git a/rc4/www/publications/kernelgen-ncar-2012-slides.pdf b/rc4/www/publications/kernelgen-ncar-2012-slides.pdf
new file mode 100644
index 0000000..8a91611
--- /dev/null
+++ b/rc4/www/publications/kernelgen-ncar-2012-slides.pdf
Binary files differ
diff --git a/rc4/www/publications/kernelgen-pavt-2012-slides.pdf b/rc4/www/publications/kernelgen-pavt-2012-slides.pdf
new file mode 100644
index 0000000..ce4b832
--- /dev/null
+++ b/rc4/www/publications/kernelgen-pavt-2012-slides.pdf
Binary files differ
diff --git a/rc4/www/publications/raghesh-a-masters-thesis.pdf b/rc4/www/publications/raghesh-a-masters-thesis.pdf
new file mode 100644
index 0000000..2eeb193
--- /dev/null
+++ b/rc4/www/publications/raghesh-a-masters-thesis.pdf
Binary files differ
diff --git a/rc4/www/todo.html b/rc4/www/todo.html
new file mode 100644
index 0000000..e9098b9
--- /dev/null
+++ b/rc4/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"> - 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"> - 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"> - Reconsider pass-ordering (move Polly later)
+</th><td align="center" class='open'> Open
+</td><td>
+</td>
+</tr>
+
+<tr><td colspan='4'> </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'> </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'> </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'> </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"> - Reconsider unreachables in post-dominance tree
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+
+<th align="left"> - Actually eliminate statements
+</th><td align="center" class='open'> Open
+</td><td>
+</td></tr>
+
+<tr><td colspan='4'> </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'> </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'> </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'> </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'> </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'> </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'> </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'> </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'> </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'> </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/rc4/www/video-js/video-js.css b/rc4/www/video-js/video-js.css
new file mode 100644
index 0000000..c9c4823
--- /dev/null
+++ b/rc4/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/rc4/www/video-js/video.js b/rc4/www/video-js/video.js
new file mode 100644
index 0000000..9571eeb
--- /dev/null
+++ b/rc4/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