Merge "Add bitcast to invoke helper pass."
diff --git a/include/bcc/Compiler.h b/include/bcc/Compiler.h
index 865947e..2c0995b 100644
--- a/include/bcc/Compiler.h
+++ b/include/bcc/Compiler.h
@@ -84,6 +84,7 @@
   bool addCustomPasses(Script &pScript, llvm::PassManager &pPM);
   bool addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM);
   bool addExpandForEachPass(Script &pScript, llvm::PassManager &pPM);
+  bool addInvariantPass(llvm::PassManager &pPM);
   bool addInvokeHelperPass(llvm::PassManager &pPM);
 
 public:
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index 5c0d6e8..b33ff2b 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -18,12 +18,12 @@
 #define BCC_RS_COMPILER_DRIVER_H
 
 #include "bcc/Compiler.h"
-#include "bcc/Renderscript/RSInfo.h"
 #include "bcc/Renderscript/RSScript.h"
 
 #include "bcinfo/MetadataExtractor.h"
 
 #include <list>
+#include <string>
 #include <vector>
 
 namespace bcc {
@@ -61,18 +61,12 @@
   bool setupConfig(const RSScript &pScript);
 
   // Compiles the provided bitcode, placing the binary at pOutputPath.
-  // - If saveInfoFile is true, it also stores the RSInfo data in a file with a path derived from
-  //   pOutputPath.
-  // - pSourceHash and commandLineToEmbed are values to embed in the RSInfo for future cache
-  //   invalidation decision.
   // - If pDumpIR is true, a ".ll" file will also be created.
   Compiler::ErrorCode compileScript(RSScript& pScript, const char* pScriptName,
                                     const char* pOutputPath,
-                                    const char *pRuntimePath,
-                                    const RSInfo::DependencyHashTy& pSourceHash,
-                                    const char* commandLineToEmbed,
+                                    const char* pRuntimePath,
                                     const char* pBuildChecksum,
-                                    bool saveInfoFile, bool pDumpIR);
+                                    bool pDumpIR);
 
 public:
   RSCompilerDriver(bool pUseCompilerRT = true);
@@ -114,7 +108,7 @@
   //        SymbolResolverInterface is not a const-method.
   // Returns true if script is successfully compiled.
   bool build(BCCContext& pContext, const char* pCacheDir, const char* pResName,
-             const char* pBitcode, size_t pBitcodeSize, const char* commandLine,
+             const char* pBitcode, size_t pBitcodeSize,
              const char *pBuildChecksum, const char* pRuntimePath,
              RSLinkRuntimeCallback pLinkRuntimeCallback = nullptr,
              bool pDumpIR = false);
diff --git a/include/bcc/Renderscript/RSInfo.h b/include/bcc/Renderscript/RSInfo.h
deleted file mode 100644
index 31b8da5..0000000
--- a/include/bcc/Renderscript/RSInfo.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef BCC_RS_INFO_H
-#define BCC_RS_INFO_H
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/Sha1Util.h"
-
-namespace llvm {
-class Module;
-}
-
-namespace bcc {
-
-// Forward declarations
-class FileBase;
-class InputFile;
-class OutputFile;
-class Source;
-class RSScript;
-
-typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
-
-namespace rsinfo {
-
-/* RS info file magic */
-#define RSINFO_MAGIC      "\0rsinfo\n"
-
-/* RS info file version, encoded in 4 bytes of ASCII */
-#define RSINFO_VERSION    "006\0"
-
-struct __attribute__((packed)) ListHeader {
-  // The offset from the beginning of the file of data
-  uint32_t offset;
-  // Number of item in the list
-  uint32_t count;
-  // Size of each item
-  uint8_t itemSize;
-};
-
-typedef uint32_t StringIndexTy;
-
-/* RS info file header */
-struct __attribute__((packed)) Header {
-  // Magic versus version
-  uint8_t magic[8];
-  uint8_t version[4];
-
-  uint8_t isThreadable;
-  uint8_t hasDebugInformation;
-
-  uint16_t headerSize;
-
-  uint32_t strPoolSize;
-
-  // The index in the pool of the SHA-1 checksum of the source file.
-  // It has a fixed-length of SHA1_DIGEST_LENGTH (=20) bytes.
-  StringIndexTy sourceSha1Idx;
-  // The index in the pool of the command used to compile this source.
-  StringIndexTy compileCommandLineIdx;
-  // The index in the pool of the build fingerprint of Android when the source was compiled.
-  StringIndexTy buildFingerprintIdx;
-
-  struct ListHeader pragmaList;
-  struct ListHeader objectSlotList;
-  struct ListHeader exportVarNameList;
-  struct ListHeader exportFuncNameList;
-  struct ListHeader exportForeachFuncList;
-};
-
-// Use value -1 as an invalid string index marker. No need to declare with
-// 'static' modifier since 'const' variable has internal linkage by default.
-const StringIndexTy gInvalidStringIndex = static_cast<StringIndexTy>(-1);
-
-struct __attribute__((packed)) PragmaItem {
-  // Pragma is a key-value pair.
-  StringIndexTy key;
-  StringIndexTy value;
-};
-
-struct __attribute__((packed)) ObjectSlotItem {
-  uint32_t slot;
-};
-
-struct __attribute__((packed)) ExportVarNameItem {
-  StringIndexTy name;
-};
-
-struct __attribute__((packed)) ExportFuncNameItem {
-  StringIndexTy name;
-};
-
-struct __attribute__((packed)) ExportForeachFuncItem {
-  StringIndexTy name;
-  uint32_t signature;
-};
-
-// Return the human-readable name of the given rsinfo::*Item in the template
-// parameter. This is for debugging and error message.
-template<typename Item>
-inline const char *GetItemTypeName();
-
-template<>
-inline const char *GetItemTypeName<PragmaItem>()
-{  return "rs pragma"; }
-
-template<>
-inline const char *GetItemTypeName<ObjectSlotItem>()
-{  return "rs object slot"; }
-
-template<>
-inline const char *GetItemTypeName<ExportVarNameItem>()
-{ return "rs export var"; }
-
-template<>
-inline const char *GetItemTypeName<ExportFuncNameItem>()
-{  return "rs export func"; }
-
-template<>
-inline const char *GetItemTypeName<ExportForeachFuncItem>()
-{ return "rs export foreach"; }
-
-} // end namespace rsinfo
-
-class RSInfo {
-public:
-  typedef const uint8_t* DependencyHashTy;
-  typedef std::vector<std::pair<const char*, const char*> > PragmaListTy;
-  typedef std::vector<uint32_t> ObjectSlotListTy;
-  typedef std::vector<const char *> ExportVarNameListTy;
-  typedef std::vector<const char *> ExportFuncNameListTy;
-  typedef std::vector<std::pair<const char *,
-                                    uint32_t> > ExportForeachFuncListTy;
-
-public:
-  // Return the path of the RS info file corresponded to the given output
-  // executable file.
-  static std::string GetPath(const char *pFilename);
-
-  // Check whether this info contains the same source hash, compile command line, and fingerprint.
-  // If not, it's an indication we need to recompile.
-  bool IsConsistent(const char* pInputFilename, const DependencyHashTy& sourceHash,
-                    const char* compileCommandLine, const char* buildFingerprint);
-
-private:
-
-  rsinfo::Header mHeader;
-
-  char *mStringPool;
-
-  // Pointer to the hash of the souce file, somewhere in the string pool.
-  DependencyHashTy mSourceHash;
-  // Pointer to the command used to compile this source, somewhere in the string pool.
-  const char* mCompileCommandLine;
-  // Pointer to the build fingerprint of Android when the source was compiled, somewhere in the
-  // string pool.
-  const char* mBuildFingerprint;
-
-  PragmaListTy mPragmas;
-  ObjectSlotListTy mObjectSlots;
-  ExportVarNameListTy mExportVarNames;
-  ExportFuncNameListTy mExportFuncNames;
-  ExportForeachFuncListTy mExportForeachFuncs;
-
-  // Initialize an empty RSInfo with its size of string pool is pStringPoolSize.
-  RSInfo(size_t pStringPoolSize);
-
-  // layout() assigns value of offset in each ListHeader (i.e., it decides where
-  // data should go in the file.) It also updates fields other than offset to
-  // reflect the current RSInfo object states to mHeader.
-  bool layout(off_t initial_offset);
-
-public:
-  ~RSInfo();
-
-  // Implemented in RSInfoExtractor.cpp.
-  static RSInfo *ExtractFromSource(const Source &pSource,
-                                   const DependencyHashTy &sourceHashToEmbed,
-                                   const char* compileCommandLineToEmbed,
-                                   const char* buildFingerprintToEmbed);
-
-  // Implemented in RSInfoReader.cpp.
-  static RSInfo *ReadFromFile(InputFile &pInput);
-
-  // Implemneted in RSInfoWriter.cpp
-  bool write(OutputFile &pOutput);
-
-  void dump() const;
-
-  // const getter
-  inline bool isThreadable() const
-  { return mHeader.isThreadable; }
-  inline bool hasDebugInformation() const
-  { return mHeader.hasDebugInformation; }
-  inline const PragmaListTy &getPragmas() const
-  { return mPragmas; }
-  inline const ObjectSlotListTy &getObjectSlots() const
-  { return mObjectSlots; }
-  inline const ExportVarNameListTy &getExportVarNames() const
-  { return mExportVarNames; }
-  inline const ExportFuncNameListTy &getExportFuncNames() const
-  { return mExportFuncNames; }
-  inline const ExportForeachFuncListTy &getExportForeachFuncs() const
-  { return mExportForeachFuncs; }
-
-  const char *getStringFromPool(rsinfo::StringIndexTy pStrIdx) const;
-  rsinfo::StringIndexTy getStringIdxInPool(const char *pStr) const;
-
-  // setter
-  inline void setThreadable(bool pThreadable = true)
-  { mHeader.isThreadable = pThreadable; }
-
-public:
-  enum FloatPrecision {
-    FP_Full,
-    FP_Relaxed,
-  };
-
-  // Return the minimal floating point precision required for the associated
-  // script.
-  FloatPrecision getFloatPrecisionRequirement() const;
-};
-
-// Returns the arguments concatenated into one string.
-std::string getCommandLine(int argc, const char* const* argv);
-
-} // end namespace bcc
-
-#endif  // BCC_RS_INFO_H
diff --git a/include/bcc/Renderscript/RSScript.h b/include/bcc/Renderscript/RSScript.h
index cd4385f..8dc53b9 100644
--- a/include/bcc/Renderscript/RSScript.h
+++ b/include/bcc/Renderscript/RSScript.h
@@ -18,14 +18,20 @@
 #define BCC_RS_SCRIPT_H
 
 #include "bcc/Script.h"
-#include "bcc/Renderscript/RSInfo.h"
 #include "bcc/Support/Sha1Util.h"
 
+namespace llvm {
+  class Module;
+}
+
 namespace bcc {
 
 class RSScript;
 class Source;
 
+typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
+
+
 class RSScript : public Script {
 public:
   // This is one-one mapping with the llvm::CodeGenOpt::Level in
@@ -39,8 +45,6 @@
   };
 
 private:
-  const RSInfo *mInfo;
-
   unsigned mCompilerVersion;
 
   OptimizationLevel mOptimizationLevel;
@@ -58,18 +62,7 @@
 
   RSScript(Source &pSource);
 
-  virtual ~RSScript() {
-    delete mInfo;
-  }
-
-  // Set the associated RSInfo of the script.
-  void setInfo(const RSInfo *pInfo) {
-    mInfo = pInfo;
-  }
-
-  const RSInfo *getInfo() const {
-    return mInfo;
-  }
+  virtual ~RSScript() { }
 
   void setCompilerVersion(unsigned pCompilerVersion) {
     mCompilerVersion = pCompilerVersion;
diff --git a/include/bcc/Renderscript/RSTransforms.h b/include/bcc/Renderscript/RSTransforms.h
index 647ac4d..c2ca439 100644
--- a/include/bcc/Renderscript/RSTransforms.h
+++ b/include/bcc/Renderscript/RSTransforms.h
@@ -28,6 +28,9 @@
 createRSForEachExpandPass(bool pEnableStepOpt);
 
 llvm::FunctionPass *
+createRSInvariantPass();
+
+llvm::FunctionPass *
 createRSInvokeHelperPass();
 
 llvm::ModulePass * createRSEmbedInfoPass();
diff --git a/lib/Core/Compiler.cpp b/lib/Core/Compiler.cpp
index 4f1dc8e..00c6fb2 100644
--- a/lib/Core/Compiler.cpp
+++ b/lib/Core/Compiler.cpp
@@ -374,6 +374,14 @@
   return true;
 }
 
+bool Compiler::addInvariantPass(llvm::PassManager &pPM) {
+  // Mark Loads from RsExpandKernelDriverInfo as "load.invariant".
+  // Should run after ExpandForEach and before inlining.
+  pPM.add(createRSInvariantPass());
+
+  return true;
+}
+
 bool Compiler::addCustomPasses(Script &pScript, llvm::PassManager &pPM) {
   if (!addInvokeHelperPass(pPM))
     return false;
@@ -381,6 +389,9 @@
   if (!addExpandForEachPass(pScript, pPM))
     return false;
 
+  if (!addInvariantPass(pPM))
+    return false;
+
   if (!addInternalizeSymbolsPass(pScript, pPM))
     return false;
 
diff --git a/lib/Renderscript/Android.mk b/lib/Renderscript/Android.mk
index 8e692f9..bbb289d 100644
--- a/lib/Renderscript/Android.mk
+++ b/lib/Renderscript/Android.mk
@@ -25,10 +25,7 @@
   RSCompilerDriver.cpp \
   RSEmbedInfo.cpp \
   RSForEachExpand.cpp \
-  RSInfo.cpp \
-  RSInfoExtractor.cpp \
-  RSInfoReader.cpp \
-  RSInfoWriter.cpp \
+  RSInvariant.cpp \
   RSScript.cpp \
   RSInvokeHelperPass.cpp \
   RSIsThreadablePass.cpp \
diff --git a/lib/Renderscript/RSCompilerDriver.cpp b/lib/Renderscript/RSCompilerDriver.cpp
index 757d920..903e056 100644
--- a/lib/Renderscript/RSCompilerDriver.cpp
+++ b/lib/Renderscript/RSCompilerDriver.cpp
@@ -25,10 +25,10 @@
 
 #include "bcinfo/BitcodeWrapper.h"
 #include "bcc/Assert.h"
+#include "bcinfo/MetadataExtractor.h"
 #include "bcc/BCCContext.h"
 #include "bcc/Compiler.h"
 #include "bcc/Config/Config.h"
-#include "bcc/Renderscript/RSInfo.h"
 #include "bcc/Renderscript/RSScript.h"
 #include "bcc/Renderscript/RSScriptGroupFusion.h"
 #include "bcc/Support/CompilerConfig.h"
@@ -37,7 +37,6 @@
 #include "bcc/Support/Log.h"
 #include "bcc/Support/InputFile.h"
 #include "bcc/Support/Initialization.h"
-#include "bcc/Support/Sha1Util.h"
 #include "bcc/Support/OutputFile.h"
 
 #include <sstream>
@@ -50,17 +49,6 @@
 
 using namespace bcc;
 
-// Get the build fingerprint of the Android device we are running on.
-static std::string getBuildFingerPrint() {
-#ifdef HAVE_ANDROID_OS
-    char fingerprint[PROPERTY_VALUE_MAX];
-    property_get("ro.build.fingerprint", fingerprint, "");
-    return fingerprint;
-#else
-    return "HostBuild";
-#endif
-}
-
 RSCompilerDriver::RSCompilerDriver(bool pUseCompilerRT) :
     mConfig(nullptr), mCompiler(), mDebugContext(false),
     mLinkRuntimeCallback(nullptr), mEnableGlobalMerge(true) {
@@ -105,9 +93,12 @@
   }
 
 #if defined(PROVIDE_ARM_CODEGEN)
-  assert((pScript.getInfo() != nullptr) && "NULL RS info!");
-  bool script_full_prec = (pScript.getInfo()->getFloatPrecisionRequirement() ==
-                           RSInfo::FP_Full);
+  bcinfo::MetadataExtractor me(&pScript.getSource().getModule());
+  if (!me.extract()) {
+    assert("Could not extract RS pragma metadata for module!");
+  }
+
+  bool script_full_prec = (me.getRSFloatPrecision() == bcinfo::RS_FP_Full);
   if (mConfig->getFullPrecision() != script_full_prec) {
     mConfig->setFullPrecision(script_full_prec);
     changed = true;
@@ -120,37 +111,13 @@
 Compiler::ErrorCode RSCompilerDriver::compileScript(RSScript& pScript, const char* pScriptName,
                                                     const char* pOutputPath,
                                                     const char* pRuntimePath,
-                                                    const RSInfo::DependencyHashTy& pSourceHash,
-                                                    const char* compileCommandLineToEmbed,
                                                     const char* pBuildChecksum,
-                                                    bool saveInfoFile, bool pDumpIR) {
-  // android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
-
+                                                    bool pDumpIR) {
   // embed build checksum metadata into the source
   if (pBuildChecksum != nullptr && strlen(pBuildChecksum) > 0) {
     pScript.getSource().addBuildChecksumMetadata(pBuildChecksum);
   }
 
-  RSInfo *info = nullptr;
-
-  //===--------------------------------------------------------------------===//
-  // Extract RS-specific information from source bitcode.
-  //===--------------------------------------------------------------------===//
-  // RS info may contains configuration (such as #optimization_level) to the
-  // compiler therefore it should be extracted before compilation.
-  info = RSInfo::ExtractFromSource(pScript.getSource(), pSourceHash, compileCommandLineToEmbed,
-                                   getBuildFingerPrint().c_str());
-  if (info == nullptr) {
-    return Compiler::kErrInvalidSource;
-  }
-
-  //===--------------------------------------------------------------------===//
-  // Associate script with its info
-  //===--------------------------------------------------------------------===//
-  // This is required since RS compiler may need information in the info file
-  // to do some transformation (e.g., expand foreach-able function.)
-  pScript.setInfo(info);
-
   //===--------------------------------------------------------------------===//
   // Link RS script with Renderscript runtime.
   //===--------------------------------------------------------------------===//
@@ -229,30 +196,6 @@
     }
   }
 
-  if (saveInfoFile) {
-    std::string info_path = RSInfo::GetPath(pOutputPath);
-    OutputFile info_file(info_path.c_str(), FileBase::kTruncate);
-
-    if (info_file.hasError()) {
-      ALOGE("Failed to open the info file %s for write! (%s)",
-            info_path.c_str(), info_file.getErrorMessage().c_str());
-      return Compiler::kErrInvalidSource;
-    }
-
-    FileMutex<FileBase::kWriteLock> write_info_mutex(info_path.c_str());
-    if (write_info_mutex.hasError() || !write_info_mutex.lock()) {
-      ALOGE("Unable to acquire the lock for writing %s! (%s)",
-            info_path.c_str(), write_info_mutex.getErrorMessage().c_str());
-      return Compiler::kErrInvalidSource;
-    }
-
-    // Perform the write.
-    if (!info->write(info_file)) {
-      ALOGE("Failed to sync the RS info file %s!", info_path.c_str());
-      return Compiler::kErrInvalidSource;
-    }
-  }
-
   return Compiler::kSuccess;
 }
 
@@ -261,7 +204,6 @@
                              const char *pResName,
                              const char *pBitcode,
                              size_t pBitcodeSize,
-                             const char *commandLine,
                              const char *pBuildChecksum,
                              const char *pRuntimePath,
                              RSLinkRuntimeCallback pLinkRuntimeCallback,
@@ -284,12 +226,6 @@
   }
 
   //===--------------------------------------------------------------------===//
-  // Prepare dependency information.
-  //===--------------------------------------------------------------------===//
-  uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
-  Sha1Util::GetSHA1DigestFromBuffer(bitcode_sha1, pBitcode, pBitcodeSize);
-
-  //===--------------------------------------------------------------------===//
   // Construct output path.
   // {pCacheDir}/{pResName}.o
   //===--------------------------------------------------------------------===//
@@ -324,8 +260,9 @@
   //===--------------------------------------------------------------------===//
   Compiler::ErrorCode status = compileScript(script, pResName,
                                              output_path.c_str(),
-                                             pRuntimePath, bitcode_sha1, commandLine,
-                                             pBuildChecksum, true, pDumpIR);
+                                             pRuntimePath,
+                                             pBuildChecksum,
+                                             pDumpIR);
 
   return status == Compiler::kSuccess;
 }
@@ -397,17 +334,7 @@
       Source::CreateFromModule(Context, pOutputFilepath, module, true));
   RSScript script(*source);
 
-  uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
-  const char* compileCommandLineToEmbed = "";
   const char* buildChecksum = "DummyChecksumForScriptGroup";
-  const char* buildFingerprintToEmbed = "";
-
-  RSInfo* info = RSInfo::ExtractFromSource(*source, bitcode_sha1,
-                                           compileCommandLineToEmbed, buildFingerprintToEmbed);
-  if (info == nullptr) {
-    return false;
-  }
-  script.setInfo(info);
 
   // Embed the info string directly in the ELF
   script.setEmbedInfo(true);
@@ -427,8 +354,7 @@
   }
 
   compileScript(script, pOutputFilepath, output_path.c_str(), coreLibPath,
-                bitcode_sha1, compileCommandLineToEmbed, buildChecksum,
-                true, dumpIR);
+                buildChecksum, dumpIR);
 
   return true;
 }
@@ -437,28 +363,12 @@
                                          const char *pBuildChecksum,
                                          const char *pRuntimePath,
                                          bool pDumpIR) {
-  // For compat lib, we don't check the RS info file so we don't need the source hash,
-  // compile command, and build fingerprint.
-  // TODO We may want to make them optional or embed real values.
-  uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH] = {0};
-  const char* compileCommandLineToEmbed = "";
-  const char* buildFingerprintToEmbed = "";
-
-  RSInfo* info = RSInfo::ExtractFromSource(pScript.getSource(), bitcode_sha1,
-                                           compileCommandLineToEmbed, buildFingerprintToEmbed);
-  if (info == nullptr) {
-    return false;
-  }
-  pScript.setInfo(info);
-
   // Embed the info string directly in the ELF, since this path is for an
   // offline (host) compilation.
   pScript.setEmbedInfo(true);
 
   Compiler::ErrorCode status = compileScript(pScript, pOut, pOut, pRuntimePath,
-                                             bitcode_sha1,
-                                             compileCommandLineToEmbed,
-                                             pBuildChecksum, false, pDumpIR);
+                                             pBuildChecksum, pDumpIR);
   if (status != Compiler::kSuccess) {
     return false;
   }
diff --git a/lib/Renderscript/RSForEachExpand.cpp b/lib/Renderscript/RSForEachExpand.cpp
index 865e695..2f036a6 100644
--- a/lib/Renderscript/RSForEachExpand.cpp
+++ b/lib/Renderscript/RSForEachExpand.cpp
@@ -245,7 +245,7 @@
     llvm::StructType *RsLaunchDimensionsTy =
         llvm::StructType::create(RsLaunchDimensionsTypes, "RsLaunchDimensions");
 
-    /* Defined in frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h:
+    /* Defined as the beginning of RsExpandKernelDriverInfo in frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h:
      *
      * struct RsExpandKernelDriverInfoPfx {
      *     const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT];
@@ -269,6 +269,8 @@
      *     // So the compiler must assume there are an unknown number of fields of unknown type
      *     // beginning here.
      * };
+     *
+     * The name "RsExpandKernelDriverInfoPfx" is known to RSInvariantPass (RSInvariant.cpp).
      */
     llvm::SmallVector<llvm::Type*, RsExpandKernelDriverInfoPfxFieldCount> RsExpandKernelDriverInfoPfxTypes;
     RsExpandKernelDriverInfoPfxTypes.push_back(Int8PtrArrayInputLimitTy); // const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT]
diff --git a/lib/Renderscript/RSInfo.cpp b/lib/Renderscript/RSInfo.cpp
deleted file mode 100644
index ba203ca..0000000
--- a/lib/Renderscript/RSInfo.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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.
- */
-
-// #define LOG_NDEBUG 0
-#include "bcc/Renderscript/RSInfo.h"
-
-#if !defined(_WIN32)  /* TODO create a HAVE_DLFCN_H */
-#include <dlfcn.h>
-#endif
-
-#include <cstring>
-#include <new>
-#include <string>
-
-#include "bcc/Support/FileBase.h"
-#include "bcc/Support/Log.h"
-
-#ifdef HAVE_ANDROID_OS
-#include <cutils/properties.h>
-#endif
-
-using namespace bcc;
-
-std::string RSInfo::GetPath(const char *pFilename) {
-  std::string result(pFilename);
-  result.append(".info");
-  return result;
-}
-
-static std::string stringFromSourceHash(const RSInfo::DependencyHashTy& hash) {
-    std::string s;
-    s.reserve(SHA1_DIGEST_LENGTH + 1);
-    for (int i = 0; i < SHA1_DIGEST_LENGTH; i++) {
-        char buf[4];
-        snprintf(buf, sizeof(buf), "%02x", hash[i]);
-        s.append(buf);
-    }
-    return s;
-}
-
-std::string bcc::getCommandLine(int argc, const char* const* argv) {
-    std::string s;
-    for (int i = 0; i < argc; i++) {
-        if (i > 0) {
-            s += ' ';
-        }
-        s += argv[i];
-    }
-    return s;
-}
-
-bool RSInfo::IsConsistent(const char* pInputFilename, const DependencyHashTy& expectedSourceHash,
-                          const char* expectedCompileCommandLine,
-                          const char* expectedBuildFingerprint) {
-    if (::memcmp(mSourceHash, expectedSourceHash, SHA1_DIGEST_LENGTH) != 0) {
-        ALOGD("Cache %s is dirty due to the source it depends on has been changed:",
-              pInputFilename);
-        ALOGD("expected: %s", stringFromSourceHash(expectedSourceHash).c_str());
-        ALOGD("cached  : %s", stringFromSourceHash(mSourceHash).c_str());
-        return false;
-    }
-    if (strcmp(expectedCompileCommandLine, mCompileCommandLine) != 0) {
-        ALOGD("Cache %s is dirty because the command line used to compile it has changed:",
-              pInputFilename);
-        ALOGD("expected: %s", expectedCompileCommandLine);
-        ALOGD("cached  : %s", mCompileCommandLine);
-        return false;
-    }
-    if (strcmp(expectedBuildFingerprint, mBuildFingerprint) != 0) {
-        ALOGD("Cache %s is dirty because the build fingerprint has changed:", pInputFilename);
-        ALOGD("expected: %s", expectedBuildFingerprint);
-        ALOGD("cached  : %s", mBuildFingerprint);
-        return false;
-    }
-    return true;
-}
-
-RSInfo::RSInfo(size_t pStringPoolSize) : mStringPool(nullptr) {
-  ::memset(&mHeader, 0, sizeof(mHeader));
-
-  ::memcpy(mHeader.magic, RSINFO_MAGIC, sizeof(mHeader.magic));
-  ::memcpy(mHeader.version, RSINFO_VERSION, sizeof(mHeader.version));
-
-  mHeader.headerSize = sizeof(mHeader);
-
-  mHeader.pragmaList.itemSize = sizeof(rsinfo::PragmaItem);
-  mHeader.objectSlotList.itemSize = sizeof(rsinfo::ObjectSlotItem);
-  mHeader.exportVarNameList.itemSize = sizeof(rsinfo::ExportVarNameItem);
-  mHeader.exportFuncNameList.itemSize = sizeof(rsinfo::ExportFuncNameItem);
-  mHeader.exportForeachFuncList.itemSize = sizeof(rsinfo::ExportForeachFuncItem);
-
-  if (pStringPoolSize > 0) {
-    mHeader.strPoolSize = pStringPoolSize;
-    mStringPool = new (std::nothrow) char [ mHeader.strPoolSize ];
-    if (mStringPool == nullptr) {
-      ALOGE("Out of memory when allocate memory for string pool in RSInfo "
-            "constructor (size: %u)!", mHeader.strPoolSize);
-    }
-    ::memset(mStringPool, 0, mHeader.strPoolSize);
-  }
-  mSourceHash = nullptr;
-  mCompileCommandLine = nullptr;
-  mBuildFingerprint = nullptr;
-}
-
-RSInfo::~RSInfo() {
-  delete [] mStringPool;
-}
-
-bool RSInfo::layout(off_t initial_offset) {
-  mHeader.pragmaList.offset = initial_offset +
-                              mHeader.headerSize +
-                              mHeader.strPoolSize;
-  mHeader.pragmaList.count = mPragmas.size();
-
-#define AFTER(_list) ((_list).offset + (_list).itemSize * (_list).count)
-  mHeader.objectSlotList.offset = AFTER(mHeader.pragmaList);
-  mHeader.objectSlotList.count = mObjectSlots.size();
-
-  mHeader.exportVarNameList.offset = AFTER(mHeader.objectSlotList);
-  mHeader.exportVarNameList.count = mExportVarNames.size();
-
-  mHeader.exportFuncNameList.offset = AFTER(mHeader.exportVarNameList);
-  mHeader.exportFuncNameList.count = mExportFuncNames.size();
-
-  mHeader.exportForeachFuncList.offset = AFTER(mHeader.exportFuncNameList);
-  mHeader.exportForeachFuncList.count = mExportForeachFuncs.size();
-#undef AFTER
-
-  return true;
-}
-
-void RSInfo::dump() const {
-  // Hide the codes to save the code size when debugging is disabled.
-#if !LOG_NDEBUG
-
-  // Dump header
-  ALOGV("RSInfo Header:");
-  ALOGV("\tIs threadable: %s", ((mHeader.isThreadable) ? "true" : "false"));
-  ALOGV("\tHeader size: %u", mHeader.headerSize);
-  ALOGV("\tString pool size: %u", mHeader.strPoolSize);
-
-  if (mSourceHash == nullptr) {
-      ALOGV("Source hash: NULL!");
-  } else {
-      ALOGV("Source hash: %s", stringFromSourceHash(mSourceHash).c_str());
-  }
-
-  ALOGV("Compile Command Line: %s", mCompileCommandLine ? mCompileCommandLine :
-                                                          "(NULL)");
-  ALOGV("mBuildFingerprint: %s", mBuildFingerprint ? mBuildFingerprint :
-                                                     "(NULL)");
-
-#define DUMP_LIST_HEADER(_name, _header) do { \
-  ALOGV(_name ":"); \
-  ALOGV("\toffset: %u", (_header).offset);  \
-  ALOGV("\t# of item: %u", (_header).count);  \
-  ALOGV("\tsize of each item: %u", (_header).itemSize); \
-} while (false)
-
-  DUMP_LIST_HEADER("Pragma list", mHeader.pragmaList);
-  for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
-        pragma_end = mPragmas.end(); pragma_iter != pragma_end; pragma_iter++) {
-    ALOGV("\tkey: %s, value: %s", pragma_iter->first, pragma_iter->second);
-  }
-
-  DUMP_LIST_HEADER("RS object slots", mHeader.objectSlotList);
-  for (ObjectSlotListTy::const_iterator slot_iter = mObjectSlots.begin(),
-          slot_end = mObjectSlots.end(); slot_iter != slot_end; slot_iter++) {
-    ALOGV("slot: %u", *slot_iter);
-  }
-
-  DUMP_LIST_HEADER("RS export variables", mHeader.exportVarNameList);
-  for (ExportVarNameListTy::const_iterator var_iter = mExportVarNames.begin(),
-          var_end = mExportVarNames.end(); var_iter != var_end; var_iter++) {
-    ALOGV("name: %s", *var_iter);
-  }
-
-  DUMP_LIST_HEADER("RS export functions", mHeader.exportFuncNameList);
-  for (ExportFuncNameListTy::const_iterator func_iter = mExportFuncNames.begin(),
-        func_end = mExportFuncNames.end(); func_iter != func_end; func_iter++) {
-    ALOGV("name: %s", *func_iter);
-  }
-
-  DUMP_LIST_HEADER("RS foreach list", mHeader.exportForeachFuncList);
-  for (ExportForeachFuncListTy::const_iterator
-          foreach_iter = mExportForeachFuncs.begin(),
-          foreach_end = mExportForeachFuncs.end(); foreach_iter != foreach_end;
-          foreach_iter++) {
-    ALOGV("name: %s, signature: %05x", foreach_iter->first,
-                                       foreach_iter->second);
-  }
-#undef DUMP_LIST_HEADER
-
-#endif // LOG_NDEBUG
-  return;
-}
-
-const char *RSInfo::getStringFromPool(rsinfo::StringIndexTy pStrIdx) const {
-  // String pool uses direct indexing. Ensure that the pStrIdx is within the
-  // range.
-  if (pStrIdx >= mHeader.strPoolSize) {
-    ALOGE("String index #%u is out of range in string pool (size: %u)!",
-          pStrIdx, mHeader.strPoolSize);
-    return nullptr;
-  }
-  return &mStringPool[ pStrIdx ];
-}
-
-rsinfo::StringIndexTy RSInfo::getStringIdxInPool(const char *pStr) const {
-  // Assume we are on the flat memory architecture (i.e., the memory space is
-  // continuous.)
-  if ((mStringPool + mHeader.strPoolSize) < pStr) {
-    ALOGE("String %s does not in the string pool!", pStr);
-    return rsinfo::gInvalidStringIndex;
-  }
-  return (pStr - mStringPool);
-}
-
-RSInfo::FloatPrecision RSInfo::getFloatPrecisionRequirement() const {
-  // Check to see if we have any FP precision-related pragmas.
-  std::string relaxed_pragma("rs_fp_relaxed");
-  std::string imprecise_pragma("rs_fp_imprecise");
-  std::string full_pragma("rs_fp_full");
-  bool relaxed_pragma_seen = false;
-  bool full_pragma_seen = false;
-
-  for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
-           pragma_end = mPragmas.end(); pragma_iter != pragma_end;
-       pragma_iter++) {
-    const char *pragma_key = pragma_iter->first;
-    if (!relaxed_pragma.compare(pragma_key)) {
-      relaxed_pragma_seen = true;
-    } else if (!imprecise_pragma.compare(pragma_key)) {
-      ALOGW("rs_fp_imprecise is deprecated.  Assuming rs_fp_relaxed instead.");
-      relaxed_pragma_seen = true;
-    } else if (!full_pragma.compare(pragma_key)) {
-      full_pragma_seen = true;
-    }
-  }
-
-  if (relaxed_pragma_seen && full_pragma_seen) {
-    ALOGE("Full and relaxed precision specified at the same time!");
-  }
-  RSInfo::FloatPrecision result = relaxed_pragma_seen ? FP_Relaxed : FP_Full;
-
-#ifdef HAVE_ANDROID_OS
-  // Provide an override for precsion via adb shell setprop
-  // adb shell setprop debug.rs.precision rs_fp_full
-  // adb shell setprop debug.rs.precision rs_fp_relaxed
-  // adb shell setprop debug.rs.precision rs_fp_imprecise
-  char precision_prop_buf[PROPERTY_VALUE_MAX];
-  property_get("debug.rs.precision", precision_prop_buf, "");
-
-  if (precision_prop_buf[0]) {
-    if (!relaxed_pragma.compare(precision_prop_buf)) {
-      ALOGI("Switching to RS FP relaxed mode via setprop");
-      result = FP_Relaxed;
-    } else if (!imprecise_pragma.compare(precision_prop_buf)) {
-      ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was specified but is "
-              "deprecated ");
-      result = FP_Relaxed;
-    } else if (!full_pragma.compare(precision_prop_buf)) {
-      ALOGI("Switching to RS FP full mode via setprop");
-      result = FP_Full;
-    } else {
-      ALOGE("Unrecognized debug.rs.precision %s", precision_prop_buf);
-    }
-  }
-#endif
-
-  return result;
-}
diff --git a/lib/Renderscript/RSInfoExtractor.cpp b/lib/Renderscript/RSInfoExtractor.cpp
deleted file mode 100644
index 78d1b4c..0000000
--- a/lib/Renderscript/RSInfoExtractor.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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.
- */
-
-//===----------------------------------------------------------------------===//
-// This file implements RSInfo::ExtractFromSource()
-//===----------------------------------------------------------------------===//
-#include "bcc/Renderscript/RSInfo.h"
-
-#include <llvm/IR/Constants.h>
-#include <llvm/IR/Metadata.h>
-#include <llvm/IR/Module.h>
-
-#include "bcc/Source.h"
-#include "bcc/Support/Log.h"
-
-using namespace bcc;
-
-namespace {
-
-// Name of metadata node where pragma info resides (should be synced with
-// slang.cpp)
-const llvm::StringRef pragma_metadata_name("#pragma");
-
-/*
- * The following names should be synced with the one appeared in
- * slang_rs_metadata.h.
- */
-// Name of metadata node where exported variable names reside
-const llvm::StringRef export_var_metadata_name("#rs_export_var");
-
-// Name of metadata node where exported function names reside
-const llvm::StringRef export_func_metadata_name("#rs_export_func");
-
-// Name of metadata node where exported ForEach name information resides
-const llvm::StringRef export_foreach_name_metadata_name("#rs_export_foreach_name");
-
-// Name of metadata node where exported ForEach signature information resides
-const llvm::StringRef export_foreach_metadata_name("#rs_export_foreach");
-
-// Name of metadata node where RS object slot info resides (should be
-const llvm::StringRef object_slot_metadata_name("#rs_object_slots");
-
-inline llvm::StringRef getStringFromOperand(const llvm::Value *pString) {
-  if ((pString != nullptr) && (pString->getValueID() == llvm::Value::MDStringVal)) {
-    return static_cast<const llvm::MDString *>(pString)->getString();
-  }
-  return llvm::StringRef();
-}
-
-template<size_t NumOperands>
-inline size_t getMetadataStringLength(const llvm::NamedMDNode *pMetadata) {
-  if (pMetadata == nullptr) {
-    return 0;
-  }
-
-  size_t string_size = 0;
-  for (unsigned i = 0, e = pMetadata->getNumOperands(); i < e; i++) {
-    llvm::MDNode *node = pMetadata->getOperand(i);
-    if ((node != nullptr) && (node->getNumOperands() >= NumOperands)) {
-      // Compiler try its best to unroll this loop since NumOperands is a
-      // template parameter (therefore the number of iteration can be determined
-      // at compile-time and it's usually small.)
-      for (unsigned j = 0; j < NumOperands; j++) {
-        llvm::StringRef s = getStringFromOperand(node->getOperand(j));
-        if (s.size() > 0) {
-          // +1 is for the null-terminator at the end of string.
-          string_size += (s.size() + 1);
-        }
-      }
-    }
-  }
-
-  return string_size;
-}
-
-// Write a string pString to the string pool pStringPool at offset pWriteStart.
-// Return the pointer the pString resides within the string pool.
-// Updates pWriteStart to the next available spot.
-const char *writeString(const llvm::StringRef &pString, char *pStringPool,
-                        off_t *pWriteStart) {
-  if (pString.empty()) {
-    return pStringPool;
-  }
-
-  char *pStringWriteStart = pStringPool + *pWriteStart;
-  // Copy the string.
-  ::memcpy(pStringWriteStart, pString.data(), pString.size());
-  // Write null-terminator at the end of the string.
-  pStringWriteStart[ pString.size() ] = '\0';
-  // Update pWriteStart.
-  *pWriteStart += (pString.size() + 1);
-
-  return pStringWriteStart;
-}
-
-} // end anonymous namespace
-
-RSInfo* RSInfo::ExtractFromSource(const Source& pSource, const DependencyHashTy& sourceHashToEmbed,
-                                  const char* compileCommandLineToEmbed,
-                                  const char* buildFingerprintToEmbed) {
-  const llvm::Module &module = pSource.getModule();
-  const char *module_name = module.getModuleIdentifier().c_str();
-
-  const llvm::NamedMDNode *pragma =
-      module.getNamedMetadata(pragma_metadata_name);
-  const llvm::NamedMDNode *export_var =
-      module.getNamedMetadata(export_var_metadata_name);
-  const llvm::NamedMDNode *export_func =
-      module.getNamedMetadata(export_func_metadata_name);
-  const llvm::NamedMDNode *export_foreach_name =
-      module.getNamedMetadata(export_foreach_name_metadata_name);
-  const llvm::NamedMDNode *export_foreach_signature =
-      module.getNamedMetadata(export_foreach_metadata_name);
-  const llvm::NamedMDNode *object_slots =
-      module.getNamedMetadata(object_slot_metadata_name);
-
-  // Always write a byte 0x0 at the beginning of the string pool.
-  size_t string_pool_size = 1;
-  off_t cur_string_pool_offset = 0;
-
-  RSInfo *result = nullptr;
-
-  // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
-  // section for ForEach. We generate a full signature for a "root" function.
-  if ((export_foreach_name == nullptr) || (export_foreach_signature == nullptr)) {
-    export_foreach_name = nullptr;
-    export_foreach_signature = nullptr;
-    string_pool_size += 5;  // insert "root\0" for #rs_export_foreach_name
-  }
-
-  string_pool_size += getMetadataStringLength<2>(pragma);
-  string_pool_size += getMetadataStringLength<1>(export_var);
-  string_pool_size += getMetadataStringLength<1>(export_func);
-  string_pool_size += getMetadataStringLength<1>(export_foreach_name);
-
-  // Reserve the space for the source hash, command line, and fingerprint
-  string_pool_size += SHA1_DIGEST_LENGTH;
-  string_pool_size += strlen(compileCommandLineToEmbed) + 1;
-  string_pool_size += strlen(buildFingerprintToEmbed) + 1;
-
-  // Allocate result object
-  result = new (std::nothrow) RSInfo(string_pool_size);
-  if (result == nullptr) {
-    ALOGE("Out of memory when create RSInfo object for %s!", module_name);
-    goto bail;
-  }
-
-  // Check string pool.
-  if (result->mStringPool == nullptr) {
-    ALOGE("Out of memory when allocate string pool in RSInfo object for %s!",
-          module_name);
-    goto bail;
-  }
-
-  // First byte of string pool should be an empty string
-  result->mStringPool[ cur_string_pool_offset++ ] = '\0';
-
-  // Populate all the strings and data.
-#define FOR_EACH_NODE_IN(_metadata, _node)  \
-  for (unsigned i = 0, e = (_metadata)->getNumOperands(); i != e; i++)  \
-    if (((_node) = (_metadata)->getOperand(i)) != nullptr)
-  //===--------------------------------------------------------------------===//
-  // #pragma
-  //===--------------------------------------------------------------------===//
-  // Pragma is actually a key-value pair. The value can be an empty string while
-  // the key cannot.
-  if (pragma != nullptr) {
-    llvm::MDNode *node;
-    FOR_EACH_NODE_IN(pragma, node) {
-        llvm::StringRef key = getStringFromOperand(node->getOperand(0));
-        llvm::StringRef val = getStringFromOperand(node->getOperand(1));
-        if (key.empty()) {
-          ALOGW("%s contains pragma metadata with empty key (skip)!",
-                module_name);
-        } else {
-          result->mPragmas.push_back(std::make_pair(
-              writeString(key, result->mStringPool, &cur_string_pool_offset),
-              writeString(val, result->mStringPool, &cur_string_pool_offset)));
-        } // key.empty()
-    } // FOR_EACH_NODE_IN
-  } // pragma != nullptr
-
-  //===--------------------------------------------------------------------===//
-  // #rs_export_var
-  //===--------------------------------------------------------------------===//
-  if (export_var != nullptr) {
-    llvm::MDNode *node;
-    FOR_EACH_NODE_IN(export_var, node) {
-      llvm::StringRef name = getStringFromOperand(node->getOperand(0));
-      if (name.empty()) {
-        ALOGW("%s contains empty entry in #rs_export_var metadata (skip)!",
-              module_name);
-      } else {
-          result->mExportVarNames.push_back(
-              writeString(name, result->mStringPool, &cur_string_pool_offset));
-      }
-    }
-  }
-
-  //===--------------------------------------------------------------------===//
-  // #rs_export_func
-  //===--------------------------------------------------------------------===//
-  if (export_func != nullptr) {
-    llvm::MDNode *node;
-    FOR_EACH_NODE_IN(export_func, node) {
-      llvm::StringRef name = getStringFromOperand(node->getOperand(0));
-      if (name.empty()) {
-        ALOGW("%s contains empty entry in #rs_export_func metadata (skip)!",
-              module_name);
-      } else {
-        result->mExportFuncNames.push_back(
-            writeString(name, result->mStringPool, &cur_string_pool_offset));
-      }
-    }
-  }
-
-  //===--------------------------------------------------------------------===//
-  // #rs_export_foreach and #rs_export_foreach_name
-  //===--------------------------------------------------------------------===//
-  // It's a little bit complicated to deal with #rs_export_foreach (the
-  // signature of foreach-able function) and #rs_export_foreach_name (the name
-  // of function which is foreach-able). We have to maintain a legacy case:
-  //
-  //  In pre-ICS bitcode, forEach feature only supports non-graphic root()
-  //  function and only one signature corresponded to that non-graphic root()
-  //  was written to the #rs_export_foreach metadata section. There's no
-  //  #rs_export_foreach_name metadata section.
-  //
-  // Currently, not only non-graphic root() is supported but also other
-  // functions that are exportable. Therefore, a new metadata section
-  // #rs_export_foreach_name is added to specify which functions are
-  // for-eachable. In this case, #rs_export_foreach (the function name) and
-  // #rs_export_foreach metadata (the signature) is one-to-one mapping among
-  // their entries.
-  if ((export_foreach_name != nullptr) && (export_foreach_signature != nullptr)) {
-    unsigned num_foreach_function;
-
-    // Should be one-to-one mapping.
-    if (export_foreach_name->getNumOperands() !=
-        export_foreach_signature->getNumOperands()) {
-      ALOGE("Mismatch number of foreach-able function names (%u) in "
-            "#rs_export_foreach_name and number of signatures (%u) "
-            "in %s!", export_foreach_name->getNumOperands(),
-            export_foreach_signature->getNumOperands(), module_name);
-      goto bail;
-    }
-
-    num_foreach_function = export_foreach_name->getNumOperands();
-    for (unsigned i = 0; i < num_foreach_function; i++) {
-      llvm::MDNode *name_node = export_foreach_name->getOperand(i);
-      llvm::MDNode *signature_node = export_foreach_signature->getOperand(i);
-
-      llvm::StringRef name, signature_string;
-      if (name_node != nullptr) {
-        name = getStringFromOperand(name_node->getOperand(0));
-      }
-      if (signature_node != nullptr) {
-        signature_string = getStringFromOperand(signature_node->getOperand(0));
-      }
-
-      if (!name.empty() && !signature_string.empty()) {
-        // Both name_node and signature_node are not nullptr nodes.
-        uint32_t signature;
-        if (signature_string.getAsInteger(10, signature)) {
-          ALOGE("Non-integer signature value '%s' for function %s found in %s!",
-                signature_string.str().c_str(), name.str().c_str(), module_name);
-          goto bail;
-        }
-        result->mExportForeachFuncs.push_back(std::make_pair(
-              writeString(name, result->mStringPool, &cur_string_pool_offset),
-              signature));
-      } else {
-        // One or both of the name and signature value are empty. It's safe only
-        // if both of them are empty.
-        if (name.empty() && signature_string.empty()) {
-          ALOGW("Entries #%u at #rs_export_foreach_name and #rs_export_foreach"
-                " are both nullptr in %s! (skip)", i, module_name);
-          continue;
-        } else {
-          ALOGE("Entries #%u at %s is NULL in %s! (skip)", i,
-                (name.empty() ? "#rs_export_foreach_name" :
-                                "#rs_export_foreach"), module_name);
-          goto bail;
-        }
-      }
-    } // end for
-  } else {
-    // To handle the legacy case, we generate a full signature for a "root"
-    // function which means that we need to set the bottom 5 bits (0x1f) in the
-    // mask.
-    result->mExportForeachFuncs.push_back(std::make_pair(
-          writeString(llvm::StringRef("root"), result->mStringPool,
-                      &cur_string_pool_offset), 0x1f));
-  }
-
-  //===--------------------------------------------------------------------===//
-  // #rs_object_slots
-  //===--------------------------------------------------------------------===//
-  if (object_slots != nullptr) {
-    llvm::MDNode *node;
-    for (unsigned int i = 0; i <= export_var->getNumOperands(); i++) {
-      result->mObjectSlots.push_back(0);
-    }
-    FOR_EACH_NODE_IN(object_slots, node) {
-      llvm::StringRef val = getStringFromOperand(node->getOperand(0));
-      if (val.empty()) {
-        ALOGW("%s contains empty entry in #rs_object_slots (skip)!",
-              module.getModuleIdentifier().c_str());
-      } else {
-        uint32_t slot;
-        if (val.getAsInteger(10, slot)) {
-          ALOGE("Non-integer object slot value '%s' in %s!", val.str().c_str(),
-                module.getModuleIdentifier().c_str());
-          goto bail;
-        } else {
-          result->mObjectSlots[slot] = 1;
-        }
-      }
-    }
-  }
-#undef FOR_EACH_NODE_IN
-
-  //===------------------------------------------------------------------===//
-  // Record information used to invalidate the cache
-  //===------------------------------------------------------------------===//
-  {
-      // Store the SHA-1 in the string pool but without a null-terminator.
-      result->mHeader.sourceSha1Idx = cur_string_pool_offset;
-      uint8_t* sha1 = reinterpret_cast<uint8_t*>(result->mStringPool + cur_string_pool_offset);
-      ::memcpy(sha1, sourceHashToEmbed, SHA1_DIGEST_LENGTH);
-      // Update the string pool pointer.
-      cur_string_pool_offset += SHA1_DIGEST_LENGTH;
-      result->mSourceHash = sha1;
-
-      result->mHeader.compileCommandLineIdx = cur_string_pool_offset;
-      result->mCompileCommandLine = writeString(compileCommandLineToEmbed, result->mStringPool,
-                                                &cur_string_pool_offset);
-
-      result->mHeader.buildFingerprintIdx = cur_string_pool_offset;
-      result->mBuildFingerprint = writeString(buildFingerprintToEmbed, result->mStringPool,
-                                              &cur_string_pool_offset);
-  }
-
-  //===--------------------------------------------------------------------===//
-  // Determine whether the bitcode contains debug information
-  //===--------------------------------------------------------------------===//
-  // The root context of the debug information in the bitcode is put under
-  // the metadata named "llvm.dbg.cu".
-  result->mHeader.hasDebugInformation =
-      static_cast<uint8_t>(module.getNamedMetadata("llvm.dbg.cu") != nullptr);
-
-  assert(((size_t)cur_string_pool_offset == string_pool_size) &&
-            "Unexpected string pool size!");
-
-  return result;
-
-bail:
-  delete result;
-  return nullptr;
-}
diff --git a/lib/Renderscript/RSInfoReader.cpp b/lib/Renderscript/RSInfoReader.cpp
deleted file mode 100644
index 611742c..0000000
--- a/lib/Renderscript/RSInfoReader.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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.
- */
-
-//===----------------------------------------------------------------------===//
-// This file implements RSInfo::ReadFromFile()
-//===----------------------------------------------------------------------===//
-
-#include "bcc/Renderscript/RSInfo.h"
-
-#include <new>
-
-#include <utils/FileMap.h>
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/InputFile.h"
-
-using namespace bcc;
-
-namespace {
-
-template<typename ItemType, typename ItemContainer>
-inline bool helper_read_list_item(const ItemType &pItem,
-                                  const RSInfo &pInfo,
-                                  ItemContainer &pResult);
-
-// Process PragmaItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
-    const rsinfo::PragmaItem &pItem,
-    const RSInfo &pInfo,
-    RSInfo::PragmaListTy &pResult)
-{
-  const char *key = pInfo.getStringFromPool(pItem.key);
-  const char *value =pInfo.getStringFromPool(pItem.value);
-
-  if (key == nullptr) {
-    ALOGE("Invalid string index %d for key in RS pragma list.", pItem.key);
-    return false;
-  }
-
-  if (value == nullptr) {
-    ALOGE("Invalid string index %d for value in RS pragma list.", pItem.value);
-    return false;
-  }
-
-  pResult.push_back(std::make_pair(key, value));
-  return true;
-}
-
-// Procee ObjectSlotItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
-    const rsinfo::ObjectSlotItem &pItem,
-    const RSInfo &pInfo,
-    RSInfo::ObjectSlotListTy &pResult)
-{
-  pResult.push_back(pItem.slot);
-  return true;
-}
-
-// Procee ExportVarNameItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
-    const rsinfo::ExportVarNameItem &pItem,
-    const RSInfo &pInfo,
-    RSInfo::ExportVarNameListTy &pResult)
-{
-  const char *name = pInfo.getStringFromPool(pItem.name);
-
-  if (name == nullptr) {
-    ALOGE("Invalid string index %d for name in RS export vars.", pItem.name);
-    return false;
-  }
-
-  pResult.push_back(name);
-  return true;
-}
-
-// Procee ExportFuncNameItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ExportFuncNameItem, RSInfo::ExportFuncNameListTy>(
-    const rsinfo::ExportFuncNameItem &pItem,
-    const RSInfo &pInfo,
-    RSInfo::ExportFuncNameListTy &pResult)
-{
-  const char *name = pInfo.getStringFromPool(pItem.name);
-
-  if (name == nullptr) {
-    ALOGE("Invalid string index %d for name in RS export funcs.", pItem.name);
-    return false;
-  }
-
-  pResult.push_back(name);
-  return true;
-}
-
-// Procee ExportForeachFuncItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ExportForeachFuncItem, RSInfo::ExportForeachFuncListTy>(
-    const rsinfo::ExportForeachFuncItem &pItem,
-    const RSInfo &pInfo,
-    RSInfo::ExportForeachFuncListTy &pResult)
-{
-  const char *name = pInfo.getStringFromPool(pItem.name);
-
-  if (name == nullptr) {
-    ALOGE("Invalid string index %d for name in RS export foreachs.", pItem.name);
-    return false;
-  }
-
-  pResult.push_back(std::make_pair(name, pItem.signature));
-  return true;
-}
-
-template<typename ItemType, typename ItemContainer>
-inline bool helper_read_list(const uint8_t *pData,
-                             const RSInfo &pInfo,
-                             const rsinfo::ListHeader &pHeader,
-                             ItemContainer &pResult) {
-  const ItemType *item;
-
-  // Out-of-range exception has been checked.
-  for (uint32_t i = 0; i < pHeader.count; i++) {
-    item = reinterpret_cast<const ItemType *>(pData +
-                                              pHeader.offset +
-                                              i * pHeader.itemSize);
-    if (!helper_read_list_item<ItemType, ItemContainer>(*item, pInfo, pResult)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-} // end anonymous namespace
-
-RSInfo *RSInfo::ReadFromFile(InputFile &pInput) {
-  android::FileMap *map = nullptr;
-  RSInfo *result = nullptr;
-  const uint8_t *data;
-  const rsinfo::Header *header;
-  size_t filesize;
-  const char *input_filename = pInput.getName().c_str();
-  const off_t cur_input_offset = pInput.tell();
-
-  if (pInput.hasError()) {
-    ALOGE("Invalid RS info file %s! (%s)", input_filename,
-                                           pInput.getErrorMessage().c_str());
-    goto bail;
-  }
-
-  filesize = pInput.getSize();
-  if (pInput.hasError()) {
-    ALOGE("Failed to get the size of RS info file %s! (%s)",
-          input_filename, pInput.getErrorMessage().c_str());
-    goto bail;
-  }
-
-  // Create memory map for the file.
-  map = pInput.createMap(/* pOffset */cur_input_offset,
-                         /* pLength */filesize - cur_input_offset);
-  if (map == nullptr) {
-    ALOGE("Failed to map RS info file %s to the memory! (%s)",
-          input_filename, pInput.getErrorMessage().c_str());
-    goto bail;
-  }
-
-  data = reinterpret_cast<const uint8_t *>(map->getDataPtr());
-
-  // Header starts at the beginning of the file.
-  header = reinterpret_cast<const rsinfo::Header *>(data);
-
-  // Check the magic.
-  if (::memcmp(header->magic, RSINFO_MAGIC, sizeof(header->magic)) != 0) {
-    ALOGV("Wrong magic found in the RS info file %s. Treat it as a dirty "
-          "cache.", input_filename);
-    goto bail;
-  }
-
-  // Check the version.
-  if (::memcmp(header->version,
-               RSINFO_VERSION,
-               sizeof(header->version)) != 0) {
-    ALOGV("Mismatch the version of RS info file %s: (current) %s v.s. (file) "
-          "%s. Treat it as as a dirty cache.", input_filename, RSINFO_VERSION,
-          header->version);
-    goto bail;
-  }
-
-  // Check the size.
-  if ((header->headerSize != sizeof(rsinfo::Header)) ||
-      (header->pragmaList.itemSize != sizeof(rsinfo::PragmaItem)) ||
-      (header->objectSlotList.itemSize != sizeof(rsinfo::ObjectSlotItem)) ||
-      (header->exportVarNameList.itemSize != sizeof(rsinfo::ExportVarNameItem)) ||
-      (header->exportFuncNameList.itemSize != sizeof(rsinfo::ExportFuncNameItem)) ||
-      (header->exportForeachFuncList.itemSize != sizeof(rsinfo::ExportForeachFuncItem))) {
-    ALOGW("Corrupted RS info file %s! (unexpected size found)", input_filename);
-    goto bail;
-  }
-
-  // Check the range.
-#define LIST_DATA_RANGE(_list_header) \
-  ((_list_header).offset + (_list_header).count * (_list_header).itemSize)
-  if (((header->headerSize + header->strPoolSize) > filesize) ||
-      (LIST_DATA_RANGE(header->pragmaList) > filesize) ||
-      (LIST_DATA_RANGE(header->objectSlotList) > filesize) ||
-      (LIST_DATA_RANGE(header->exportVarNameList) > filesize) ||
-      (LIST_DATA_RANGE(header->exportFuncNameList) > filesize) ||
-      (LIST_DATA_RANGE(header->exportForeachFuncList) > filesize)) {
-    ALOGW("Corrupted RS info file %s! (data out of the range)", input_filename);
-    goto bail;
-  }
-#undef LIST_DATA_RANGE
-
-  // File seems ok, create result RSInfo object.
-  result = new (std::nothrow) RSInfo(header->strPoolSize);
-  if (result == nullptr) {
-    ALOGE("Out of memory when create RSInfo object for %s!", input_filename);
-    goto bail;
-  }
-
-  // Make advice on our access pattern.
-  map->advise(android::FileMap::SEQUENTIAL);
-
-  // Copy the header.
-  ::memcpy(&result->mHeader, header, sizeof(rsinfo::Header));
-
-  if (header->strPoolSize > 0) {
-    // Copy the string pool. The string pool is immediately after the header at
-    // the offset header->headerSize.
-    if (result->mStringPool == nullptr) {
-      ALOGE("Out of memory when allocate string pool for RS info file %s!",
-            input_filename);
-      goto bail;
-    }
-    ::memcpy(result->mStringPool, data + result->mHeader.headerSize,
-             result->mHeader.strPoolSize);
-  }
-
-  // Populate all the data to the result object.
-  result->mSourceHash =
-              reinterpret_cast<const uint8_t*>(result->getStringFromPool(header->sourceSha1Idx));
-  if (result->mSourceHash == nullptr) {
-      ALOGE("Invalid string index %d for SHA-1 checksum of source.", header->sourceSha1Idx);
-      goto bail;
-  }
-
-  result->mCompileCommandLine = result->getStringFromPool(header->compileCommandLineIdx);
-  if (result->mCompileCommandLine == nullptr) {
-      ALOGE("Invalid string index %d for compile command line.", header->compileCommandLineIdx);
-      goto bail;
-  }
-
-  result->mBuildFingerprint = result->getStringFromPool(header->buildFingerprintIdx);
-  if (result->mBuildFingerprint == nullptr) {
-      ALOGE("Invalid string index %d for build fingerprint.", header->buildFingerprintIdx);
-      goto bail;
-  }
-
-  if (!helper_read_list<rsinfo::PragmaItem, PragmaListTy>
-        (data, *result, header->pragmaList, result->mPragmas)) {
-    goto bail;
-  }
-
-  if (!helper_read_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
-        (data, *result, header->objectSlotList, result->mObjectSlots)) {
-    goto bail;
-  }
-
-  if (!helper_read_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
-        (data, *result, header->exportVarNameList, result->mExportVarNames)) {
-    goto bail;
-  }
-
-  if (!helper_read_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
-        (data, *result, header->exportFuncNameList, result->mExportFuncNames)) {
-    goto bail;
-  }
-
-  if (!helper_read_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
-        (data, *result, header->exportForeachFuncList, result->mExportForeachFuncs)) {
-    goto bail;
-  }
-
-  // Clean up.
-  delete map;
-
-  return result;
-
-bail:
-  delete map;
-
-  delete result;
-
-  return nullptr;
-} // RSInfo::ReadFromFile
diff --git a/lib/Renderscript/RSInfoWriter.cpp b/lib/Renderscript/RSInfoWriter.cpp
deleted file mode 100644
index f9e2e2f..0000000
--- a/lib/Renderscript/RSInfoWriter.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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.
- */
-
-//===----------------------------------------------------------------------===//
-// This file implements RSInfo::write()
-//===----------------------------------------------------------------------===//
-
-#include "bcc/Renderscript/RSInfo.h"
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/OutputFile.h"
-
-using namespace bcc;
-
-namespace {
-
-template<typename ItemType, typename ItemContainer> inline bool
-helper_adapt_list_item(ItemType &pResult, const RSInfo &pInfo,
-                       const typename ItemContainer::const_iterator &pItem);
-
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
-    rsinfo::PragmaItem &pResult,
-    const RSInfo &pInfo,
-    const RSInfo::PragmaListTy::const_iterator &pItem) {
-  pResult.key = pInfo.getStringIdxInPool(pItem->first);
-  pResult.value = pInfo.getStringIdxInPool(pItem->second);
-
-  if (pResult.key == rsinfo::gInvalidStringIndex) {
-    ALOGE("RS pragma list contains invalid string '%s' for key.", pItem->first);
-    return false;
-  }
-
-  if (pResult.value == rsinfo::gInvalidStringIndex) {
-    ALOGE("RS pragma list contains invalid string '%s' for value.",
-          pItem->second);
-    return false;
-  }
-
-  return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
-    rsinfo::ObjectSlotItem &pResult,
-    const RSInfo &pInfo,
-    const RSInfo::ObjectSlotListTy::const_iterator &pItem) {
-  pResult.slot = *pItem;
-  return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
-    rsinfo::ExportVarNameItem &pResult,
-    const RSInfo &pInfo,
-    const RSInfo::ExportVarNameListTy::const_iterator &pItem) {
-  pResult.name = pInfo.getStringIdxInPool(*pItem);
-
-  if (pResult.name == rsinfo::gInvalidStringIndex) {
-    ALOGE("RS export vars contains invalid string '%s' for name.", *pItem);
-    return false;
-  }
-
-  return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ExportFuncNameItem,
-                       RSInfo::ExportFuncNameListTy>(
-    rsinfo::ExportFuncNameItem &pResult,
-    const RSInfo &pInfo,
-    const RSInfo::ExportFuncNameListTy::const_iterator &pItem) {
-  pResult.name = pInfo.getStringIdxInPool(*pItem);
-
-  if (pResult.name == rsinfo::gInvalidStringIndex) {
-    ALOGE("RS export funcs contains invalid string '%s' for name.", *pItem);
-    return false;
-  }
-
-  return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ExportForeachFuncItem,
-                       RSInfo::ExportForeachFuncListTy>(
-    rsinfo::ExportForeachFuncItem &pResult,
-    const RSInfo &pInfo,
-    const RSInfo::ExportForeachFuncListTy::const_iterator &pItem) {
-  pResult.name = pInfo.getStringIdxInPool(pItem->first);
-  pResult.signature = pItem->second;
-
-  if (pResult.name == rsinfo::gInvalidStringIndex) {
-    ALOGE("RS export foreach contains invalid string '%s' for name.",
-          pItem->first);
-    return false;
-  }
-
-  return true;
-}
-
-template<typename ItemType, typename ItemContainer>
-inline bool helper_write_list(OutputFile &pOutput,
-                              const RSInfo &pInfo,
-                              const rsinfo::ListHeader &pHeader,
-                              ItemContainer &pList) {
-  ItemType item;
-
-  for (typename ItemContainer::const_iterator item_iter = pList.begin(),
-          item_end = pList.end(); item_iter != item_end; item_iter++) {
-    // Convert each entry in the pList to ItemType.
-    if (!helper_adapt_list_item<ItemType, ItemContainer>(item,
-                                                         pInfo,
-                                                         item_iter)) {
-      return false;
-    }
-    // And write out an item.
-    if (pOutput.write(&item, sizeof(item)) != sizeof(item)) {
-      ALOGE("Cannot write out item of %s for RSInfo file %s! (%s)",
-            rsinfo::GetItemTypeName<ItemType>(), pOutput.getName().c_str(),
-            pOutput.getErrorMessage().c_str());
-      return false;
-    }
-  }
-
-  return true;
-}
-
-} // end anonymous namespace
-
-bool RSInfo::write(OutputFile &pOutput) {
-  off_t initial_offset = pOutput.tell();
-  const char *output_filename = pOutput.getName().c_str();
-
-  if (pOutput.hasError()) {
-    ALOGE("Invalid RS info file %s for output! (%s)",
-          output_filename, pOutput.getErrorMessage().c_str());
-    return false;
-  }
-
-  // Layout.
-  if (!layout(initial_offset)) {
-    return false;
-  }
-
-  // Write header.
-  if (pOutput.write(&mHeader, sizeof(mHeader)) != sizeof(mHeader)) {
-    ALOGE("Cannot write out the header for RSInfo file %s! (%s)",
-          output_filename, pOutput.getErrorMessage().c_str());
-    return false;
-  }
-
-  // Write string pool.
-  if (static_cast<size_t>(pOutput.write(mStringPool, mHeader.strPoolSize))
-          != mHeader.strPoolSize) {
-    ALOGE("Cannot write out the string pool for RSInfo file %s! (%s)",
-          output_filename, pOutput.getErrorMessage().c_str());
-    return false;
-  }
-
-  // Write pragmaList.
-  if (!helper_write_list<rsinfo::PragmaItem, PragmaListTy>
-        (pOutput, *this, mHeader.pragmaList, mPragmas)) {
-    return false;
-  }
-
-  // Write objectSlotList.
-  if (!helper_write_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
-        (pOutput, *this, mHeader.objectSlotList, mObjectSlots)) {
-    return false;
-  }
-
-  // Write exportVarNameList.
-  if (!helper_write_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
-        (pOutput, *this, mHeader.exportVarNameList, mExportVarNames)) {
-    return false;
-  }
-
-  // Write exportFuncNameList.
-  if (!helper_write_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
-        (pOutput, *this, mHeader.exportFuncNameList, mExportFuncNames)) {
-    return false;
-  }
-
-  // Write exportForeachFuncList.
-  if (!helper_write_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
-        (pOutput, *this, mHeader.exportForeachFuncList, mExportForeachFuncs)) {
-    return false;
-  }
-
-  return true;
-}
diff --git a/lib/Renderscript/RSInvariant.cpp b/lib/Renderscript/RSInvariant.cpp
new file mode 100644
index 0000000..1119a7a
--- /dev/null
+++ b/lib/Renderscript/RSInvariant.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * 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.
+ */
+
+#include "bcc/Renderscript/RSTransforms.h"
+
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+
+namespace {
+
+/*
+ * RSInvariantPass - This pass looks for Loads that access
+ * RsExpandKernelDriverInfo instances (which should never be written by
+ * a script, only by the driver) and marks them "invariant.load".
+ *
+ * There should be only two sources of Loads from such instances:
+ * - An instance can appear as an argument of type
+ *   "RsExpandKernelDriverInfoPfx*" passed to a .expand function by
+ *   the driver.
+ * - An instance can appear as an argument of type
+ *   "rs_kernel_context_t*" passed to an API query function by the
+ *   user.
+ * Only the compiler-generated .expand functions and the API query
+ * functions can see the fields of RsExpandKernelDriverInfo --
+ * rs_kernel_context_t is opaque to user code, so there cannot be any
+ * Loads from it in user code.
+ *
+ * This pass should be run
+ * - after foreachexp, so that it can see the Loads generated within
+ *   .expand functions
+ * - before inlining, so that it can recognize API query function
+ *   arguments.
+ *
+ * WARNINGS:
+ * - If user code or APIs can modify RsExpandKernelDriverInfo
+ *   instances, this pass MAY ALLOW ILLEGAL OPTIMIZATION.
+ * - If this pass runs at a different time, it may be ineffective
+ *   (fail to mark some or all eligible Loads, and thereby cost
+ *   performance).
+ * - If the names of the data types change, this pass may be
+ *   ineffective.
+ * - If the patterns by which fields are loaded from
+ *   RsExpandKernelDriverInfo instances change, this pass may be
+ *   ineffective.
+ */
+class RSInvariantPass : public llvm::FunctionPass {
+public:
+  static char ID;
+
+  RSInvariantPass() : FunctionPass(ID), EmptyMDNode(nullptr) { }
+
+  virtual bool doInitialization(llvm::Module &M) {
+    EmptyMDNode = llvm::MDNode::get(M.getContext(), llvm::None);
+    return true;
+  }
+
+  virtual bool runOnFunction(llvm::Function &F) {
+    bool Changed = false;
+
+    for (llvm::Value &Arg : F.args()) {
+      const llvm::Type *ArgType = Arg.getType();
+      if (ArgType->isPointerTy()) {
+        const llvm::Type *ArgPtrDomainType =  ArgType->getPointerElementType();
+        if (ArgPtrDomainType->isStructTy()) {
+          const llvm::StringRef StructName = ArgPtrDomainType->getStructName();
+          if (StructName.equals("struct.rs_kernel_context_t") || StructName.equals("RsExpandKernelDriverInfoPfx")) {
+            Changed |= markInvariantUserLoads(&Arg);
+          }
+        }
+      }
+    }
+
+    return Changed;
+  }
+
+  virtual const char *getPassName() const {
+    return "Renderscript Invariant Load Annotation";
+  }
+
+private:
+
+  /*
+   * Follow def->use chains rooted at Value through calculations
+   * "based on" Value (see the "based on" definition at
+   * http://llvm.org/docs/LangRef.html#pointer-aliasing-rules).  If a
+   * chain reaches the pointer operand of a Load, mark that Load as
+   * "invariant.load" -- i.e., it accesses memory which does not
+   * change.
+   */
+  bool markInvariantUserLoads(llvm::Value *Value) {
+    bool Changed = false;
+    for (llvm::Use &Use : Value->uses()) {
+      llvm::Instruction *Inst = llvm::cast<llvm::Instruction>(Use.getUser());
+
+      /*
+       * We only examine a small set of opcodes here, because these
+       * are the opcodes that currently appear in the patterns of
+       * interest (foreachexp-generated code, and
+       * rsGet*(rs_kernel_context_t*) APIs).  Other opcodes could be
+       * added if necessary.
+       */
+      if (auto BitCast = llvm::dyn_cast<llvm::BitCastInst>(Inst)) {
+        Changed |= markInvariantUserLoads(BitCast);
+      } else if (auto GetElementPtr = llvm::dyn_cast<llvm::GetElementPtrInst>(Inst)) {
+        if (Use.get() == GetElementPtr->getPointerOperand())
+          Changed |= markInvariantUserLoads(GetElementPtr);
+      } else if (auto Load = llvm::dyn_cast<llvm::LoadInst>(Inst)) {
+        if (Use.get() == Load->getPointerOperand()) {
+          Load->setMetadata("invariant.load", EmptyMDNode);
+          Changed = true;
+        }
+      }
+    }
+    return Changed;
+  }
+
+  // Pointer to empty metadata node used for "invariant.load" marking.
+  llvm::MDNode *EmptyMDNode;
+}; // end RSInvariantPass
+
+char RSInvariantPass::ID = 0;
+llvm::RegisterPass<RSInvariantPass> X("rsinvariant", "RS Invariant Load Pass");
+
+} // end anonymous namespace
+
+namespace bcc {
+
+llvm::FunctionPass *
+createRSInvariantPass() {
+  return new RSInvariantPass();
+}
+
+} // end namespace bcc
diff --git a/lib/Renderscript/RSScript.cpp b/lib/Renderscript/RSScript.cpp
index c93ca64..396b47d 100644
--- a/lib/Renderscript/RSScript.cpp
+++ b/lib/Renderscript/RSScript.cpp
@@ -17,7 +17,6 @@
 #include "bcc/Renderscript/RSScript.h"
 
 #include "bcc/Assert.h"
-#include "bcc/Renderscript/RSInfo.h"
 #include "bcc/Source.h"
 #include "bcc/Support/Log.h"
 
@@ -50,12 +49,11 @@
 }
 
 RSScript::RSScript(Source &pSource)
-  : Script(pSource), mInfo(nullptr), mCompilerVersion(0),
+  : Script(pSource), mCompilerVersion(0),
     mOptimizationLevel(kOptLvl3), mLinkRuntimeCallback(nullptr),
     mEmbedInfo(false) { }
 
 bool RSScript::doReset() {
-  mInfo = nullptr;
   mCompilerVersion = 0;
   mOptimizationLevel = kOptLvl3;
   return true;
diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk
index f228f9d..b8cdc60 100644
--- a/lib/Support/Android.mk
+++ b/lib/Support/Android.mk
@@ -28,8 +28,6 @@
   Initialization.cpp \
   InputFile.cpp \
   OutputFile.cpp \
-  Sha1Util.cpp \
-  sha1.c \
 
 #=====================================================================
 # Device Static Library: libbccSupport
diff --git a/lib/Support/Sha1Util.cpp b/lib/Support/Sha1Util.cpp
deleted file mode 100644
index 7cc636c..0000000
--- a/lib/Support/Sha1Util.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * copyright 2012, the android open source project
- *
- * 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.
- */
-
-#include "bcc/Support/Sha1Util.h"
-
-#include <sha1.h>
-
-#include <cstring>
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/InputFile.h"
-
-using namespace bcc;
-
-bool Sha1Util::GetSHA1DigestFromFile(uint8_t pResult[SHA1_DIGEST_LENGTH],
-                                     const char *pFilename) {
-  InputFile file(pFilename);
-
-  if (file.hasError()) {
-    ALOGE("Unable to open the file %s before SHA-1 checksum "
-          "calculation! (%s)", pFilename, file.getErrorMessage().c_str());
-    return false;
-  }
-
-  SHA1_CTX sha1_context;
-  SHA1Init(&sha1_context);
-
-  char buf[256];
-  while (true) {
-    ssize_t nread = file.read(buf, sizeof(buf));
-
-    if (nread < 0) {
-      // Some errors occurred during file reading.
-      return false;
-    }
-
-    SHA1Update(&sha1_context,
-               reinterpret_cast<unsigned char *>(buf),
-               static_cast<unsigned long>(nread));
-
-    if (static_cast<size_t>(nread) < sizeof(buf)) {
-      break;
-    }
-  }
-
-  SHA1Final(pResult, &sha1_context);
-
-  return true;
-}
-
-bool Sha1Util::GetSHA1DigestFromBuffer(uint8_t pResult[SHA1_DIGEST_LENGTH],
-                                       const uint8_t *pData, size_t pSize) {
-  SHA1_CTX sha1_context;
-
-  SHA1Init(&sha1_context);
-
-  SHA1Update(&sha1_context,
-             reinterpret_cast<const unsigned char *>(pData),
-             static_cast<unsigned long>(pSize));
-
-  SHA1Final(pResult, &sha1_context);
-
-  return true;
-}
diff --git a/lib/Support/sha1.c b/lib/Support/sha1.c
deleted file mode 100644
index 553e560..0000000
--- a/lib/Support/sha1.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/* This file is derived from libdex project */
-
-/*
- * Tweaked in various ways for Google/Android:
- *  - Changed from .cpp to .c.
- *  - Made argument to SHA1Update a const pointer, and enabled
- *    SHA1HANDSOFF.  This incurs a speed penalty but prevents us from
- *    trashing the input.
- *  - Include <endian.h> to get endian info.
- *  - Split a small piece into a header file.
- */
-
-/*
-sha1sum: inspired by md5sum.
-
-SHA-1 in C
-By Steve Reid <steve@edmweb.com>
-100% Public Domain
-
------------------
-Modified 7/98
-By James H. Brown <jbrown@burgoyne.com>
-Still 100% Public Domain
-
-bit machines
-Routine SHA1Update changed from
-    void SHA1Update(SHA1_CTX* context, unsigned char* data,
-      unsigned int len)
-to
-    void SHA1Update(SHA1_CTX* context, unsigned char* data,
-      unsigned long len)
-
-The 'len' parameter was declared an int which works fine on 32
-bit machines. However, on 16 bit machines an int is too small
-for the shifts being done against it.  This caused the hash
-function to generate incorrect values if len was greater than
-8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
-
-Since the file IO in main() reads 16K at a time, any file 8K or
-larger would be guaranteed to generate the wrong hash (e.g.
-Test Vector #3, a million "a"s).
-
-I also changed the declaration of variables i & j in SHA1Update
-to unsigned long from unsigned int for the same reason.
-
-These changes should make no difference to any 32 bit
-implementations since an int and a long are the same size in
-those environments.
-
---
-I also corrected a few compiler warnings generated by Borland
-C.
-1. Added #include <process.h> for exit() prototype
-2. Removed unused variable 'j' in SHA1Final
-3. Changed exit(0) to return(0) at end of main.
-
-ALL changes I made can be located by searching for comments
-containing 'JHB'
-
------------------
-Modified 13 August 2000
-By Michael Paul Johnson <mpj@cryptography.org>
-Still 100% Public Domain
-
-Changed command line syntax, added feature to automatically
-check files against their previous SHA-1 check values, kind of
-like md5sum does. Added functions hexval, verifyfile,
-and sha1file. Rewrote main().
------------------
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
-  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
-  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-#define SHA1HANDSOFF    /*Copies data before messing with it.*/
-
-/*#define CMDLINE        * include main() and file processing */
-//#ifdef CMDLINE
-//# undef CMDLINE         /* Never include main() for libbcc */
-//#endif
-
-#include "sha1.h"
-
-#include <stdio.h>
-#include <string.h>
-#ifdef __BORLANDC__
-#include <dir.h>
-#include <dos.h>
-#include <process.h>   /*  prototype for exit() - JHB
-               needed for Win32, but chokes Linux - MPJ */
-#define X_LITTLE_ENDIAN /* This should be #define'd if true.*/
-#else
-# define X_LITTLE_ENDIAN
-# include <unistd.h>
-# include <stdlib.h>
-#endif
-#include <ctype.h>
-
-#define LINESIZE 2048
-
-static void SHA1Transform(uint32_t state[5], const uint8_t buffer[64]);
-
-#define rol(value,bits) \
- (((value)<<(bits))|((value)>>(32-(bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from
-   SSLeay */
-#ifdef X_LITTLE_ENDIAN
-#define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \
-    |(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-    ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-static void SHA1Transform(uint32_t state[5],
-    const uint8_t buffer[64])
-{
-uint32_t a, b, c, d, e;
-typedef union {
-    uint8_t c[64];
-    uint32_t l[16];
-} CHAR64LONG16;
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static uint8_t workspace[64];
-    block = (CHAR64LONG16*)workspace;
-    memcpy(block, buffer, 64);
-#else
-    block = (CHAR64LONG16*)buffer;
-#endif
-    /* Copy context->state[] to working vars */
-    a = state[0];
-    b = state[1];
-    c = state[2];
-    d = state[3];
-    e = state[4];
-    /* 4 rounds of 20 operations each. Loop unrolled. */
-    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2);
-    R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5);
-    R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8);
-    R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14);
-    R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17);
-    R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20);
-    R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26);
-    R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29);
-    R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32);
-    R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38);
-    R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41);
-    R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44);
-    R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50);
-    R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53);
-    R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56);
-    R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62);
-    R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65);
-    R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68);
-    R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74);
-    R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77);
-    R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
-    /* Add the working vars back into context.state[] */
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-    state[4] += e;
-    /* Wipe variables */
-/*    a = b = c = d = e = 0; Nice try, but the compiler
-optimizes this out, anyway, and it produces an annoying
-warning. */
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
-    /* SHA1 initialization constants */
-    context->state[0] = 0x67452301;
-    context->state[1] = 0xEFCDAB89;
-    context->state[2] = 0x98BADCFE;
-    context->state[3] = 0x10325476;
-    context->state[4] = 0xC3D2E1F0;
-    context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, const uint8_t* data,
-    uint32_t len)  /* JHB */
-{
-    uint32_t i, j; /* JHB */
-
-    j = (context->count[0] >> 3) & 63;
-    if ((context->count[0] += len << 3) < (len << 3))
-        context->count[1]++;
-    context->count[1] += (len >> 29);
-    if ((j + len) > 63)
-    {
-        memcpy(&context->buffer[j], data, (i = 64-j));
-        SHA1Transform(context->state, context->buffer);
-        for ( ; i + 63 < len; i += 64) {
-            SHA1Transform(context->state, &data[i]);
-        }
-        j = 0;
-    }
-    else
-        i = 0;
-    memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(uint8_t digest[HASHSIZE], SHA1_CTX*
-context)
-{
-uint32_t i;    /* JHB */
-uint8_t finalcount[8];
-
-    for (i = 0; i < 8; i++)
-    {
-        finalcount[i] = (uint8_t)((context->count[(i>=4?
-            0:1)]>>((3-(i&3))*8))&255);
-        /* Endian independent */
-    }
-    SHA1Update(context, (uint8_t *)"\200", 1);
-    while ((context->count[0] & 504) != 448) {
-        SHA1Update(context, (uint8_t *)"\0", 1);
-    }
-    SHA1Update(context, finalcount, 8);
-    /* Should cause a SHA1Transform() */
-    for (i = 0; i < HASHSIZE; i++) {
-        digest[i] = (uint8_t)
-         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-    }
-    /* Wipe variables */
-    memset(context->buffer, 0, 64);
-    memset(context->state, 0, HASHSIZE);
-    memset(context->count, 0, 8);
-    memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF
-    /* make SHA1Transform overwrite it's own static vars */
-    SHA1Transform(context->state, context->buffer);
-#endif
-}
-
-
-
-#ifdef CMDLINE
-
-/* sha1file computes the SHA-1 hash of the named file and puts
-   it in the 20-byte array digest. If fname is NULL, stdin is
-   assumed.
-*/
-void sha1file(char *fname, uint8_t* digest)
-{
-    int bytesread;
-    SHA1_CTX context;
-    uint8_t buffer[16384];
-    FILE* f;
-
-    if (fname)
-    {
-        f = fopen(fname, "rb");
-        if (!f)
-        {
-            fprintf(stderr, "Can't open %s\n", fname);
-            memset(digest, 0, HASHSIZE);
-            return;
-        }
-    }
-    else
-    {
-        f = stdin;
-    }
-    SHA1Init(&context);
-    while (!feof(f))
-    {
-        bytesread = fread(buffer, 1, 16384, f);
-        SHA1Update(&context, buffer, bytesread);
-    }
-    SHA1Final(digest, &context);
-    if (fname)
-        fclose(f);
-}
-
-/* Convert ASCII hexidecimal digit to 4-bit value. */
-uint8_t hexval(char c)
-{
-    uint8_t h;
-
-    c = toupper(c);
-    if (c >= 'A')
-        h = c - 'A' + 10;
-    else
-        h = c - '0';
-    return h;
-}
-
-/* Verify a file created with sha1sum by redirecting output
-   to a file. */
-int verifyfile(char *fname)
-{
-    int j, k;
-    int found = 0;
-    uint8_t digest[HASHSIZE];
-    uint8_t expected_digest[HASHSIZE];
-    FILE *checkfile;
-    char checkline[LINESIZE];
-    char *s;
-    uint8_t err;
-
-    checkfile = fopen(fname, "rt");
-    if (!checkfile)
-    {
-        fprintf(stderr, "Can't open %s\n", fname);
-        return(0);
-    }
-    do
-    {
-        s = fgets(checkline, LINESIZE, checkfile);
-        if (s)
-        {
-            if ((strlen(checkline)>26)&&
-                1 /*(!strncmp(checkline,"SHA1=", 5))*/)
-            {
-                /* Overwrite newline. */
-                checkline[strlen(checkline)-1]=0;
-                found = 1;
-
-                /* Read expected check value. */
-                for (k=0, j=5; k < HASHSIZE; k++)
-                {
-                    expected_digest[k]=hexval(checkline[j++]);
-                    expected_digest[k]=(expected_digest[k]<<4)
-                        +hexval(checkline[j++]);
-                }
-
-                /* Compute fingerprints */
-                s = checkline+46;
-                sha1file(s, digest);
-
-                /* Compare fingerprints */
-                err = 0;
-                for (k=0; k<HASHSIZE; k++)
-                    err |= digest[k]-
-                        expected_digest[k];
-                if (err)
-                {
-                    fprintf(stderr, "FAILED: %s\n"
-                        " EXPECTED: ", s);
-                    for (k=0; k<HASHSIZE; k++)
-                        fprintf(stderr, "%02X",
-                            expected_digest[k]);
-                    fprintf(stderr,"\n    FOUND: ");
-                    for (k=0; k<HASHSIZE; k++)
-                        fprintf(stderr, "%02X", digest[k]);
-                    fprintf(stderr, "\n");
-                }
-                else
-                {
-                    printf("OK: %s\n", s);
-                }
-            }
-        }
-    } while (s);
-    return found;
-}
-
-
-
-void syntax(char *progname)
-{
-    printf("\nsyntax:\n"
-     "%s [-c|-h][-q] file name[s]\n"
-     "    -c = check files against previous check values\n"
-     "    -g = generate SHA-1 check values (default action)\n"
-     "    -h = display this help\n"
-     "For example,\n"
-     "sha1sum test.txt > check.txt\n"
-     "generates check value for test.txt in check.txt, and\n"
-     "sha1sum -c check.txt\n"
-     "checks test.txt against the check value in check.txt\n",
-     progname);
-    exit(1);
-}
-
-
-/**********************************************************/
-
-int main(int argc, char** argv)
-{
-    int i, j, k;
-    int check = 0;
-    int found = 0;
-    uint8_t digest[HASHSIZE];
-    uint8_t expected_digest[HASHSIZE];
-    FILE *checkfile;
-    char checkline[LINESIZE];
-    char *s;
-#ifdef __BORLANDC__
-    struct ffblk f;
-    int done;
-    char path[MAXPATH];
-    char drive[MAXDRIVE];
-    char dir[MAXDIR];
-    char name[MAXFILE];
-    char ext[MAXEXT];
-#endif
-    uint8_t err;
-    const char *binary_output_file = 0;
-
-    for (i = 1; i < argc; i++)
-    {
-        if (argv[i][0] == '-')
-        {
-            switch (argv[i][1])
-            {
-                case 'B':
-                    ++i;
-                    binary_output_file = argv[i];
-                    break;
-                case 'c':
-                case 'C':
-                    check = 1;
-                    break;
-                case 'g':
-                case 'G':
-                    check = 0;
-                    break;
-                default:
-                    syntax(argv[0]);
-            }
-        }
-    }
-
-    // Read from STDIN
-    sha1file(NULL, digest);
-    if (binary_output_file) {
-      FILE *fout = fopen(binary_output_file, "wb");
-      if (!fout) {
-        fprintf(stderr, "Error: Can not write to %s.\n", binary_output_file);
-        return 1;
-      }
-      fwrite(digest, 1, HASHSIZE, fout);
-      fclose(fout);
-      return 0;
-    }
-    for (j = 0; j < HASHSIZE; j++)
-        printf("%02x", digest[j]);
-    return 0;
-
-    for (i=1; i<argc; i++)
-    {
-        if (argv[i][0] != '-')
-        {
-#ifdef __BORLANDC__
-            fnsplit(argv[i], drive, dir, name, ext);
-            done = findfirst(argv[i], &f, FA_RDONLY |
-                FA_HIDDEN|FA_SYSTEM|FA_ARCH);
-             while (!done)
-            {
-                sprintf(path, "%s%s%s", drive, dir, f.ff_name);
-                s = path;
-#else
-                s = argv[i];
-#endif
-
-                if (check)
-                {   /* Check fingerprint file. */
-                    found |= verifyfile(s);
-                }
-                else
-                {   /* Generate fingerprints & write to
-                       stdout. */
-                    sha1file(s, digest);
-                    //printf("SHA1=");
-                    for (j=0; j<HASHSIZE; j++)
-                        printf("%02x", digest[j]);
-                    printf("  %s\n", s);
-                    found = 1;
-                }
-
-#ifdef __BORLANDC__
-                done = findnext(&f);
-            }
-#endif
-
-        }
-    }
-    if (!found)
-    {
-        if (check)
-        {
-            fprintf(stderr,
-                "No SHA1 lines found in %s\n",
-                argv[i]);
-        }
-        else
-        {
-            fprintf(stderr, "No files checked.\n");
-            syntax(argv[0]);
-        }
-    }
-    return(0);  /* JHB */
-}
-
-#endif  /*CMDLINE*/
diff --git a/tools/bcc/Main.cpp b/tools/bcc/Main.cpp
index a047e88..cfe8b97 100644
--- a/tools/bcc/Main.cpp
+++ b/tools/bcc/Main.cpp
@@ -41,6 +41,7 @@
 #include <bcc/Renderscript/RSCompilerDriver.h>
 #include <bcc/Script.h>
 #include <bcc/Source.h>
+#include <bcc/Support/Log.h>
 #include <bcc/Support/CompilerConfig.h>
 #include <bcc/Support/Initialization.h>
 #include <bcc/Support/InputFile.h>
@@ -288,7 +289,6 @@
   init::Initialize();
   llvm::cl::SetVersionPrinter(BCCVersionPrinter);
   llvm::cl::ParseCommandLineOptions(argc, argv);
-  std::string commandLine = bcc::getCommandLine(argc, argv);
 
   BCCContext context;
   RSCompilerDriver RSCD;
@@ -334,9 +334,11 @@
   size_t bitcodeSize = input_data->getBufferSize();
 
   if (!OptEmbedRSInfo) {
-    bool built = RSCD.build(context, OptOutputPath.c_str(), OptOutputFilename.c_str(), bitcode,
-                            bitcodeSize, commandLine.c_str(), OptChecksum.c_str(), OptBCLibFilename.c_str(), nullptr,
-                            OptEmitLLVM);
+    bool built = RSCD.build(context, OptOutputPath.c_str(),
+                            OptOutputFilename.c_str(),
+                            bitcode, bitcodeSize,
+                            OptChecksum.c_str(), OptBCLibFilename.c_str(),
+                            nullptr, OptEmitLLVM);
 
     if (!built) {
       return EXIT_FAILURE;