Add LLVM dependencies for Subzero.

Change-Id: I5ab054a5622c9f9dee099f5a3a30c3bb4079ffeb
Reviewed-on: https://swiftshader-review.googlesource.com/7291
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/third_party/llvm-subzero/CREDITS.TXT b/third_party/llvm-subzero/CREDITS.TXT
new file mode 100644
index 0000000..96a6e49
--- /dev/null
+++ b/third_party/llvm-subzero/CREDITS.TXT
@@ -0,0 +1,475 @@
+This file is a partial list of people who have contributed to the LLVM
+project.  If you have contributed a patch or made some other contribution to
+LLVM, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts.  The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), snail-mail address
+(S), and (I) IRC handle.
+
+
+N: Vikram Adve
+E: vadve@cs.uiuc.edu
+W: http://www.cs.uiuc.edu/~vadve/
+D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM
+
+N: Owen Anderson
+E: resistor@mac.com
+D: LCSSA pass and related LoopUnswitch work
+D: GVNPRE pass, DataLayout refactoring, random improvements
+
+N: Henrik Bach
+D: MingW Win32 API portability layer
+
+N: Aaron Ballman
+E: aaron@aaronballman.com
+D: __declspec attributes, Windows support, general bug fixing
+
+N: Nate Begeman
+E: natebegeman@mac.com
+D: PowerPC backend developer
+D: Target-independent code generator and analysis improvements
+
+N: Daniel Berlin
+E: dberlin@dberlin.org
+D: ET-Forest implementation.
+D: Sparse bitmap
+
+N: David Blaikie
+E: dblaikie@gmail.com
+D: General bug fixing/fit & finish, mostly in Clang
+
+N: Neil Booth
+E: neil@daikokuya.co.uk
+D: APFloat implementation.
+
+N: Misha Brukman
+E: brukman+llvm@uiuc.edu
+W: http://misha.brukman.net
+D: Portions of X86 and Sparc JIT compilers, PowerPC backend
+D: Incremental bitcode loader
+
+N: Cameron Buschardt
+E: buschard@uiuc.edu
+D: The `mem2reg' pass - promotes values stored in memory to registers
+
+N: Brendon Cahoon
+E: bcahoon@codeaurora.org
+D: Loop unrolling with run-time trip counts.
+
+N: Chandler Carruth
+E: chandlerc@gmail.com
+E: chandlerc@google.com
+D: Hashing algorithms and interfaces
+D: Inline cost analysis
+D: Machine block placement pass
+D: SROA
+
+N: Casey Carter
+E: ccarter@uiuc.edu
+D: Fixes to the Reassociation pass, various improvement patches
+
+N: Evan Cheng
+E: evan.cheng@apple.com
+D: ARM and X86 backends
+D: Instruction scheduler improvements
+D: Register allocator improvements
+D: Loop optimizer improvements
+D: Target-independent code generator improvements
+
+N: Dan Villiom Podlaski Christiansen
+E: danchr@gmail.com
+E: danchr@cs.au.dk
+W: http://villiom.dk
+D: LLVM Makefile improvements
+D: Clang diagnostic & driver tweaks
+S: Aarhus, Denmark
+
+N: Jeff Cohen
+E: jeffc@jolt-lang.org
+W: http://jolt-lang.org
+D: Native Win32 API portability layer
+
+N: John T. Criswell
+E: criswell@uiuc.edu
+D: Original Autoconf support, documentation improvements, bug fixes
+
+N: Anshuman Dasgupta
+E: adasgupt@codeaurora.org
+D: Deterministic finite automaton based infrastructure for VLIW packetization
+
+N: Stefanus Du Toit
+E: stefanus.du.toit@intel.com
+D: Bug fixes and minor improvements
+
+N: Rafael Avila de Espindola
+E: rafael.espindola@gmail.com
+D: The ARM backend
+
+N: Dave Estes
+E: cestes@codeaurora.org
+D: AArch64 machine description for Cortex-A53
+
+N: Alkis Evlogimenos
+E: alkis@evlogimenos.com
+D: Linear scan register allocator, many codegen improvements, Java frontend
+
+N: Hal Finkel
+E: hfinkel@anl.gov
+D: Basic-block autovectorization, PowerPC backend improvements
+
+N: Eric Fiselier
+E: eric@efcs.ca
+D: LIT patches and documentation.
+
+N: Ryan Flynn
+E: pizza@parseerror.com
+D: Miscellaneous bug fixes
+
+N: Brian Gaeke
+E: gaeke@uiuc.edu
+W: http://www.students.uiuc.edu/~gaeke/
+D: Portions of X86 static and JIT compilers; initial SparcV8 backend
+D: Dynamic trace optimizer
+D: FreeBSD/X86 compatibility fixes, the llvm-nm tool
+
+N: Nicolas Geoffray
+E: nicolas.geoffray@lip6.fr
+W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/
+D: PPC backend fixes for Linux
+
+N: Louis Gerbarg
+E: lgg@apple.com
+D: Portions of the PowerPC backend
+
+N: Saem Ghani
+E: saemghani@gmail.com
+D: Callgraph class cleanups
+
+N: Mikhail Glushenkov
+E: foldr@codedgers.com
+D: Author of llvmc2
+
+N: Dan Gohman
+E: sunfish@mozilla.com
+D: Miscellaneous bug fixes
+D: WebAssembly Backend
+
+N: David Goodwin
+E: david@goodwinz.net
+D: Thumb-2 code generator
+
+N: David Greene
+E: greened@obbligato.org
+D: Miscellaneous bug fixes
+D: Register allocation refactoring
+
+N: Gabor Greif
+E: ggreif@gmail.com
+D: Improvements for space efficiency
+
+N: James Grosbach
+E: grosbach@apple.com
+I: grosbach
+D: SjLj exception handling support
+D: General fixes and improvements for the ARM back-end
+D: MCJIT
+D: ARM integrated assembler and assembly parser
+D: Led effort for the backend formerly known as ARM64
+
+N: Lang Hames
+E: lhames@gmail.com
+D: PBQP-based register allocator
+
+N: Gordon Henriksen
+E: gordonhenriksen@mac.com
+D: Pluggable GC support
+D: C interface
+D: Ocaml bindings
+
+N: Raul Fernandes Herbster
+E: raul@dsc.ufcg.edu.br
+D: JIT support for ARM
+
+N: Paolo Invernizzi
+E: arathorn@fastwebnet.it
+D: Visual C++ compatibility fixes
+
+N: Patrick Jenkins
+E: patjenk@wam.umd.edu
+D: Nightly Tester
+
+N: Dale Johannesen
+E: dalej@apple.com
+D: ARM constant islands improvements
+D: Tail merging improvements
+D: Rewrite X87 back end
+D: Use APFloat for floating point constants widely throughout compiler
+D: Implement X87 long double
+
+N: Brad Jones
+E: kungfoomaster@nondot.org
+D: Support for packed types
+
+N: Rod Kay
+E: rkay@auroraux.org
+D: Author of LLVM Ada bindings
+
+N: Eric Kidd
+W: http://randomhacks.net/
+D: llvm-config script
+
+N: Anton Korobeynikov
+E: asl@math.spbu.ru
+D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv.
+D: x86/linux PIC codegen, aliases, regparm/visibility attributes
+D: Switch lowering refactoring
+
+N: Sumant Kowshik
+E: kowshik@uiuc.edu
+D: Author of the original C backend
+
+N: Benjamin Kramer
+E: benny.kra@gmail.com
+D: Miscellaneous bug fixes
+
+N: Sundeep Kushwaha
+E: sundeepk@codeaurora.org
+D: Implemented DFA-based target independent VLIW packetizer
+
+N: Christopher Lamb
+E: christopher.lamb@gmail.com
+D: aligned load/store support, parts of noalias and restrict support
+D: vreg subreg infrastructure, X86 codegen improvements based on subregs
+D: address spaces
+
+N: Jim Laskey
+E: jlaskey@apple.com
+D: Improvements to the PPC backend, instruction scheduling
+D: Debug and Dwarf implementation
+D: Auto upgrade mangler
+D: llvm-gcc4 svn wrangler
+
+N: Chris Lattner
+E: sabre@nondot.org
+W: http://nondot.org/~sabre/
+D: Primary architect of LLVM
+
+N: Tanya Lattner (Tanya Brethour)
+E: tonic@nondot.org
+W: http://nondot.org/~tonic/
+D: The initial llvm-ar tool, converted regression testsuite to dejagnu
+D: Modulo scheduling in the SparcV9 backend
+D: Release manager (1.7+)
+
+N: Sylvestre Ledru
+E: sylvestre@debian.org
+W: http://sylvestre.ledru.info/
+W: http://llvm.org/apt/
+D: Debian and Ubuntu packaging
+D: Continuous integration with jenkins
+
+N: Andrew Lenharth
+E: alenhar2@cs.uiuc.edu
+W: http://www.lenharth.org/~andrewl/
+D: Alpha backend
+D: Sampling based profiling
+
+N: Nick Lewycky
+E: nicholas@mxc.ca
+D: PredicateSimplifier pass
+
+N: Tony Linthicum, et. al.
+E: tlinth@codeaurora.org
+D: Backend for Qualcomm's Hexagon VLIW processor.
+
+N: Bruno Cardoso Lopes
+E: bruno.cardoso@gmail.com
+I: bruno
+W: http://brunocardoso.cc
+D: Mips backend
+D: Random ARM integrated assembler and assembly parser improvements
+D: General X86 AVX1 support
+
+N: Duraid Madina
+E: duraid@octopus.com.au
+W: http://kinoko.c.u-tokyo.ac.jp/~duraid/
+D: IA64 backend, BigBlock register allocator
+
+N: John McCall
+E: rjmccall@apple.com
+D: Clang semantic analysis and IR generation
+
+N: Michael McCracken
+E: michael.mccracken@gmail.com
+D: Line number support for llvmgcc
+
+N: Vladimir Merzliakov
+E: wanderer@rsu.ru
+D: Test suite fixes for FreeBSD
+
+N: Scott Michel
+E: scottm@aero.org
+D: Added STI Cell SPU backend.
+
+N: Kai Nacke
+E: kai@redstar.de
+D: Support for implicit TLS model used with MS VC runtime
+D: Dumping of Win64 EH structures
+
+N: Takumi Nakamura
+E: geek4civic@gmail.com
+E: chapuni@hf.rim.or.jp
+D: Cygwin and MinGW support.
+D: Win32 tweaks.
+S: Yokohama, Japan
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: Add Clang support with various other improvements to utils/NewNightlyTest.pl
+D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings
+D: and error clean ups.
+
+N: Morten Ofstad
+E: morten@hue.no
+D: Visual C++ compatibility fixes
+
+N: Jakob Stoklund Olesen
+E: stoklund@2pi.dk
+D: Machine code verifier
+D: Blackfin backend
+D: Fast register allocator
+D: Greedy register allocator
+
+N: Richard Osborne
+E: richard@xmos.com
+D: XCore backend
+
+N: Piotr Padlewski
+E: piotr.padlewski@gmail.com
+D: !invariant.group metadata and other intrinsics for devirtualization in clang
+
+N: Devang Patel
+E: dpatel@apple.com
+D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate
+D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements
+D: Optimizer improvements, Loop Index Split
+
+N: Ana Pazos
+E: apazos@codeaurora.org
+D: Fixes and improvements to the AArch64 backend
+
+N: Wesley Peck
+E: peckw@wesleypeck.com
+W: http://wesleypeck.com/
+D: MicroBlaze backend
+
+N: Francois Pichet
+E: pichet2000@gmail.com
+D: MSVC support
+
+N: Adrian Prantl
+E: aprantl@apple.com
+D: Debug Information
+
+N: Vladimir Prus
+W: http://vladimir_prus.blogspot.com
+E: ghost@cs.msu.su
+D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass
+
+N: Kalle Raiskila
+E: kalle.rasikila@nokia.com
+D: Some bugfixes to CellSPU
+
+N: Xerxes Ranby
+E: xerxes@zafena.se
+D: Cmake dependency chain and various bug fixes
+
+N: Alex Rosenberg
+E: alexr@leftfield.org
+I: arosenberg
+D: ARM calling conventions rewrite, hard float support
+
+N: Chad Rosier
+E: mcrosier@codeaurora.org
+I: mcrosier
+D: AArch64 fast instruction selection pass
+D: Fixes and improvements to the ARM fast-isel pass
+D: Fixes and improvements to the AArch64 backend
+
+N: Nadav Rotem
+E: nadav.rotem@me.com
+D: X86 code generation improvements, Loop Vectorizer.
+
+N: Roman Samoilov
+E: roman@codedgers.com
+D: MSIL backend
+
+N: Duncan Sands
+E: baldrick@free.fr
+I: baldrick
+D: Ada support in llvm-gcc
+D: Dragonegg plugin
+D: Exception handling improvements
+D: Type legalizer rewrite
+
+N: Ruchira Sasanka
+E: sasanka@uiuc.edu
+D: Graph coloring register allocator for the Sparc64 backend
+
+N: Arnold Schwaighofer
+E: arnold.schwaighofer@gmail.com
+D: Tail call optimization for the x86 backend
+
+N: Shantonu Sen
+E: ssen@apple.com
+D: Miscellaneous bug fixes
+
+N: Anand Shukla
+E: ashukla@cs.uiuc.edu
+D: The `paths' pass
+
+N: Michael J. Spencer
+E: bigcheesegs@gmail.com
+D: Shepherding Windows COFF support into MC.
+D: Lots of Windows stuff.
+
+N: Reid Spencer
+E: rspencer@reidspencer.com
+W: http://reidspencer.com/
+D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid
+
+N: Alp Toker
+E: alp@nuanti.com
+W: http://atoker.com/
+D: C++ frontend next generation standards implementation
+
+N: Craig Topper
+E: craig.topper@gmail.com
+D: X86 codegen and disassembler improvements. AVX2 support.
+
+N: Edwin Torok
+E: edwintorok@gmail.com
+D: Miscellaneous bug fixes
+
+N: Adam Treat
+E: manyoso@yahoo.com
+D: C++ bugs filed, and C++ front-end bug fixes.
+
+N: Lauro Ramos Venancio
+E: lauro.venancio@indt.org.br
+D: ARM backend improvements
+D: Thread Local Storage implementation
+
+N: Bill Wendling
+I: wendling
+E: isanbard@gmail.com
+D: Release manager, IR Linker, LTO
+D: Bunches of stuff
+
+N: Bob Wilson
+E: bob.wilson@acm.org
+D: Advanced SIMD (NEON) support in the ARM backend.
+
diff --git a/third_party/llvm-subzero/LICENSE.TXT b/third_party/llvm-subzero/LICENSE.TXT
new file mode 100644
index 0000000..555c8bb
--- /dev/null
+++ b/third_party/llvm-subzero/LICENSE.TXT
@@ -0,0 +1,68 @@
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2016 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+Google Test         llvm/utils/unittest/googletest
+OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
+pyyaml tests        llvm/test/YAMLParser/{*.data, LICENSE.TXT}
+ARM contributions   llvm/lib/Target/ARM/LICENSE.TXT
+md5 contributions   llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
diff --git a/third_party/llvm-subzero/README.txt b/third_party/llvm-subzero/README.txt
new file mode 100644
index 0000000..d7a90ec
--- /dev/null
+++ b/third_party/llvm-subzero/README.txt
@@ -0,0 +1,25 @@
+llvm-subzero

+============

+

+This directory and its subdirectories contain a subset of the source code for

+LLVM, required by Subzero.

+

+The original README.txt content follows:

+

+Low Level Virtual Machine (LLVM)

+================================

+

+This directory and its subdirectories contain source code for LLVM,

+a toolkit for the construction of highly optimized compilers,

+optimizers, and runtime environments.

+

+LLVM is open source software. You may freely distribute it under the terms of

+the license agreement found in LICENSE.txt.

+

+Please see the documentation provided in docs/ for further

+assistance with LLVM, and in particular docs/GettingStarted.rst for getting

+started with LLVM and docs/README.txt for an overview of LLVM's

+documentation setup.

+

+If you are writing a package for LLVM, see docs/Packaging.rst for our

+suggestions.

diff --git a/third_party/llvm-subzero/include/llvm-c/ErrorHandling.h b/third_party/llvm-subzero/include/llvm-c/ErrorHandling.h
new file mode 100644
index 0000000..2059b3a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm-c/ErrorHandling.h
@@ -0,0 +1,49 @@
+/*===-- llvm-c/ErrorHandling.h - Error Handling C Interface -------*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file defines the C interface to LLVM's error handling mechanism.      *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_ERROR_HANDLING_H
+#define LLVM_C_ERROR_HANDLING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*LLVMFatalErrorHandler)(const char *Reason);
+
+/**
+ * Install a fatal error handler. By default, if LLVM detects a fatal error, it
+ * will call exit(1). This may not be appropriate in many contexts. For example,
+ * doing exit(1) will bypass many crash reporting/tracing system tools. This
+ * function allows you to install a callback that will be invoked prior to the
+ * call to exit(1).
+ */
+void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler);
+
+/**
+ * Reset the fatal error handler. This resets LLVM's fatal error handling
+ * behavior to the default.
+ */
+void LLVMResetFatalErrorHandler(void);
+
+/**
+ * Enable LLVM's built-in stack trace code. This intercepts the OS's crash
+ * signals and prints which component of LLVM you were in at the time if the
+ * crash.
+ */
+void LLVMEnablePrettyStackTrace(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm-c/Support.h b/third_party/llvm-subzero/include/llvm-c/Support.h
new file mode 100644
index 0000000..735d1fb
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm-c/Support.h
@@ -0,0 +1,65 @@
+/*===-- llvm-c/Support.h - Support C Interface --------------------*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file defines the C interface to the LLVM support library.             *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_SUPPORT_H
+#define LLVM_C_SUPPORT_H
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm-c/Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This function permanently loads the dynamic library at the given path.
+ * It is safe to call this function multiple times for the same library.
+ *
+ * @see sys::DynamicLibrary::LoadLibraryPermanently()
+  */
+LLVMBool LLVMLoadLibraryPermanently(const char* Filename);
+
+/**
+ * This function parses the given arguments using the LLVM command line parser.
+ * Note that the only stable thing about this function is its signature; you
+ * cannot rely on any particular set of command line arguments being interpreted
+ * the same way across LLVM versions.
+ *
+ * @see llvm::cl::ParseCommandLineOptions()
+ */
+void LLVMParseCommandLineOptions(int argc, const char *const *argv,
+                                 const char *Overview);
+
+/**
+ * This function will search through all previously loaded dynamic
+ * libraries for the symbol \p symbolName. If it is found, the address of
+ * that symbol is returned. If not, null is returned.
+ *
+ * @see sys::DynamicLibrary::SearchForAddressOfSymbol()
+ */
+void *LLVMSearchForAddressOfSymbol(const char *symbolName);
+
+/**
+ * This functions permanently adds the symbol \p symbolName with the
+ * value \p symbolValue.  These symbols are searched before any
+ * libraries.
+ *
+ * @see sys::DynamicLibrary::AddSymbol()
+ */
+void LLVMAddSymbol(const char *symbolName, void *symbolValue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm-c/Types.h b/third_party/llvm-subzero/include/llvm-c/Types.h
new file mode 100644
index 0000000..3d472a6
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm-c/Types.h
@@ -0,0 +1,131 @@
+/*===-- llvm-c/Support.h - C Interface Types declarations ---------*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file defines types used by the the C interface to LLVM.               *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_TYPES_H
+#define LLVM_C_TYPES_H
+
+#include "llvm/Support/DataTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup LLVMCSupportTypes Types and Enumerations
+ *
+ * @{
+ */
+
+typedef int LLVMBool;
+
+/* Opaque types. */
+
+/**
+ * LLVM uses a polymorphic type hierarchy which C cannot represent, therefore
+ * parameters must be passed as base types. Despite the declared types, most
+ * of the functions provided operate only on branches of the type hierarchy.
+ * The declared parameter names are descriptive and specify which type is
+ * required. Additionally, each type hierarchy is documented along with the
+ * functions that operate upon it. For more detail, refer to LLVM's C++ code.
+ * If in doubt, refer to Core.cpp, which performs parameter downcasts in the
+ * form unwrap<RequiredType>(Param).
+ */
+
+/**
+ * Used to pass regions of memory through LLVM interfaces.
+ *
+ * @see llvm::MemoryBuffer
+ */
+typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef;
+
+/**
+ * The top-level container for all LLVM global data. See the LLVMContext class.
+ */
+typedef struct LLVMOpaqueContext *LLVMContextRef;
+
+/**
+ * The top-level container for all other LLVM Intermediate Representation (IR)
+ * objects.
+ *
+ * @see llvm::Module
+ */
+typedef struct LLVMOpaqueModule *LLVMModuleRef;
+
+/**
+ * Each value in the LLVM IR has a type, an LLVMTypeRef.
+ *
+ * @see llvm::Type
+ */
+typedef struct LLVMOpaqueType *LLVMTypeRef;
+
+/**
+ * Represents an individual value in LLVM IR.
+ *
+ * This models llvm::Value.
+ */
+typedef struct LLVMOpaqueValue *LLVMValueRef;
+
+/**
+ * Represents a basic block of instructions in LLVM IR.
+ *
+ * This models llvm::BasicBlock.
+ */
+typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
+
+/**
+ * Represents an LLVM basic block builder.
+ *
+ * This models llvm::IRBuilder.
+ */
+typedef struct LLVMOpaqueBuilder *LLVMBuilderRef;
+
+/**
+ * Interface used to provide a module to JIT or interpreter.
+ * This is now just a synonym for llvm::Module, but we have to keep using the
+ * different type to keep binary compatibility.
+ */
+typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef;
+
+/** @see llvm::PassManagerBase */
+typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
+
+/** @see llvm::PassRegistry */
+typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef;
+
+/**
+ * Used to get the users and usees of a Value.
+ *
+ * @see llvm::Use */
+typedef struct LLVMOpaqueUse *LLVMUseRef;
+
+/**
+ * Used to represent an attributes.
+ *
+ * @see llvm::Attribute
+ */
+typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef;
+
+/**
+ * @see llvm::DiagnosticInfo
+ */
+typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/APFloat.h b/third_party/llvm-subzero/include/llvm/ADT/APFloat.h
new file mode 100644
index 0000000..3f6bd00
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/APFloat.h
@@ -0,0 +1,689 @@
+//===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief
+/// This file declares a class to represent arbitrary precision floating point
+/// values and provide a variety of arithmetic operations on them.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_APFLOAT_H
+#define LLVM_ADT_APFLOAT_H
+
+#include "llvm/ADT/APInt.h"
+
+namespace llvm {
+
+struct fltSemantics;
+class APSInt;
+class StringRef;
+
+template <typename T> class SmallVectorImpl;
+
+/// Enum that represents what fraction of the LSB truncated bits of an fp number
+/// represent.
+///
+/// This essentially combines the roles of guard and sticky bits.
+enum lostFraction { // Example of truncated bits:
+  lfExactlyZero,    // 000000
+  lfLessThanHalf,   // 0xxxxx  x's not all zero
+  lfExactlyHalf,    // 100000
+  lfMoreThanHalf    // 1xxxxx  x's not all zero
+};
+
+/// \brief A self-contained host- and target-independent arbitrary-precision
+/// floating-point software implementation.
+///
+/// APFloat uses bignum integer arithmetic as provided by static functions in
+/// the APInt class.  The library will work with bignum integers whose parts are
+/// any unsigned type at least 16 bits wide, but 64 bits is recommended.
+///
+/// Written for clarity rather than speed, in particular with a view to use in
+/// the front-end of a cross compiler so that target arithmetic can be correctly
+/// performed on the host.  Performance should nonetheless be reasonable,
+/// particularly for its intended use.  It may be useful as a base
+/// implementation for a run-time library during development of a faster
+/// target-specific one.
+///
+/// All 5 rounding modes in the IEEE-754R draft are handled correctly for all
+/// implemented operations.  Currently implemented operations are add, subtract,
+/// multiply, divide, fused-multiply-add, conversion-to-float,
+/// conversion-to-integer and conversion-from-integer.  New rounding modes
+/// (e.g. away from zero) can be added with three or four lines of code.
+///
+/// Four formats are built-in: IEEE single precision, double precision,
+/// quadruple precision, and x87 80-bit extended double (when operating with
+/// full extended precision).  Adding a new format that obeys IEEE semantics
+/// only requires adding two lines of code: a declaration and definition of the
+/// format.
+///
+/// All operations return the status of that operation as an exception bit-mask,
+/// so multiple operations can be done consecutively with their results or-ed
+/// together.  The returned status can be useful for compiler diagnostics; e.g.,
+/// inexact, underflow and overflow can be easily diagnosed on constant folding,
+/// and compiler optimizers can determine what exceptions would be raised by
+/// folding operations and optimize, or perhaps not optimize, accordingly.
+///
+/// At present, underflow tininess is detected after rounding; it should be
+/// straight forward to add support for the before-rounding case too.
+///
+/// The library reads hexadecimal floating point numbers as per C99, and
+/// correctly rounds if necessary according to the specified rounding mode.
+/// Syntax is required to have been validated by the caller.  It also converts
+/// floating point numbers to hexadecimal text as per the C99 %a and %A
+/// conversions.  The output precision (or alternatively the natural minimal
+/// precision) can be specified; if the requested precision is less than the
+/// natural precision the output is correctly rounded for the specified rounding
+/// mode.
+///
+/// It also reads decimal floating point numbers and correctly rounds according
+/// to the specified rounding mode.
+///
+/// Conversion to decimal text is not currently implemented.
+///
+/// Non-zero finite numbers are represented internally as a sign bit, a 16-bit
+/// signed exponent, and the significand as an array of integer parts.  After
+/// normalization of a number of precision P the exponent is within the range of
+/// the format, and if the number is not denormal the P-th bit of the
+/// significand is set as an explicit integer bit.  For denormals the most
+/// significant bit is shifted right so that the exponent is maintained at the
+/// format's minimum, so that the smallest denormal has just the least
+/// significant bit of the significand set.  The sign of zeroes and infinities
+/// is significant; the exponent and significand of such numbers is not stored,
+/// but has a known implicit (deterministic) value: 0 for the significands, 0
+/// for zero exponent, all 1 bits for infinity exponent.  For NaNs the sign and
+/// significand are deterministic, although not really meaningful, and preserved
+/// in non-conversion operations.  The exponent is implicitly all 1 bits.
+///
+/// APFloat does not provide any exception handling beyond default exception
+/// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause
+/// by encoding Signaling NaNs with the first bit of its trailing significand as
+/// 0.
+///
+/// TODO
+/// ====
+///
+/// Some features that may or may not be worth adding:
+///
+/// Binary to decimal conversion (hard).
+///
+/// Optional ability to detect underflow tininess before rounding.
+///
+/// New formats: x87 in single and double precision mode (IEEE apart from
+/// extended exponent range) (hard).
+///
+/// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward.
+///
+class APFloat {
+public:
+
+  /// A signed type to represent a floating point numbers unbiased exponent.
+  typedef signed short ExponentType;
+
+  /// \name Floating Point Semantics.
+  /// @{
+
+  static const fltSemantics IEEEhalf;
+  static const fltSemantics IEEEsingle;
+  static const fltSemantics IEEEdouble;
+  static const fltSemantics IEEEquad;
+  static const fltSemantics PPCDoubleDouble;
+  static const fltSemantics x87DoubleExtended;
+
+  /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with
+  /// anything real.
+  static const fltSemantics Bogus;
+
+  /// @}
+
+  static unsigned int semanticsPrecision(const fltSemantics &);
+  static ExponentType semanticsMinExponent(const fltSemantics &);
+  static ExponentType semanticsMaxExponent(const fltSemantics &);
+  static unsigned int semanticsSizeInBits(const fltSemantics &);
+
+  /// IEEE-754R 5.11: Floating Point Comparison Relations.
+  enum cmpResult {
+    cmpLessThan,
+    cmpEqual,
+    cmpGreaterThan,
+    cmpUnordered
+  };
+
+  /// IEEE-754R 4.3: Rounding-direction attributes.
+  enum roundingMode {
+    rmNearestTiesToEven,
+    rmTowardPositive,
+    rmTowardNegative,
+    rmTowardZero,
+    rmNearestTiesToAway
+  };
+
+  /// IEEE-754R 7: Default exception handling.
+  ///
+  /// opUnderflow or opOverflow are always returned or-ed with opInexact.
+  enum opStatus {
+    opOK = 0x00,
+    opInvalidOp = 0x01,
+    opDivByZero = 0x02,
+    opOverflow = 0x04,
+    opUnderflow = 0x08,
+    opInexact = 0x10
+  };
+
+  /// Category of internally-represented number.
+  enum fltCategory {
+    fcInfinity,
+    fcNaN,
+    fcNormal,
+    fcZero
+  };
+
+  /// Convenience enum used to construct an uninitialized APFloat.
+  enum uninitializedTag {
+    uninitialized
+  };
+
+  /// \name Constructors
+  /// @{
+
+  APFloat(const fltSemantics &); // Default construct to 0.0
+  APFloat(const fltSemantics &, StringRef);
+  APFloat(const fltSemantics &, integerPart);
+  APFloat(const fltSemantics &, uninitializedTag);
+  APFloat(const fltSemantics &, const APInt &);
+  explicit APFloat(double d);
+  explicit APFloat(float f);
+  APFloat(const APFloat &);
+  APFloat(APFloat &&);
+  ~APFloat();
+
+  /// @}
+
+  /// \brief Returns whether this instance allocated memory.
+  bool needsCleanup() const { return partCount() > 1; }
+
+  /// \name Convenience "constructors"
+  /// @{
+
+  /// Factory for Positive and Negative Zero.
+  ///
+  /// \param Negative True iff the number should be negative.
+  static APFloat getZero(const fltSemantics &Sem, bool Negative = false) {
+    APFloat Val(Sem, uninitialized);
+    Val.makeZero(Negative);
+    return Val;
+  }
+
+  /// Factory for Positive and Negative Infinity.
+  ///
+  /// \param Negative True iff the number should be negative.
+  static APFloat getInf(const fltSemantics &Sem, bool Negative = false) {
+    APFloat Val(Sem, uninitialized);
+    Val.makeInf(Negative);
+    return Val;
+  }
+
+  /// Factory for QNaN values.
+  ///
+  /// \param Negative - True iff the NaN generated should be negative.
+  /// \param type - The unspecified fill bits for creating the NaN, 0 by
+  /// default.  The value is truncated as necessary.
+  static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
+                        unsigned type = 0) {
+    if (type) {
+      APInt fill(64, type);
+      return getQNaN(Sem, Negative, &fill);
+    } else {
+      return getQNaN(Sem, Negative, nullptr);
+    }
+  }
+
+  /// Factory for QNaN values.
+  static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
+                         const APInt *payload = nullptr) {
+    return makeNaN(Sem, false, Negative, payload);
+  }
+
+  /// Factory for SNaN values.
+  static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
+                         const APInt *payload = nullptr) {
+    return makeNaN(Sem, true, Negative, payload);
+  }
+
+  /// Returns the largest finite number in the given semantics.
+  ///
+  /// \param Negative - True iff the number should be negative
+  static APFloat getLargest(const fltSemantics &Sem, bool Negative = false);
+
+  /// Returns the smallest (by magnitude) finite number in the given semantics.
+  /// Might be denormalized, which implies a relative loss of precision.
+  ///
+  /// \param Negative - True iff the number should be negative
+  static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false);
+
+  /// Returns the smallest (by magnitude) normalized finite number in the given
+  /// semantics.
+  ///
+  /// \param Negative - True iff the number should be negative
+  static APFloat getSmallestNormalized(const fltSemantics &Sem,
+                                       bool Negative = false);
+
+  /// Returns a float which is bitcasted from an all one value int.
+  ///
+  /// \param BitWidth - Select float type
+  /// \param isIEEE   - If 128 bit number, select between PPC and IEEE
+  static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
+
+  /// Returns the size of the floating point number (in bits) in the given
+  /// semantics.
+  static unsigned getSizeInBits(const fltSemantics &Sem);
+
+  /// @}
+
+  /// Used to insert APFloat objects, or objects that contain APFloat objects,
+  /// into FoldingSets.
+  void Profile(FoldingSetNodeID &NID) const;
+
+  /// \name Arithmetic
+  /// @{
+
+  opStatus add(const APFloat &, roundingMode);
+  opStatus subtract(const APFloat &, roundingMode);
+  opStatus multiply(const APFloat &, roundingMode);
+  opStatus divide(const APFloat &, roundingMode);
+  /// IEEE remainder.
+  opStatus remainder(const APFloat &);
+  /// C fmod, or llvm frem.
+  opStatus mod(const APFloat &);
+  opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode);
+  opStatus roundToIntegral(roundingMode);
+  /// IEEE-754R 5.3.1: nextUp/nextDown.
+  opStatus next(bool nextDown);
+
+  /// \brief Operator+ overload which provides the default
+  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+  APFloat operator+(const APFloat &RHS) const {
+    APFloat Result = *this;
+    Result.add(RHS, rmNearestTiesToEven);
+    return Result;
+  }
+
+  /// \brief Operator- overload which provides the default
+  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+  APFloat operator-(const APFloat &RHS) const {
+    APFloat Result = *this;
+    Result.subtract(RHS, rmNearestTiesToEven);
+    return Result;
+  }
+
+  /// \brief Operator* overload which provides the default
+  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+  APFloat operator*(const APFloat &RHS) const {
+    APFloat Result = *this;
+    Result.multiply(RHS, rmNearestTiesToEven);
+    return Result;
+  }
+
+  /// \brief Operator/ overload which provides the default
+  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
+  APFloat operator/(const APFloat &RHS) const {
+    APFloat Result = *this;
+    Result.divide(RHS, rmNearestTiesToEven);
+    return Result;
+  }
+
+  /// @}
+
+  /// \name Sign operations.
+  /// @{
+
+  void changeSign();
+  void clearSign();
+  void copySign(const APFloat &);
+
+  /// \brief A static helper to produce a copy of an APFloat value with its sign
+  /// copied from some other APFloat.
+  static APFloat copySign(APFloat Value, const APFloat &Sign) {
+    Value.copySign(Sign);
+    return Value;
+  }
+
+  /// @}
+
+  /// \name Conversions
+  /// @{
+
+  opStatus convert(const fltSemantics &, roundingMode, bool *);
+  opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode,
+                            bool *) const;
+  opStatus convertToInteger(APSInt &, roundingMode, bool *) const;
+  opStatus convertFromAPInt(const APInt &, bool, roundingMode);
+  opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
+                                          bool, roundingMode);
+  opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int,
+                                          bool, roundingMode);
+  opStatus convertFromString(StringRef, roundingMode);
+  APInt bitcastToAPInt() const;
+  double convertToDouble() const;
+  float convertToFloat() const;
+
+  /// @}
+
+  /// The definition of equality is not straightforward for floating point, so
+  /// we won't use operator==.  Use one of the following, or write whatever it
+  /// is you really mean.
+  bool operator==(const APFloat &) const = delete;
+
+  /// IEEE comparison with another floating point number (NaNs compare
+  /// unordered, 0==-0).
+  cmpResult compare(const APFloat &) const;
+
+  /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0).
+  bool bitwiseIsEqual(const APFloat &) const;
+
+  /// Write out a hexadecimal representation of the floating point value to DST,
+  /// which must be of sufficient size, in the C99 form [-]0xh.hhhhp[+-]d.
+  /// Return the number of characters written, excluding the terminating NUL.
+  unsigned int convertToHexString(char *dst, unsigned int hexDigits,
+                                  bool upperCase, roundingMode) const;
+
+  /// \name IEEE-754R 5.7.2 General operations.
+  /// @{
+
+  /// IEEE-754R isSignMinus: Returns true if and only if the current value is
+  /// negative.
+  ///
+  /// This applies to zeros and NaNs as well.
+  bool isNegative() const { return sign; }
+
+  /// IEEE-754R isNormal: Returns true if and only if the current value is normal.
+  ///
+  /// This implies that the current value of the float is not zero, subnormal,
+  /// infinite, or NaN following the definition of normality from IEEE-754R.
+  bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
+
+  /// Returns true if and only if the current value is zero, subnormal, or
+  /// normal.
+  ///
+  /// This means that the value is not infinite or NaN.
+  bool isFinite() const { return !isNaN() && !isInfinity(); }
+
+  /// Returns true if and only if the float is plus or minus zero.
+  bool isZero() const { return category == fcZero; }
+
+  /// IEEE-754R isSubnormal(): Returns true if and only if the float is a
+  /// denormal.
+  bool isDenormal() const;
+
+  /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity.
+  bool isInfinity() const { return category == fcInfinity; }
+
+  /// Returns true if and only if the float is a quiet or signaling NaN.
+  bool isNaN() const { return category == fcNaN; }
+
+  /// Returns true if and only if the float is a signaling NaN.
+  bool isSignaling() const;
+
+  /// @}
+
+  /// \name Simple Queries
+  /// @{
+
+  fltCategory getCategory() const { return category; }
+  const fltSemantics &getSemantics() const { return *semantics; }
+  bool isNonZero() const { return category != fcZero; }
+  bool isFiniteNonZero() const { return isFinite() && !isZero(); }
+  bool isPosZero() const { return isZero() && !isNegative(); }
+  bool isNegZero() const { return isZero() && isNegative(); }
+
+  /// Returns true if and only if the number has the smallest possible non-zero
+  /// magnitude in the current semantics.
+  bool isSmallest() const;
+
+  /// Returns true if and only if the number has the largest possible finite
+  /// magnitude in the current semantics.
+  bool isLargest() const;
+  
+  /// Returns true if and only if the number is an exact integer.
+  bool isInteger() const;
+
+  /// @}
+
+  APFloat &operator=(const APFloat &);
+  APFloat &operator=(APFloat &&);
+
+  /// \brief Overload to compute a hash code for an APFloat value.
+  ///
+  /// Note that the use of hash codes for floating point values is in general
+  /// frought with peril. Equality is hard to define for these values. For
+  /// example, should negative and positive zero hash to different codes? Are
+  /// they equal or not? This hash value implementation specifically
+  /// emphasizes producing different codes for different inputs in order to
+  /// be used in canonicalization and memoization. As such, equality is
+  /// bitwiseIsEqual, and 0 != -0.
+  friend hash_code hash_value(const APFloat &Arg);
+
+  /// Converts this value into a decimal string.
+  ///
+  /// \param FormatPrecision The maximum number of digits of
+  ///   precision to output.  If there are fewer digits available,
+  ///   zero padding will not be used unless the value is
+  ///   integral and small enough to be expressed in
+  ///   FormatPrecision digits.  0 means to use the natural
+  ///   precision of the number.
+  /// \param FormatMaxPadding The maximum number of zeros to
+  ///   consider inserting before falling back to scientific
+  ///   notation.  0 means to always use scientific notation.
+  ///
+  /// Number       Precision    MaxPadding      Result
+  /// ------       ---------    ----------      ------
+  /// 1.01E+4              5             2       10100
+  /// 1.01E+4              4             2       1.01E+4
+  /// 1.01E+4              5             1       1.01E+4
+  /// 1.01E-2              5             2       0.0101
+  /// 1.01E-2              4             2       0.0101
+  /// 1.01E-2              4             1       1.01E-2
+  void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
+                unsigned FormatMaxPadding = 3) const;
+
+  /// If this value has an exact multiplicative inverse, store it in inv and
+  /// return true.
+  bool getExactInverse(APFloat *inv) const;
+
+  /// \brief Enumeration of \c ilogb error results.
+  enum IlogbErrorKinds {
+    IEK_Zero = INT_MIN+1,
+    IEK_NaN = INT_MIN,
+    IEK_Inf = INT_MAX
+  };
+
+  /// \brief Returns the exponent of the internal representation of the APFloat.
+  ///
+  /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
+  /// For special APFloat values, this returns special error codes:
+  ///
+  ///   NaN -> \c IEK_NaN
+  ///   0   -> \c IEK_Zero
+  ///   Inf -> \c IEK_Inf
+  ///
+  friend int ilogb(const APFloat &Arg);
+
+  /// \brief Returns: X * 2^Exp for integral exponents.
+  friend APFloat scalbn(APFloat X, int Exp, roundingMode);
+
+  friend APFloat frexp(const APFloat &X, int &Exp, roundingMode);
+
+private:
+
+  /// \name Simple Queries
+  /// @{
+
+  integerPart *significandParts();
+  const integerPart *significandParts() const;
+  unsigned int partCount() const;
+
+  /// @}
+
+  /// \name Significand operations.
+  /// @{
+
+  integerPart addSignificand(const APFloat &);
+  integerPart subtractSignificand(const APFloat &, integerPart);
+  lostFraction addOrSubtractSignificand(const APFloat &, bool subtract);
+  lostFraction multiplySignificand(const APFloat &, const APFloat *);
+  lostFraction divideSignificand(const APFloat &);
+  void incrementSignificand();
+  void initialize(const fltSemantics *);
+  void shiftSignificandLeft(unsigned int);
+  lostFraction shiftSignificandRight(unsigned int);
+  unsigned int significandLSB() const;
+  unsigned int significandMSB() const;
+  void zeroSignificand();
+  /// Return true if the significand excluding the integral bit is all ones.
+  bool isSignificandAllOnes() const;
+  /// Return true if the significand excluding the integral bit is all zeros.
+  bool isSignificandAllZeros() const;
+
+  /// @}
+
+  /// \name Arithmetic on special values.
+  /// @{
+
+  opStatus addOrSubtractSpecials(const APFloat &, bool subtract);
+  opStatus divideSpecials(const APFloat &);
+  opStatus multiplySpecials(const APFloat &);
+  opStatus modSpecials(const APFloat &);
+
+  /// @}
+
+  /// \name Special value setters.
+  /// @{
+
+  void makeLargest(bool Neg = false);
+  void makeSmallest(bool Neg = false);
+  void makeNaN(bool SNaN = false, bool Neg = false,
+               const APInt *fill = nullptr);
+  static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
+                         const APInt *fill);
+  void makeInf(bool Neg = false);
+  void makeZero(bool Neg = false);
+  void makeQuiet();
+
+  /// @}
+
+  /// \name Miscellany
+  /// @{
+
+  bool convertFromStringSpecials(StringRef str);
+  opStatus normalize(roundingMode, lostFraction);
+  opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract);
+  cmpResult compareAbsoluteValue(const APFloat &) const;
+  opStatus handleOverflow(roundingMode);
+  bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
+  opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
+                                        roundingMode, bool *) const;
+  opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
+                                    roundingMode);
+  opStatus convertFromHexadecimalString(StringRef, roundingMode);
+  opStatus convertFromDecimalString(StringRef, roundingMode);
+  char *convertNormalToHexString(char *, unsigned int, bool,
+                                 roundingMode) const;
+  opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int,
+                                        roundingMode);
+
+  /// @}
+
+  APInt convertHalfAPFloatToAPInt() const;
+  APInt convertFloatAPFloatToAPInt() const;
+  APInt convertDoubleAPFloatToAPInt() const;
+  APInt convertQuadrupleAPFloatToAPInt() const;
+  APInt convertF80LongDoubleAPFloatToAPInt() const;
+  APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
+  void initFromAPInt(const fltSemantics *Sem, const APInt &api);
+  void initFromHalfAPInt(const APInt &api);
+  void initFromFloatAPInt(const APInt &api);
+  void initFromDoubleAPInt(const APInt &api);
+  void initFromQuadrupleAPInt(const APInt &api);
+  void initFromF80LongDoubleAPInt(const APInt &api);
+  void initFromPPCDoubleDoubleAPInt(const APInt &api);
+
+  void assign(const APFloat &);
+  void copySignificand(const APFloat &);
+  void freeSignificand();
+
+  /// The semantics that this value obeys.
+  const fltSemantics *semantics;
+
+  /// A binary fraction with an explicit integer bit.
+  ///
+  /// The significand must be at least one bit wider than the target precision.
+  union Significand {
+    integerPart part;
+    integerPart *parts;
+  } significand;
+
+  /// The signed unbiased exponent of the value.
+  ExponentType exponent;
+
+  /// What kind of floating point number this is.
+  ///
+  /// Only 2 bits are required, but VisualStudio incorrectly sign extends it.
+  /// Using the extra bit keeps it from failing under VisualStudio.
+  fltCategory category : 3;
+
+  /// Sign bit of the number.
+  unsigned int sign : 1;
+};
+
+/// See friend declarations above.
+///
+/// These additional declarations are required in order to compile LLVM with IBM
+/// xlC compiler.
+hash_code hash_value(const APFloat &Arg);
+int ilogb(const APFloat &Arg);
+APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode);
+
+/// \brief Equivalent of C standard library function.
+///
+/// While the C standard says Exp is an unspecified value for infinity and nan,
+/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
+APFloat frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM);
+
+/// \brief Returns the absolute value of the argument.
+inline APFloat abs(APFloat X) {
+  X.clearSign();
+  return X;
+}
+
+/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if
+/// both are not NaN. If either argument is a NaN, returns the other argument.
+LLVM_READONLY
+inline APFloat minnum(const APFloat &A, const APFloat &B) {
+  if (A.isNaN())
+    return B;
+  if (B.isNaN())
+    return A;
+  return (B.compare(A) == APFloat::cmpLessThan) ? B : A;
+}
+
+/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if
+/// both are not NaN. If either argument is a NaN, returns the other argument.
+LLVM_READONLY
+inline APFloat maxnum(const APFloat &A, const APFloat &B) {
+  if (A.isNaN())
+    return B;
+  if (B.isNaN())
+    return A;
+  return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
+}
+
+} // namespace llvm
+
+#endif // LLVM_ADT_APFLOAT_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/APInt.h b/third_party/llvm-subzero/include/llvm/ADT/APInt.h
new file mode 100644
index 0000000..23c6c14
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/APInt.h
@@ -0,0 +1,1972 @@
+//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements a class to represent arbitrary precision
+/// integral constant values and operations on them.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_APINT_H
+#define LLVM_ADT_APINT_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <string>
+
+namespace llvm {
+class FoldingSetNodeID;
+class StringRef;
+class hash_code;
+class raw_ostream;
+
+template <typename T> class SmallVectorImpl;
+template <typename T> class ArrayRef;
+
+// An unsigned host type used as a single part of a multi-part
+// bignum.
+typedef uint64_t integerPart;
+
+const unsigned int host_char_bit = 8;
+const unsigned int integerPartWidth =
+    host_char_bit * static_cast<unsigned int>(sizeof(integerPart));
+
+class APInt;
+
+inline APInt operator-(APInt);
+
+//===----------------------------------------------------------------------===//
+//                              APInt Class
+//===----------------------------------------------------------------------===//
+
+/// \brief Class for arbitrary precision integers.
+///
+/// APInt is a functional replacement for common case unsigned integer type like
+/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width
+/// integer sizes and large integer value types such as 3-bits, 15-bits, or more
+/// than 64-bits of precision. APInt provides a variety of arithmetic operators
+/// and methods to manipulate integer values of any bit-width. It supports both
+/// the typical integer arithmetic and comparison operations as well as bitwise
+/// manipulation.
+///
+/// The class has several invariants worth noting:
+///   * All bit, byte, and word positions are zero-based.
+///   * Once the bit width is set, it doesn't change except by the Truncate,
+///     SignExtend, or ZeroExtend operations.
+///   * All binary operators must be on APInt instances of the same bit width.
+///     Attempting to use these operators on instances with different bit
+///     widths will yield an assertion.
+///   * The value is stored canonically as an unsigned value. For operations
+///     where it makes a difference, there are both signed and unsigned variants
+///     of the operation. For example, sdiv and udiv. However, because the bit
+///     widths must be the same, operations such as Mul and Add produce the same
+///     results regardless of whether the values are interpreted as signed or
+///     not.
+///   * In general, the class tries to follow the style of computation that LLVM
+///     uses in its IR. This simplifies its use for LLVM.
+///
+class APInt {
+  unsigned BitWidth; ///< The number of bits in this APInt.
+
+  /// This union is used to store the integer value. When the
+  /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal.
+  union {
+    uint64_t VAL;   ///< Used to store the <= 64 bits integer value.
+    uint64_t *pVal; ///< Used to store the >64 bits integer value.
+  };
+
+  /// This enum is used to hold the constants we needed for APInt.
+  enum {
+    /// Bits in a word
+    APINT_BITS_PER_WORD =
+        static_cast<unsigned int>(sizeof(uint64_t)) * CHAR_BIT,
+    /// Byte size of a word
+    APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t))
+  };
+
+  friend struct DenseMapAPIntKeyInfo;
+
+  /// \brief Fast internal constructor
+  ///
+  /// This constructor is used only internally for speed of construction of
+  /// temporaries. It is unsafe for general use so it is not public.
+  APInt(uint64_t *val, unsigned bits) : BitWidth(bits), pVal(val) {}
+
+  /// \brief Determine if this APInt just has one word to store value.
+  ///
+  /// \returns true if the number of bits <= 64, false otherwise.
+  bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; }
+
+  /// \brief Determine which word a bit is in.
+  ///
+  /// \returns the word position for the specified bit position.
+  static unsigned whichWord(unsigned bitPosition) {
+    return bitPosition / APINT_BITS_PER_WORD;
+  }
+
+  /// \brief Determine which bit in a word a bit is in.
+  ///
+  /// \returns the bit position in a word for the specified bit position
+  /// in the APInt.
+  static unsigned whichBit(unsigned bitPosition) {
+    return bitPosition % APINT_BITS_PER_WORD;
+  }
+
+  /// \brief Get a single bit mask.
+  ///
+  /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set
+  /// This method generates and returns a uint64_t (word) mask for a single
+  /// bit at a specific bit position. This is used to mask the bit in the
+  /// corresponding word.
+  static uint64_t maskBit(unsigned bitPosition) {
+    return 1ULL << whichBit(bitPosition);
+  }
+
+  /// \brief Clear unused high order bits
+  ///
+  /// This method is used internally to clear the top "N" bits in the high order
+  /// word that are not used by the APInt. This is needed after the most
+  /// significant word is assigned a value to ensure that those bits are
+  /// zero'd out.
+  APInt &clearUnusedBits() {
+    // Compute how many bits are used in the final word
+    unsigned wordBits = BitWidth % APINT_BITS_PER_WORD;
+    if (wordBits == 0)
+      // If all bits are used, we want to leave the value alone. This also
+      // avoids the undefined behavior of >> when the shift is the same size as
+      // the word size (64).
+      return *this;
+
+    // Mask out the high bits.
+    uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits);
+    if (isSingleWord())
+      VAL &= mask;
+    else
+      pVal[getNumWords() - 1] &= mask;
+    return *this;
+  }
+
+  /// \brief Get the word corresponding to a bit position
+  /// \returns the corresponding word for the specified bit position.
+  uint64_t getWord(unsigned bitPosition) const {
+    return isSingleWord() ? VAL : pVal[whichWord(bitPosition)];
+  }
+
+  /// \brief Convert a char array into an APInt
+  ///
+  /// \param radix 2, 8, 10, 16, or 36
+  /// Converts a string into a number.  The string must be non-empty
+  /// and well-formed as a number of the given base. The bit-width
+  /// must be sufficient to hold the result.
+  ///
+  /// This is used by the constructors that take string arguments.
+  ///
+  /// StringRef::getAsInteger is superficially similar but (1) does
+  /// not assume that the string is well-formed and (2) grows the
+  /// result to hold the input.
+  void fromString(unsigned numBits, StringRef str, uint8_t radix);
+
+  /// \brief An internal division function for dividing APInts.
+  ///
+  /// This is used by the toString method to divide by the radix. It simply
+  /// provides a more convenient form of divide for internal use since KnuthDiv
+  /// has specific constraints on its inputs. If those constraints are not met
+  /// then it provides a simpler form of divide.
+  static void divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
+                     unsigned rhsWords, APInt *Quotient, APInt *Remainder);
+
+  /// out-of-line slow case for inline constructor
+  void initSlowCase(uint64_t val, bool isSigned);
+
+  /// shared code between two array constructors
+  void initFromArray(ArrayRef<uint64_t> array);
+
+  /// out-of-line slow case for inline copy constructor
+  void initSlowCase(const APInt &that);
+
+  /// out-of-line slow case for shl
+  APInt shlSlowCase(unsigned shiftAmt) const;
+
+  /// out-of-line slow case for operator&
+  APInt AndSlowCase(const APInt &RHS) const;
+
+  /// out-of-line slow case for operator|
+  APInt OrSlowCase(const APInt &RHS) const;
+
+  /// out-of-line slow case for operator^
+  APInt XorSlowCase(const APInt &RHS) const;
+
+  /// out-of-line slow case for operator=
+  APInt &AssignSlowCase(const APInt &RHS);
+
+  /// out-of-line slow case for operator==
+  bool EqualSlowCase(const APInt &RHS) const;
+
+  /// out-of-line slow case for operator==
+  bool EqualSlowCase(uint64_t Val) const;
+
+  /// out-of-line slow case for countLeadingZeros
+  unsigned countLeadingZerosSlowCase() const;
+
+  /// out-of-line slow case for countTrailingOnes
+  unsigned countTrailingOnesSlowCase() const;
+
+  /// out-of-line slow case for countPopulation
+  unsigned countPopulationSlowCase() const;
+
+public:
+  /// \name Constructors
+  /// @{
+
+  /// \brief Create a new APInt of numBits width, initialized as val.
+  ///
+  /// If isSigned is true then val is treated as if it were a signed value
+  /// (i.e. as an int64_t) and the appropriate sign extension to the bit width
+  /// will be done. Otherwise, no sign extension occurs (high order bits beyond
+  /// the range of val are zero filled).
+  ///
+  /// \param numBits the bit width of the constructed APInt
+  /// \param val the initial value of the APInt
+  /// \param isSigned how to treat signedness of val
+  APInt(unsigned numBits, uint64_t val, bool isSigned = false)
+      : BitWidth(numBits), VAL(0) {
+    assert(BitWidth && "bitwidth too small");
+    if (isSingleWord())
+      VAL = val;
+    else
+      initSlowCase(val, isSigned);
+    clearUnusedBits();
+  }
+
+  /// \brief Construct an APInt of numBits width, initialized as bigVal[].
+  ///
+  /// Note that bigVal.size() can be smaller or larger than the corresponding
+  /// bit width but any extraneous bits will be dropped.
+  ///
+  /// \param numBits the bit width of the constructed APInt
+  /// \param bigVal a sequence of words to form the initial value of the APInt
+  APInt(unsigned numBits, ArrayRef<uint64_t> bigVal);
+
+  /// Equivalent to APInt(numBits, ArrayRef<uint64_t>(bigVal, numWords)), but
+  /// deprecated because this constructor is prone to ambiguity with the
+  /// APInt(unsigned, uint64_t, bool) constructor.
+  ///
+  /// If this overload is ever deleted, care should be taken to prevent calls
+  /// from being incorrectly captured by the APInt(unsigned, uint64_t, bool)
+  /// constructor.
+  APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]);
+
+  /// \brief Construct an APInt from a string representation.
+  ///
+  /// This constructor interprets the string \p str in the given radix. The
+  /// interpretation stops when the first character that is not suitable for the
+  /// radix is encountered, or the end of the string. Acceptable radix values
+  /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the
+  /// string to require more bits than numBits.
+  ///
+  /// \param numBits the bit width of the constructed APInt
+  /// \param str the string to be interpreted
+  /// \param radix the radix to use for the conversion
+  APInt(unsigned numBits, StringRef str, uint8_t radix);
+
+  /// Simply makes *this a copy of that.
+  /// @brief Copy Constructor.
+  APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) {
+    if (isSingleWord())
+      VAL = that.VAL;
+    else
+      initSlowCase(that);
+  }
+
+  /// \brief Move Constructor.
+  APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) {
+    that.BitWidth = 0;
+  }
+
+  /// \brief Destructor.
+  ~APInt() {
+    if (needsCleanup())
+      delete[] pVal;
+  }
+
+  /// \brief Default constructor that creates an uninteresting APInt
+  /// representing a 1-bit zero value.
+  ///
+  /// This is useful for object deserialization (pair this with the static
+  ///  method Read).
+  explicit APInt() : BitWidth(1), VAL(0) {}
+
+  /// \brief Returns whether this instance allocated memory.
+  bool needsCleanup() const { return !isSingleWord(); }
+
+  /// Used to insert APInt objects, or objects that contain APInt objects, into
+  ///  FoldingSets.
+  void Profile(FoldingSetNodeID &id) const;
+
+  /// @}
+  /// \name Value Tests
+  /// @{
+
+  /// \brief Determine sign of this APInt.
+  ///
+  /// This tests the high bit of this APInt to determine if it is set.
+  ///
+  /// \returns true if this APInt is negative, false otherwise
+  bool isNegative() const { return (*this)[BitWidth - 1]; }
+
+  /// \brief Determine if this APInt Value is non-negative (>= 0)
+  ///
+  /// This tests the high bit of the APInt to determine if it is unset.
+  bool isNonNegative() const { return !isNegative(); }
+
+  /// \brief Determine if this APInt Value is positive.
+  ///
+  /// This tests if the value of this APInt is positive (> 0). Note
+  /// that 0 is not a positive value.
+  ///
+  /// \returns true if this APInt is positive.
+  bool isStrictlyPositive() const { return isNonNegative() && !!*this; }
+
+  /// \brief Determine if all bits are set
+  ///
+  /// This checks to see if the value has all bits of the APInt are set or not.
+  bool isAllOnesValue() const {
+    if (isSingleWord())
+      return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth);
+    return countPopulationSlowCase() == BitWidth;
+  }
+
+  /// \brief Determine if this is the largest unsigned value.
+  ///
+  /// This checks to see if the value of this APInt is the maximum unsigned
+  /// value for the APInt's bit width.
+  bool isMaxValue() const { return isAllOnesValue(); }
+
+  /// \brief Determine if this is the largest signed value.
+  ///
+  /// This checks to see if the value of this APInt is the maximum signed
+  /// value for the APInt's bit width.
+  bool isMaxSignedValue() const {
+    return !isNegative() && countPopulation() == BitWidth - 1;
+  }
+
+  /// \brief Determine if this is the smallest unsigned value.
+  ///
+  /// This checks to see if the value of this APInt is the minimum unsigned
+  /// value for the APInt's bit width.
+  bool isMinValue() const { return !*this; }
+
+  /// \brief Determine if this is the smallest signed value.
+  ///
+  /// This checks to see if the value of this APInt is the minimum signed
+  /// value for the APInt's bit width.
+  bool isMinSignedValue() const {
+    return isNegative() && isPowerOf2();
+  }
+
+  /// \brief Check if this APInt has an N-bits unsigned integer value.
+  bool isIntN(unsigned N) const {
+    assert(N && "N == 0 ???");
+    return getActiveBits() <= N;
+  }
+
+  /// \brief Check if this APInt has an N-bits signed integer value.
+  bool isSignedIntN(unsigned N) const {
+    assert(N && "N == 0 ???");
+    return getMinSignedBits() <= N;
+  }
+
+  /// \brief Check if this APInt's value is a power of two greater than zero.
+  ///
+  /// \returns true if the argument APInt value is a power of two > 0.
+  bool isPowerOf2() const {
+    if (isSingleWord())
+      return isPowerOf2_64(VAL);
+    return countPopulationSlowCase() == 1;
+  }
+
+  /// \brief Check if the APInt's value is returned by getSignBit.
+  ///
+  /// \returns true if this is the value returned by getSignBit.
+  bool isSignBit() const { return isMinSignedValue(); }
+
+  /// \brief Convert APInt to a boolean value.
+  ///
+  /// This converts the APInt to a boolean value as a test against zero.
+  bool getBoolValue() const { return !!*this; }
+
+  /// If this value is smaller than the specified limit, return it, otherwise
+  /// return the limit value.  This causes the value to saturate to the limit.
+  uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
+    return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit
+                                                            : getZExtValue();
+  }
+
+  /// \brief Check if the APInt consists of a repeated bit pattern.
+  ///
+  /// e.g. 0x01010101 satisfies isSplat(8).
+  /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit
+  /// width without remainder.
+  bool isSplat(unsigned SplatSizeInBits) const;
+
+  /// @}
+  /// \name Value Generators
+  /// @{
+
+  /// \brief Gets maximum unsigned value of APInt for specific bit width.
+  static APInt getMaxValue(unsigned numBits) {
+    return getAllOnesValue(numBits);
+  }
+
+  /// \brief Gets maximum signed value of APInt for a specific bit width.
+  static APInt getSignedMaxValue(unsigned numBits) {
+    APInt API = getAllOnesValue(numBits);
+    API.clearBit(numBits - 1);
+    return API;
+  }
+
+  /// \brief Gets minimum unsigned value of APInt for a specific bit width.
+  static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); }
+
+  /// \brief Gets minimum signed value of APInt for a specific bit width.
+  static APInt getSignedMinValue(unsigned numBits) {
+    APInt API(numBits, 0);
+    API.setBit(numBits - 1);
+    return API;
+  }
+
+  /// \brief Get the SignBit for a specific bit width.
+  ///
+  /// This is just a wrapper function of getSignedMinValue(), and it helps code
+  /// readability when we want to get a SignBit.
+  static APInt getSignBit(unsigned BitWidth) {
+    return getSignedMinValue(BitWidth);
+  }
+
+  /// \brief Get the all-ones value.
+  ///
+  /// \returns the all-ones value for an APInt of the specified bit-width.
+  static APInt getAllOnesValue(unsigned numBits) {
+    return APInt(numBits, UINT64_MAX, true);
+  }
+
+  /// \brief Get the '0' value.
+  ///
+  /// \returns the '0' value for an APInt of the specified bit-width.
+  static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); }
+
+  /// \brief Compute an APInt containing numBits highbits from this APInt.
+  ///
+  /// Get an APInt with the same BitWidth as this APInt, just zero mask
+  /// the low bits and right shift to the least significant bit.
+  ///
+  /// \returns the high "numBits" bits of this APInt.
+  APInt getHiBits(unsigned numBits) const;
+
+  /// \brief Compute an APInt containing numBits lowbits from this APInt.
+  ///
+  /// Get an APInt with the same BitWidth as this APInt, just zero mask
+  /// the high bits.
+  ///
+  /// \returns the low "numBits" bits of this APInt.
+  APInt getLoBits(unsigned numBits) const;
+
+  /// \brief Return an APInt with exactly one bit set in the result.
+  static APInt getOneBitSet(unsigned numBits, unsigned BitNo) {
+    APInt Res(numBits, 0);
+    Res.setBit(BitNo);
+    return Res;
+  }
+
+  /// \brief Get a value with a block of bits set.
+  ///
+  /// Constructs an APInt value that has a contiguous range of bits set. The
+  /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other
+  /// bits will be zero. For example, with parameters(32, 0, 16) you would get
+  /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For
+  /// example, with parameters (32, 28, 4), you would get 0xF000000F.
+  ///
+  /// \param numBits the intended bit width of the result
+  /// \param loBit the index of the lowest bit set.
+  /// \param hiBit the index of the highest bit set.
+  ///
+  /// \returns An APInt value with the requested bits set.
+  static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) {
+    assert(hiBit <= numBits && "hiBit out of range");
+    assert(loBit < numBits && "loBit out of range");
+    if (hiBit < loBit)
+      return getLowBitsSet(numBits, hiBit) |
+             getHighBitsSet(numBits, numBits - loBit);
+    return getLowBitsSet(numBits, hiBit - loBit).shl(loBit);
+  }
+
+  /// \brief Get a value with high bits set
+  ///
+  /// Constructs an APInt value that has the top hiBitsSet bits set.
+  ///
+  /// \param numBits the bitwidth of the result
+  /// \param hiBitsSet the number of high-order bits set in the result.
+  static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) {
+    assert(hiBitsSet <= numBits && "Too many bits to set!");
+    // Handle a degenerate case, to avoid shifting by word size
+    if (hiBitsSet == 0)
+      return APInt(numBits, 0);
+    unsigned shiftAmt = numBits - hiBitsSet;
+    // For small values, return quickly
+    if (numBits <= APINT_BITS_PER_WORD)
+      return APInt(numBits, ~0ULL << shiftAmt);
+    return getAllOnesValue(numBits).shl(shiftAmt);
+  }
+
+  /// \brief Get a value with low bits set
+  ///
+  /// Constructs an APInt value that has the bottom loBitsSet bits set.
+  ///
+  /// \param numBits the bitwidth of the result
+  /// \param loBitsSet the number of low-order bits set in the result.
+  static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) {
+    assert(loBitsSet <= numBits && "Too many bits to set!");
+    // Handle a degenerate case, to avoid shifting by word size
+    if (loBitsSet == 0)
+      return APInt(numBits, 0);
+    if (loBitsSet == APINT_BITS_PER_WORD)
+      return APInt(numBits, UINT64_MAX);
+    // For small values, return quickly.
+    if (loBitsSet <= APINT_BITS_PER_WORD)
+      return APInt(numBits, UINT64_MAX >> (APINT_BITS_PER_WORD - loBitsSet));
+    return getAllOnesValue(numBits).lshr(numBits - loBitsSet);
+  }
+
+  /// \brief Return a value containing V broadcasted over NewLen bits.
+  static APInt getSplat(unsigned NewLen, const APInt &V) {
+    assert(NewLen >= V.getBitWidth() && "Can't splat to smaller bit width!");
+
+    APInt Val = V.zextOrSelf(NewLen);
+    for (unsigned I = V.getBitWidth(); I < NewLen; I <<= 1)
+      Val |= Val << I;
+
+    return Val;
+  }
+
+  /// \brief Determine if two APInts have the same value, after zero-extending
+  /// one of them (if needed!) to ensure that the bit-widths match.
+  static bool isSameValue(const APInt &I1, const APInt &I2) {
+    if (I1.getBitWidth() == I2.getBitWidth())
+      return I1 == I2;
+
+    if (I1.getBitWidth() > I2.getBitWidth())
+      return I1 == I2.zext(I1.getBitWidth());
+
+    return I1.zext(I2.getBitWidth()) == I2;
+  }
+
+  /// \brief Overload to compute a hash_code for an APInt value.
+  friend hash_code hash_value(const APInt &Arg);
+
+  /// This function returns a pointer to the internal storage of the APInt.
+  /// This is useful for writing out the APInt in binary form without any
+  /// conversions.
+  const uint64_t *getRawData() const {
+    if (isSingleWord())
+      return &VAL;
+    return &pVal[0];
+  }
+
+  /// @}
+  /// \name Unary Operators
+  /// @{
+
+  /// \brief Postfix increment operator.
+  ///
+  /// \returns a new APInt value representing *this incremented by one
+  const APInt operator++(int) {
+    APInt API(*this);
+    ++(*this);
+    return API;
+  }
+
+  /// \brief Prefix increment operator.
+  ///
+  /// \returns *this incremented by one
+  APInt &operator++();
+
+  /// \brief Postfix decrement operator.
+  ///
+  /// \returns a new APInt representing *this decremented by one.
+  const APInt operator--(int) {
+    APInt API(*this);
+    --(*this);
+    return API;
+  }
+
+  /// \brief Prefix decrement operator.
+  ///
+  /// \returns *this decremented by one.
+  APInt &operator--();
+
+  /// \brief Unary bitwise complement operator.
+  ///
+  /// Performs a bitwise complement operation on this APInt.
+  ///
+  /// \returns an APInt that is the bitwise complement of *this
+  APInt operator~() const {
+    APInt Result(*this);
+    Result.flipAllBits();
+    return Result;
+  }
+
+  /// \brief Logical negation operator.
+  ///
+  /// Performs logical negation operation on this APInt.
+  ///
+  /// \returns true if *this is zero, false otherwise.
+  bool operator!() const {
+    if (isSingleWord())
+      return !VAL;
+
+    for (unsigned i = 0; i != getNumWords(); ++i)
+      if (pVal[i])
+        return false;
+    return true;
+  }
+
+  /// @}
+  /// \name Assignment Operators
+  /// @{
+
+  /// \brief Copy assignment operator.
+  ///
+  /// \returns *this after assignment of RHS.
+  APInt &operator=(const APInt &RHS) {
+    // If the bitwidths are the same, we can avoid mucking with memory
+    if (isSingleWord() && RHS.isSingleWord()) {
+      VAL = RHS.VAL;
+      BitWidth = RHS.BitWidth;
+      return clearUnusedBits();
+    }
+
+    return AssignSlowCase(RHS);
+  }
+
+  /// @brief Move assignment operator.
+  APInt &operator=(APInt &&that) {
+    if (!isSingleWord()) {
+      // The MSVC STL shipped in 2013 requires that self move assignment be a
+      // no-op.  Otherwise algorithms like stable_sort will produce answers
+      // where half of the output is left in a moved-from state.
+      if (this == &that)
+        return *this;
+      delete[] pVal;
+    }
+
+    // Use memcpy so that type based alias analysis sees both VAL and pVal
+    // as modified.
+    memcpy(&VAL, &that.VAL, sizeof(uint64_t));
+
+    // If 'this == &that', avoid zeroing our own bitwidth by storing to 'that'
+    // first.
+    unsigned ThatBitWidth = that.BitWidth;
+    that.BitWidth = 0;
+    BitWidth = ThatBitWidth;
+
+    return *this;
+  }
+
+  /// \brief Assignment operator.
+  ///
+  /// The RHS value is assigned to *this. If the significant bits in RHS exceed
+  /// the bit width, the excess bits are truncated. If the bit width is larger
+  /// than 64, the value is zero filled in the unspecified high order bits.
+  ///
+  /// \returns *this after assignment of RHS value.
+  APInt &operator=(uint64_t RHS);
+
+  /// \brief Bitwise AND assignment operator.
+  ///
+  /// Performs a bitwise AND operation on this APInt and RHS. The result is
+  /// assigned to *this.
+  ///
+  /// \returns *this after ANDing with RHS.
+  APInt &operator&=(const APInt &RHS);
+
+  /// \brief Bitwise OR assignment operator.
+  ///
+  /// Performs a bitwise OR operation on this APInt and RHS. The result is
+  /// assigned *this;
+  ///
+  /// \returns *this after ORing with RHS.
+  APInt &operator|=(const APInt &RHS);
+
+  /// \brief Bitwise OR assignment operator.
+  ///
+  /// Performs a bitwise OR operation on this APInt and RHS. RHS is
+  /// logically zero-extended or truncated to match the bit-width of
+  /// the LHS.
+  APInt &operator|=(uint64_t RHS) {
+    if (isSingleWord()) {
+      VAL |= RHS;
+      clearUnusedBits();
+    } else {
+      pVal[0] |= RHS;
+    }
+    return *this;
+  }
+
+  /// \brief Bitwise XOR assignment operator.
+  ///
+  /// Performs a bitwise XOR operation on this APInt and RHS. The result is
+  /// assigned to *this.
+  ///
+  /// \returns *this after XORing with RHS.
+  APInt &operator^=(const APInt &RHS);
+
+  /// \brief Multiplication assignment operator.
+  ///
+  /// Multiplies this APInt by RHS and assigns the result to *this.
+  ///
+  /// \returns *this
+  APInt &operator*=(const APInt &RHS);
+
+  /// \brief Addition assignment operator.
+  ///
+  /// Adds RHS to *this and assigns the result to *this.
+  ///
+  /// \returns *this
+  APInt &operator+=(const APInt &RHS);
+  APInt &operator+=(uint64_t RHS);
+
+  /// \brief Subtraction assignment operator.
+  ///
+  /// Subtracts RHS from *this and assigns the result to *this.
+  ///
+  /// \returns *this
+  APInt &operator-=(const APInt &RHS);
+  APInt &operator-=(uint64_t RHS);
+
+  /// \brief Left-shift assignment function.
+  ///
+  /// Shifts *this left by shiftAmt and assigns the result to *this.
+  ///
+  /// \returns *this after shifting left by shiftAmt
+  APInt &operator<<=(unsigned shiftAmt) {
+    *this = shl(shiftAmt);
+    return *this;
+  }
+
+  /// @}
+  /// \name Binary Operators
+  /// @{
+
+  /// \brief Bitwise AND operator.
+  ///
+  /// Performs a bitwise AND operation on *this and RHS.
+  ///
+  /// \returns An APInt value representing the bitwise AND of *this and RHS.
+  APInt operator&(const APInt &RHS) const {
+    assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+    if (isSingleWord())
+      return APInt(getBitWidth(), VAL & RHS.VAL);
+    return AndSlowCase(RHS);
+  }
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APInt &RHS) const {
+    return this->operator&(RHS);
+  }
+
+  /// \brief Bitwise OR operator.
+  ///
+  /// Performs a bitwise OR operation on *this and RHS.
+  ///
+  /// \returns An APInt value representing the bitwise OR of *this and RHS.
+  APInt operator|(const APInt &RHS) const {
+    assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+    if (isSingleWord())
+      return APInt(getBitWidth(), VAL | RHS.VAL);
+    return OrSlowCase(RHS);
+  }
+
+  /// \brief Bitwise OR function.
+  ///
+  /// Performs a bitwise or on *this and RHS. This is implemented by simply
+  /// calling operator|.
+  ///
+  /// \returns An APInt value representing the bitwise OR of *this and RHS.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APInt &RHS) const {
+    return this->operator|(RHS);
+  }
+
+  /// \brief Bitwise XOR operator.
+  ///
+  /// Performs a bitwise XOR operation on *this and RHS.
+  ///
+  /// \returns An APInt value representing the bitwise XOR of *this and RHS.
+  APInt operator^(const APInt &RHS) const {
+    assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+    if (isSingleWord())
+      return APInt(BitWidth, VAL ^ RHS.VAL);
+    return XorSlowCase(RHS);
+  }
+
+  /// \brief Bitwise XOR function.
+  ///
+  /// Performs a bitwise XOR operation on *this and RHS. This is implemented
+  /// through the usage of operator^.
+  ///
+  /// \returns An APInt value representing the bitwise XOR of *this and RHS.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APInt &RHS) const {
+    return this->operator^(RHS);
+  }
+
+  /// \brief Multiplication operator.
+  ///
+  /// Multiplies this APInt by RHS and returns the result.
+  APInt operator*(const APInt &RHS) const;
+
+  /// \brief Left logical shift operator.
+  ///
+  /// Shifts this APInt left by \p Bits and returns the result.
+  APInt operator<<(unsigned Bits) const { return shl(Bits); }
+
+  /// \brief Left logical shift operator.
+  ///
+  /// Shifts this APInt left by \p Bits and returns the result.
+  APInt operator<<(const APInt &Bits) const { return shl(Bits); }
+
+  /// \brief Arithmetic right-shift function.
+  ///
+  /// Arithmetic right-shift this APInt by shiftAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(unsigned shiftAmt) const;
+
+  /// \brief Logical right-shift function.
+  ///
+  /// Logical right-shift this APInt by shiftAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const;
+
+  /// \brief Left-shift function.
+  ///
+  /// Left-shift this APInt by shiftAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const {
+    assert(shiftAmt <= BitWidth && "Invalid shift amount");
+    if (isSingleWord()) {
+      if (shiftAmt >= BitWidth)
+        return APInt(BitWidth, 0); // avoid undefined shift results
+      return APInt(BitWidth, VAL << shiftAmt);
+    }
+    return shlSlowCase(shiftAmt);
+  }
+
+  /// \brief Rotate left by rotateAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(unsigned rotateAmt) const;
+
+  /// \brief Rotate right by rotateAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(unsigned rotateAmt) const;
+
+  /// \brief Arithmetic right-shift function.
+  ///
+  /// Arithmetic right-shift this APInt by shiftAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(const APInt &shiftAmt) const;
+
+  /// \brief Logical right-shift function.
+  ///
+  /// Logical right-shift this APInt by shiftAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(const APInt &shiftAmt) const;
+
+  /// \brief Left-shift function.
+  ///
+  /// Left-shift this APInt by shiftAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(const APInt &shiftAmt) const;
+
+  /// \brief Rotate left by rotateAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(const APInt &rotateAmt) const;
+
+  /// \brief Rotate right by rotateAmt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(const APInt &rotateAmt) const;
+
+  /// \brief Unsigned division operation.
+  ///
+  /// Perform an unsigned divide operation on this APInt by RHS. Both this and
+  /// RHS are treated as unsigned quantities for purposes of this division.
+  ///
+  /// \returns a new APInt value containing the division result
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT udiv(const APInt &RHS) const;
+
+  /// \brief Signed division function for APInt.
+  ///
+  /// Signed divide this APInt by APInt RHS.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const;
+
+  /// \brief Unsigned remainder operation.
+  ///
+  /// Perform an unsigned remainder operation on this APInt with RHS being the
+  /// divisor. Both this and RHS are treated as unsigned quantities for purposes
+  /// of this operation. Note that this is a true remainder operation and not a
+  /// modulo operation because the sign follows the sign of the dividend which
+  /// is *this.
+  ///
+  /// \returns a new APInt value containing the remainder result
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT urem(const APInt &RHS) const;
+
+  /// \brief Function for signed remainder operation.
+  ///
+  /// Signed remainder operation on APInt.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT srem(const APInt &RHS) const;
+
+  /// \brief Dual division/remainder interface.
+  ///
+  /// Sometimes it is convenient to divide two APInt values and obtain both the
+  /// quotient and remainder. This function does both operations in the same
+  /// computation making it a little more efficient. The pair of input arguments
+  /// may overlap with the pair of output arguments. It is safe to call
+  /// udivrem(X, Y, X, Y), for example.
+  static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient,
+                      APInt &Remainder);
+
+  static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient,
+                      APInt &Remainder);
+
+  // Operations that return overflow indicators.
+  APInt sadd_ov(const APInt &RHS, bool &Overflow) const;
+  APInt uadd_ov(const APInt &RHS, bool &Overflow) const;
+  APInt ssub_ov(const APInt &RHS, bool &Overflow) const;
+  APInt usub_ov(const APInt &RHS, bool &Overflow) const;
+  APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
+  APInt smul_ov(const APInt &RHS, bool &Overflow) const;
+  APInt umul_ov(const APInt &RHS, bool &Overflow) const;
+  APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
+  APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
+
+  /// \brief Array-indexing support.
+  ///
+  /// \returns the bit value at bitPosition
+  bool operator[](unsigned bitPosition) const {
+    assert(bitPosition < getBitWidth() && "Bit position out of bounds!");
+    return (maskBit(bitPosition) &
+            (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) !=
+           0;
+  }
+
+  /// @}
+  /// \name Comparison Operators
+  /// @{
+
+  /// \brief Equality operator.
+  ///
+  /// Compares this APInt with RHS for the validity of the equality
+  /// relationship.
+  bool operator==(const APInt &RHS) const {
+    assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths");
+    if (isSingleWord())
+      return VAL == RHS.VAL;
+    return EqualSlowCase(RHS);
+  }
+
+  /// \brief Equality operator.
+  ///
+  /// Compares this APInt with a uint64_t for the validity of the equality
+  /// relationship.
+  ///
+  /// \returns true if *this == Val
+  bool operator==(uint64_t Val) const {
+    if (isSingleWord())
+      return VAL == Val;
+    return EqualSlowCase(Val);
+  }
+
+  /// \brief Equality comparison.
+  ///
+  /// Compares this APInt with RHS for the validity of the equality
+  /// relationship.
+  ///
+  /// \returns true if *this == Val
+  bool eq(const APInt &RHS) const { return (*this) == RHS; }
+
+  /// \brief Inequality operator.
+  ///
+  /// Compares this APInt with RHS for the validity of the inequality
+  /// relationship.
+  ///
+  /// \returns true if *this != Val
+  bool operator!=(const APInt &RHS) const { return !((*this) == RHS); }
+
+  /// \brief Inequality operator.
+  ///
+  /// Compares this APInt with a uint64_t for the validity of the inequality
+  /// relationship.
+  ///
+  /// \returns true if *this != Val
+  bool operator!=(uint64_t Val) const { return !((*this) == Val); }
+
+  /// \brief Inequality comparison
+  ///
+  /// Compares this APInt with RHS for the validity of the inequality
+  /// relationship.
+  ///
+  /// \returns true if *this != Val
+  bool ne(const APInt &RHS) const { return !((*this) == RHS); }
+
+  /// \brief Unsigned less than comparison
+  ///
+  /// Regards both *this and RHS as unsigned quantities and compares them for
+  /// the validity of the less-than relationship.
+  ///
+  /// \returns true if *this < RHS when both are considered unsigned.
+  bool ult(const APInt &RHS) const;
+
+  /// \brief Unsigned less than comparison
+  ///
+  /// Regards both *this as an unsigned quantity and compares it with RHS for
+  /// the validity of the less-than relationship.
+  ///
+  /// \returns true if *this < RHS when considered unsigned.
+  bool ult(uint64_t RHS) const {
+    return getActiveBits() > 64 ? false : getZExtValue() < RHS;
+  }
+
+  /// \brief Signed less than comparison
+  ///
+  /// Regards both *this and RHS as signed quantities and compares them for
+  /// validity of the less-than relationship.
+  ///
+  /// \returns true if *this < RHS when both are considered signed.
+  bool slt(const APInt &RHS) const;
+
+  /// \brief Signed less than comparison
+  ///
+  /// Regards both *this as a signed quantity and compares it with RHS for
+  /// the validity of the less-than relationship.
+  ///
+  /// \returns true if *this < RHS when considered signed.
+  bool slt(int64_t RHS) const {
+    return getMinSignedBits() > 64 ? isNegative() : getSExtValue() < RHS;
+  }
+
+  /// \brief Unsigned less or equal comparison
+  ///
+  /// Regards both *this and RHS as unsigned quantities and compares them for
+  /// validity of the less-or-equal relationship.
+  ///
+  /// \returns true if *this <= RHS when both are considered unsigned.
+  bool ule(const APInt &RHS) const { return ult(RHS) || eq(RHS); }
+
+  /// \brief Unsigned less or equal comparison
+  ///
+  /// Regards both *this as an unsigned quantity and compares it with RHS for
+  /// the validity of the less-or-equal relationship.
+  ///
+  /// \returns true if *this <= RHS when considered unsigned.
+  bool ule(uint64_t RHS) const { return !ugt(RHS); }
+
+  /// \brief Signed less or equal comparison
+  ///
+  /// Regards both *this and RHS as signed quantities and compares them for
+  /// validity of the less-or-equal relationship.
+  ///
+  /// \returns true if *this <= RHS when both are considered signed.
+  bool sle(const APInt &RHS) const { return slt(RHS) || eq(RHS); }
+
+  /// \brief Signed less or equal comparison
+  ///
+  /// Regards both *this as a signed quantity and compares it with RHS for the
+  /// validity of the less-or-equal relationship.
+  ///
+  /// \returns true if *this <= RHS when considered signed.
+  bool sle(uint64_t RHS) const { return !sgt(RHS); }
+
+  /// \brief Unsigned greather than comparison
+  ///
+  /// Regards both *this and RHS as unsigned quantities and compares them for
+  /// the validity of the greater-than relationship.
+  ///
+  /// \returns true if *this > RHS when both are considered unsigned.
+  bool ugt(const APInt &RHS) const { return !ult(RHS) && !eq(RHS); }
+
+  /// \brief Unsigned greater than comparison
+  ///
+  /// Regards both *this as an unsigned quantity and compares it with RHS for
+  /// the validity of the greater-than relationship.
+  ///
+  /// \returns true if *this > RHS when considered unsigned.
+  bool ugt(uint64_t RHS) const {
+    return getActiveBits() > 64 ? true : getZExtValue() > RHS;
+  }
+
+  /// \brief Signed greather than comparison
+  ///
+  /// Regards both *this and RHS as signed quantities and compares them for the
+  /// validity of the greater-than relationship.
+  ///
+  /// \returns true if *this > RHS when both are considered signed.
+  bool sgt(const APInt &RHS) const { return !slt(RHS) && !eq(RHS); }
+
+  /// \brief Signed greater than comparison
+  ///
+  /// Regards both *this as a signed quantity and compares it with RHS for
+  /// the validity of the greater-than relationship.
+  ///
+  /// \returns true if *this > RHS when considered signed.
+  bool sgt(int64_t RHS) const {
+    return getMinSignedBits() > 64 ? !isNegative() : getSExtValue() > RHS;
+  }
+
+  /// \brief Unsigned greater or equal comparison
+  ///
+  /// Regards both *this and RHS as unsigned quantities and compares them for
+  /// validity of the greater-or-equal relationship.
+  ///
+  /// \returns true if *this >= RHS when both are considered unsigned.
+  bool uge(const APInt &RHS) const { return !ult(RHS); }
+
+  /// \brief Unsigned greater or equal comparison
+  ///
+  /// Regards both *this as an unsigned quantity and compares it with RHS for
+  /// the validity of the greater-or-equal relationship.
+  ///
+  /// \returns true if *this >= RHS when considered unsigned.
+  bool uge(uint64_t RHS) const { return !ult(RHS); }
+
+  /// \brief Signed greather or equal comparison
+  ///
+  /// Regards both *this and RHS as signed quantities and compares them for
+  /// validity of the greater-or-equal relationship.
+  ///
+  /// \returns true if *this >= RHS when both are considered signed.
+  bool sge(const APInt &RHS) const { return !slt(RHS); }
+
+  /// \brief Signed greater or equal comparison
+  ///
+  /// Regards both *this as a signed quantity and compares it with RHS for
+  /// the validity of the greater-or-equal relationship.
+  ///
+  /// \returns true if *this >= RHS when considered signed.
+  bool sge(int64_t RHS) const { return !slt(RHS); }
+
+  /// This operation tests if there are any pairs of corresponding bits
+  /// between this APInt and RHS that are both set.
+  bool intersects(const APInt &RHS) const { return (*this & RHS) != 0; }
+
+  /// @}
+  /// \name Resizing Operators
+  /// @{
+
+  /// \brief Truncate to new width.
+  ///
+  /// Truncate the APInt to a specified width. It is an error to specify a width
+  /// that is greater than or equal to the current width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const;
+
+  /// \brief Sign extend to a new width.
+  ///
+  /// This operation sign extends the APInt to a new width. If the high order
+  /// bit is set, the fill on the left will be done with 1 bits, otherwise zero.
+  /// It is an error to specify a width that is less than or equal to the
+  /// current width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT sext(unsigned width) const;
+
+  /// \brief Zero extend to a new width.
+  ///
+  /// This operation zero extends the APInt to a new width. The high order bits
+  /// are filled with 0 bits.  It is an error to specify a width that is less
+  /// than or equal to the current width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const;
+
+  /// \brief Sign extend or truncate to width
+  ///
+  /// Make this APInt have the bit width given by \p width. The value is sign
+  /// extended, truncated, or left alone to make it that width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const;
+
+  /// \brief Zero extend or truncate to width
+  ///
+  /// Make this APInt have the bit width given by \p width. The value is zero
+  /// extended, truncated, or left alone to make it that width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrTrunc(unsigned width) const;
+
+  /// \brief Sign extend or truncate to width
+  ///
+  /// Make this APInt have the bit width given by \p width. The value is sign
+  /// extended, or left alone to make it that width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrSelf(unsigned width) const;
+
+  /// \brief Zero extend or truncate to width
+  ///
+  /// Make this APInt have the bit width given by \p width. The value is zero
+  /// extended, or left alone to make it that width.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrSelf(unsigned width) const;
+
+  /// @}
+  /// \name Bit Manipulation Operators
+  /// @{
+
+  /// \brief Set every bit to 1.
+  void setAllBits() {
+    if (isSingleWord())
+      VAL = UINT64_MAX;
+    else {
+      // Set all the bits in all the words.
+      for (unsigned i = 0; i < getNumWords(); ++i)
+        pVal[i] = UINT64_MAX;
+    }
+    // Clear the unused ones
+    clearUnusedBits();
+  }
+
+  /// \brief Set a given bit to 1.
+  ///
+  /// Set the given bit to 1 whose position is given as "bitPosition".
+  void setBit(unsigned bitPosition);
+
+  /// \brief Set every bit to 0.
+  void clearAllBits() {
+    if (isSingleWord())
+      VAL = 0;
+    else
+      memset(pVal, 0, getNumWords() * APINT_WORD_SIZE);
+  }
+
+  /// \brief Set a given bit to 0.
+  ///
+  /// Set the given bit to 0 whose position is given as "bitPosition".
+  void clearBit(unsigned bitPosition);
+
+  /// \brief Toggle every bit to its opposite value.
+  void flipAllBits() {
+    if (isSingleWord())
+      VAL ^= UINT64_MAX;
+    else {
+      for (unsigned i = 0; i < getNumWords(); ++i)
+        pVal[i] ^= UINT64_MAX;
+    }
+    clearUnusedBits();
+  }
+
+  /// \brief Toggles a given bit to its opposite value.
+  ///
+  /// Toggle a given bit to its opposite value whose position is given
+  /// as "bitPosition".
+  void flipBit(unsigned bitPosition);
+
+  /// @}
+  /// \name Value Characterization Functions
+  /// @{
+
+  /// \brief Return the number of bits in the APInt.
+  unsigned getBitWidth() const { return BitWidth; }
+
+  /// \brief Get the number of words.
+  ///
+  /// Here one word's bitwidth equals to that of uint64_t.
+  ///
+  /// \returns the number of words to hold the integer value of this APInt.
+  unsigned getNumWords() const { return getNumWords(BitWidth); }
+
+  /// \brief Get the number of words.
+  ///
+  /// *NOTE* Here one word's bitwidth equals to that of uint64_t.
+  ///
+  /// \returns the number of words to hold the integer value with a given bit
+  /// width.
+  static unsigned getNumWords(unsigned BitWidth) {
+    return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
+  }
+
+  /// \brief Compute the number of active bits in the value
+  ///
+  /// This function returns the number of active bits which is defined as the
+  /// bit width minus the number of leading zeros. This is used in several
+  /// computations to see how "wide" the value is.
+  unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); }
+
+  /// \brief Compute the number of active words in the value of this APInt.
+  ///
+  /// This is used in conjunction with getActiveData to extract the raw value of
+  /// the APInt.
+  unsigned getActiveWords() const {
+    unsigned numActiveBits = getActiveBits();
+    return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1;
+  }
+
+  /// \brief Get the minimum bit size for this signed APInt
+  ///
+  /// Computes the minimum bit width for this APInt while considering it to be a
+  /// signed (and probably negative) value. If the value is not negative, this
+  /// function returns the same value as getActiveBits()+1. Otherwise, it
+  /// returns the smallest bit width that will retain the negative value. For
+  /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so
+  /// for -1, this function will always return 1.
+  unsigned getMinSignedBits() const {
+    if (isNegative())
+      return BitWidth - countLeadingOnes() + 1;
+    return getActiveBits() + 1;
+  }
+
+  /// \brief Get zero extended value
+  ///
+  /// This method attempts to return the value of this APInt as a zero extended
+  /// uint64_t. The bitwidth must be <= 64 or the value must fit within a
+  /// uint64_t. Otherwise an assertion will result.
+  uint64_t getZExtValue() const {
+    if (isSingleWord())
+      return VAL;
+    assert(getActiveBits() <= 64 && "Too many bits for uint64_t");
+    return pVal[0];
+  }
+
+  /// \brief Get sign extended value
+  ///
+  /// This method attempts to return the value of this APInt as a sign extended
+  /// int64_t. The bit width must be <= 64 or the value must fit within an
+  /// int64_t. Otherwise an assertion will result.
+  int64_t getSExtValue() const {
+    if (isSingleWord())
+      return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >>
+             (APINT_BITS_PER_WORD - BitWidth);
+    assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
+    return int64_t(pVal[0]);
+  }
+
+  /// \brief Get bits required for string value.
+  ///
+  /// This method determines how many bits are required to hold the APInt
+  /// equivalent of the string given by \p str.
+  static unsigned getBitsNeeded(StringRef str, uint8_t radix);
+
+  /// \brief The APInt version of the countLeadingZeros functions in
+  ///   MathExtras.h.
+  ///
+  /// It counts the number of zeros from the most significant bit to the first
+  /// one bit.
+  ///
+  /// \returns BitWidth if the value is zero, otherwise returns the number of
+  ///   zeros from the most significant bit to the first one bits.
+  unsigned countLeadingZeros() const {
+    if (isSingleWord()) {
+      unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth;
+      return llvm::countLeadingZeros(VAL) - unusedBits;
+    }
+    return countLeadingZerosSlowCase();
+  }
+
+  /// \brief Count the number of leading one bits.
+  ///
+  /// This function is an APInt version of the countLeadingOnes
+  /// functions in MathExtras.h. It counts the number of ones from the most
+  /// significant bit to the first zero bit.
+  ///
+  /// \returns 0 if the high order bit is not set, otherwise returns the number
+  /// of 1 bits from the most significant to the least
+  unsigned countLeadingOnes() const;
+
+  /// Computes the number of leading bits of this APInt that are equal to its
+  /// sign bit.
+  unsigned getNumSignBits() const {
+    return isNegative() ? countLeadingOnes() : countLeadingZeros();
+  }
+
+  /// \brief Count the number of trailing zero bits.
+  ///
+  /// This function is an APInt version of the countTrailingZeros
+  /// functions in MathExtras.h. It counts the number of zeros from the least
+  /// significant bit to the first set bit.
+  ///
+  /// \returns BitWidth if the value is zero, otherwise returns the number of
+  /// zeros from the least significant bit to the first one bit.
+  unsigned countTrailingZeros() const;
+
+  /// \brief Count the number of trailing one bits.
+  ///
+  /// This function is an APInt version of the countTrailingOnes
+  /// functions in MathExtras.h. It counts the number of ones from the least
+  /// significant bit to the first zero bit.
+  ///
+  /// \returns BitWidth if the value is all ones, otherwise returns the number
+  /// of ones from the least significant bit to the first zero bit.
+  unsigned countTrailingOnes() const {
+    if (isSingleWord())
+      return llvm::countTrailingOnes(VAL);
+    return countTrailingOnesSlowCase();
+  }
+
+  /// \brief Count the number of bits set.
+  ///
+  /// This function is an APInt version of the countPopulation functions
+  /// in MathExtras.h. It counts the number of 1 bits in the APInt value.
+  ///
+  /// \returns 0 if the value is zero, otherwise returns the number of set bits.
+  unsigned countPopulation() const {
+    if (isSingleWord())
+      return llvm::countPopulation(VAL);
+    return countPopulationSlowCase();
+  }
+
+  /// @}
+  /// \name Conversion Functions
+  /// @{
+  void print(raw_ostream &OS, bool isSigned) const;
+
+  /// Converts an APInt to a string and append it to Str.  Str is commonly a
+  /// SmallString.
+  void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed,
+                bool formatAsCLiteral = false) const;
+
+  /// Considers the APInt to be unsigned and converts it into a string in the
+  /// radix given. The radix can be 2, 8, 10 16, or 36.
+  void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
+    toString(Str, Radix, false, false);
+  }
+
+  /// Considers the APInt to be signed and converts it into a string in the
+  /// radix given. The radix can be 2, 8, 10, 16, or 36.
+  void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
+    toString(Str, Radix, true, false);
+  }
+
+  /// \brief Return the APInt as a std::string.
+  ///
+  /// Note that this is an inefficient method.  It is better to pass in a
+  /// SmallVector/SmallString to the methods above to avoid thrashing the heap
+  /// for the string.
+  std::string toString(unsigned Radix, bool Signed) const;
+
+  /// \returns a byte-swapped representation of this APInt Value.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const;
+
+  /// \returns the value with the bit representation reversed of this APInt
+  /// Value.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT reverseBits() const;
+
+  /// \brief Converts this APInt to a double value.
+  double roundToDouble(bool isSigned) const;
+
+  /// \brief Converts this unsigned APInt to a double value.
+  double roundToDouble() const { return roundToDouble(false); }
+
+  /// \brief Converts this signed APInt to a double value.
+  double signedRoundToDouble() const { return roundToDouble(true); }
+
+  /// \brief Converts APInt bits to a double
+  ///
+  /// The conversion does not do a translation from integer to double, it just
+  /// re-interprets the bits as a double. Note that it is valid to do this on
+  /// any bit width. Exactly 64 bits will be translated.
+  double bitsToDouble() const {
+    union {
+      uint64_t I;
+      double D;
+    } T;
+    T.I = (isSingleWord() ? VAL : pVal[0]);
+    return T.D;
+  }
+
+  /// \brief Converts APInt bits to a double
+  ///
+  /// The conversion does not do a translation from integer to float, it just
+  /// re-interprets the bits as a float. Note that it is valid to do this on
+  /// any bit width. Exactly 32 bits will be translated.
+  float bitsToFloat() const {
+    union {
+      unsigned I;
+      float F;
+    } T;
+    T.I = unsigned((isSingleWord() ? VAL : pVal[0]));
+    return T.F;
+  }
+
+  /// \brief Converts a double to APInt bits.
+  ///
+  /// The conversion does not do a translation from double to integer, it just
+  /// re-interprets the bits of the double.
+  static APInt LLVM_ATTRIBUTE_UNUSED_RESULT doubleToBits(double V) {
+    union {
+      uint64_t I;
+      double D;
+    } T;
+    T.D = V;
+    return APInt(sizeof T * CHAR_BIT, T.I);
+  }
+
+  /// \brief Converts a float to APInt bits.
+  ///
+  /// The conversion does not do a translation from float to integer, it just
+  /// re-interprets the bits of the float.
+  static APInt LLVM_ATTRIBUTE_UNUSED_RESULT floatToBits(float V) {
+    union {
+      unsigned I;
+      float F;
+    } T;
+    T.F = V;
+    return APInt(sizeof T * CHAR_BIT, T.I);
+  }
+
+  /// @}
+  /// \name Mathematics Operations
+  /// @{
+
+  /// \returns the floor log base 2 of this APInt.
+  unsigned logBase2() const { return BitWidth - 1 - countLeadingZeros(); }
+
+  /// \returns the ceil log base 2 of this APInt.
+  unsigned ceilLogBase2() const {
+    APInt temp(*this);
+    --temp;
+    return BitWidth - temp.countLeadingZeros();
+  }
+
+  /// \returns the nearest log base 2 of this APInt. Ties round up.
+  ///
+  /// NOTE: When we have a BitWidth of 1, we define:
+  ///
+  ///   log2(0) = UINT32_MAX
+  ///   log2(1) = 0
+  ///
+  /// to get around any mathematical concerns resulting from
+  /// referencing 2 in a space where 2 does no exist.
+  unsigned nearestLogBase2() const {
+    // Special case when we have a bitwidth of 1. If VAL is 1, then we
+    // get 0. If VAL is 0, we get UINT64_MAX which gets truncated to
+    // UINT32_MAX.
+    if (BitWidth == 1)
+      return VAL - 1;
+
+    // Handle the zero case.
+    if (!getBoolValue())
+      return UINT32_MAX;
+
+    // The non-zero case is handled by computing:
+    //
+    //   nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1].
+    //
+    // where x[i] is referring to the value of the ith bit of x.
+    unsigned lg = logBase2();
+    return lg + unsigned((*this)[lg - 1]);
+  }
+
+  /// \returns the log base 2 of this APInt if its an exact power of two, -1
+  /// otherwise
+  int32_t exactLogBase2() const {
+    if (!isPowerOf2())
+      return -1;
+    return logBase2();
+  }
+
+  /// \brief Compute the square root
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT sqrt() const;
+
+  /// \brief Get the absolute value;
+  ///
+  /// If *this is < 0 then return -(*this), otherwise *this;
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT abs() const {
+    if (isNegative())
+      return -(*this);
+    return *this;
+  }
+
+  /// \returns the multiplicative inverse for a given modulo.
+  APInt multiplicativeInverse(const APInt &modulo) const;
+
+  /// @}
+  /// \name Support for division by constant
+  /// @{
+
+  /// Calculate the magic number for signed division by a constant.
+  struct ms;
+  ms magic() const;
+
+  /// Calculate the magic number for unsigned division by a constant.
+  struct mu;
+  mu magicu(unsigned LeadingZeros = 0) const;
+
+  /// @}
+  /// \name Building-block Operations for APInt and APFloat
+  /// @{
+
+  // These building block operations operate on a representation of arbitrary
+  // precision, two's-complement, bignum integer values. They should be
+  // sufficient to implement APInt and APFloat bignum requirements. Inputs are
+  // generally a pointer to the base of an array of integer parts, representing
+  // an unsigned bignum, and a count of how many parts there are.
+
+  /// Sets the least significant part of a bignum to the input value, and zeroes
+  /// out higher parts.
+  static void tcSet(integerPart *, integerPart, unsigned int);
+
+  /// Assign one bignum to another.
+  static void tcAssign(integerPart *, const integerPart *, unsigned int);
+
+  /// Returns true if a bignum is zero, false otherwise.
+  static bool tcIsZero(const integerPart *, unsigned int);
+
+  /// Extract the given bit of a bignum; returns 0 or 1.  Zero-based.
+  static int tcExtractBit(const integerPart *, unsigned int bit);
+
+  /// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to
+  /// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least
+  /// significant bit of DST.  All high bits above srcBITS in DST are
+  /// zero-filled.
+  static void tcExtract(integerPart *, unsigned int dstCount,
+                        const integerPart *, unsigned int srcBits,
+                        unsigned int srcLSB);
+
+  /// Set the given bit of a bignum.  Zero-based.
+  static void tcSetBit(integerPart *, unsigned int bit);
+
+  /// Clear the given bit of a bignum.  Zero-based.
+  static void tcClearBit(integerPart *, unsigned int bit);
+
+  /// Returns the bit number of the least or most significant set bit of a
+  /// number.  If the input number has no bits set -1U is returned.
+  static unsigned int tcLSB(const integerPart *, unsigned int);
+  static unsigned int tcMSB(const integerPart *parts, unsigned int n);
+
+  /// Negate a bignum in-place.
+  static void tcNegate(integerPart *, unsigned int);
+
+  /// DST += RHS + CARRY where CARRY is zero or one.  Returns the carry flag.
+  static integerPart tcAdd(integerPart *, const integerPart *,
+                           integerPart carry, unsigned);
+
+  /// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag.
+  static integerPart tcSubtract(integerPart *, const integerPart *,
+                                integerPart carry, unsigned);
+
+  /// DST += SRC * MULTIPLIER + PART   if add is true
+  /// DST  = SRC * MULTIPLIER + PART   if add is false
+  ///
+  /// Requires 0 <= DSTPARTS <= SRCPARTS + 1.  If DST overlaps SRC they must
+  /// start at the same point, i.e. DST == SRC.
+  ///
+  /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is returned.
+  /// Otherwise DST is filled with the least significant DSTPARTS parts of the
+  /// result, and if all of the omitted higher parts were zero return zero,
+  /// otherwise overflow occurred and return one.
+  static int tcMultiplyPart(integerPart *dst, const integerPart *src,
+                            integerPart multiplier, integerPart carry,
+                            unsigned int srcParts, unsigned int dstParts,
+                            bool add);
+
+  /// DST = LHS * RHS, where DST has the same width as the operands and is
+  /// filled with the least significant parts of the result.  Returns one if
+  /// overflow occurred, otherwise zero.  DST must be disjoint from both
+  /// operands.
+  static int tcMultiply(integerPart *, const integerPart *, const integerPart *,
+                        unsigned);
+
+  /// DST = LHS * RHS, where DST has width the sum of the widths of the
+  /// operands.  No overflow occurs.  DST must be disjoint from both
+  /// operands. Returns the number of parts required to hold the result.
+  static unsigned int tcFullMultiply(integerPart *, const integerPart *,
+                                     const integerPart *, unsigned, unsigned);
+
+  /// If RHS is zero LHS and REMAINDER are left unchanged, return one.
+  /// Otherwise set LHS to LHS / RHS with the fractional part discarded, set
+  /// REMAINDER to the remainder, return zero.  i.e.
+  ///
+  ///  OLD_LHS = RHS * LHS + REMAINDER
+  ///
+  /// SCRATCH is a bignum of the same size as the operands and result for use by
+  /// the routine; its contents need not be initialized and are destroyed.  LHS,
+  /// REMAINDER and SCRATCH must be distinct.
+  static int tcDivide(integerPart *lhs, const integerPart *rhs,
+                      integerPart *remainder, integerPart *scratch,
+                      unsigned int parts);
+
+  /// Shift a bignum left COUNT bits.  Shifted in bits are zero.  There are no
+  /// restrictions on COUNT.
+  static void tcShiftLeft(integerPart *, unsigned int parts,
+                          unsigned int count);
+
+  /// Shift a bignum right COUNT bits.  Shifted in bits are zero.  There are no
+  /// restrictions on COUNT.
+  static void tcShiftRight(integerPart *, unsigned int parts,
+                           unsigned int count);
+
+  /// The obvious AND, OR and XOR and complement operations.
+  static void tcAnd(integerPart *, const integerPart *, unsigned int);
+  static void tcOr(integerPart *, const integerPart *, unsigned int);
+  static void tcXor(integerPart *, const integerPart *, unsigned int);
+  static void tcComplement(integerPart *, unsigned int);
+
+  /// Comparison (unsigned) of two bignums.
+  static int tcCompare(const integerPart *, const integerPart *, unsigned int);
+
+  /// Increment a bignum in-place.  Return the carry flag.
+  static integerPart tcIncrement(integerPart *, unsigned int);
+
+  /// Decrement a bignum in-place.  Return the borrow flag.
+  static integerPart tcDecrement(integerPart *, unsigned int);
+
+  /// Set the least significant BITS and clear the rest.
+  static void tcSetLeastSignificantBits(integerPart *, unsigned int,
+                                        unsigned int bits);
+
+  /// \brief debug method
+  void dump() const;
+
+  /// @}
+};
+
+/// Magic data for optimising signed division by a constant.
+struct APInt::ms {
+  APInt m;    ///< magic number
+  unsigned s; ///< shift amount
+};
+
+/// Magic data for optimising unsigned division by a constant.
+struct APInt::mu {
+  APInt m;    ///< magic number
+  bool a;     ///< add indicator
+  unsigned s; ///< shift amount
+};
+
+inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; }
+
+inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; }
+
+inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) {
+  I.print(OS, true);
+  return OS;
+}
+
+inline APInt operator-(APInt v) {
+  v.flipAllBits();
+  ++v;
+  return v;
+}
+
+inline APInt operator+(APInt a, const APInt &b) {
+  a += b;
+  return a;
+}
+
+inline APInt operator+(const APInt &a, APInt &&b) {
+  b += a;
+  return std::move(b);
+}
+
+inline APInt operator+(APInt a, uint64_t RHS) {
+  a += RHS;
+  return a;
+}
+
+inline APInt operator+(uint64_t LHS, APInt b) {
+  b += LHS;
+  return b;
+}
+
+inline APInt operator-(APInt a, const APInt &b) {
+  a -= b;
+  return a;
+}
+
+inline APInt operator-(const APInt &a, APInt &&b) {
+  b = -std::move(b);
+  b += a;
+  return std::move(b);
+}
+
+inline APInt operator-(APInt a, uint64_t RHS) {
+  a -= RHS;
+  return a;
+}
+
+inline APInt operator-(uint64_t LHS, APInt b) {
+  b = -std::move(b);
+  b += LHS;
+  return b;
+}
+
+
+namespace APIntOps {
+
+/// \brief Determine the smaller of two APInts considered to be signed.
+inline const APInt &smin(const APInt &A, const APInt &B) {
+  return A.slt(B) ? A : B;
+}
+
+/// \brief Determine the larger of two APInts considered to be signed.
+inline const APInt &smax(const APInt &A, const APInt &B) {
+  return A.sgt(B) ? A : B;
+}
+
+/// \brief Determine the smaller of two APInts considered to be signed.
+inline const APInt &umin(const APInt &A, const APInt &B) {
+  return A.ult(B) ? A : B;
+}
+
+/// \brief Determine the larger of two APInts considered to be unsigned.
+inline const APInt &umax(const APInt &A, const APInt &B) {
+  return A.ugt(B) ? A : B;
+}
+
+/// \brief Check if the specified APInt has a N-bits unsigned integer value.
+inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); }
+
+/// \brief Check if the specified APInt has a N-bits signed integer value.
+inline bool isSignedIntN(unsigned N, const APInt &APIVal) {
+  return APIVal.isSignedIntN(N);
+}
+
+/// \returns true if the argument APInt value is a sequence of ones starting at
+/// the least significant bit with the remainder zero.
+inline bool isMask(unsigned numBits, const APInt &APIVal) {
+  return numBits <= APIVal.getBitWidth() &&
+         APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits);
+}
+
+/// \returns true if the argument is a non-empty sequence of ones starting at
+/// the least significant bit with the remainder zero (32 bit version).
+/// Ex. isMask(0x0000FFFFU) == true.
+inline bool isMask(const APInt &Value) {
+  return (Value != 0) && ((Value + 1) & Value) == 0;
+}
+
+/// \brief Return true if the argument APInt value contains a sequence of ones
+/// with the remainder zero.
+inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) {
+  return isMask(numBits, (APIVal - APInt(numBits, 1)) | APIVal);
+}
+
+/// \brief Returns a byte-swapped representation of the specified APInt Value.
+inline APInt byteSwap(const APInt &APIVal) { return APIVal.byteSwap(); }
+
+/// \brief Returns the floor log base 2 of the specified APInt value.
+inline unsigned logBase2(const APInt &APIVal) { return APIVal.logBase2(); }
+
+/// \brief Compute GCD of two APInt values.
+///
+/// This function returns the greatest common divisor of the two APInt values
+/// using Euclid's algorithm.
+///
+/// \returns the greatest common divisor of Val1 and Val2
+APInt GreatestCommonDivisor(const APInt &Val1, const APInt &Val2);
+
+/// \brief Converts the given APInt to a double value.
+///
+/// Treats the APInt as an unsigned value for conversion purposes.
+inline double RoundAPIntToDouble(const APInt &APIVal) {
+  return APIVal.roundToDouble();
+}
+
+/// \brief Converts the given APInt to a double value.
+///
+/// Treats the APInt as a signed value for conversion purposes.
+inline double RoundSignedAPIntToDouble(const APInt &APIVal) {
+  return APIVal.signedRoundToDouble();
+}
+
+/// \brief Converts the given APInt to a float vlalue.
+inline float RoundAPIntToFloat(const APInt &APIVal) {
+  return float(RoundAPIntToDouble(APIVal));
+}
+
+/// \brief Converts the given APInt to a float value.
+///
+/// Treast the APInt as a signed value for conversion purposes.
+inline float RoundSignedAPIntToFloat(const APInt &APIVal) {
+  return float(APIVal.signedRoundToDouble());
+}
+
+/// \brief Converts the given double value into a APInt.
+///
+/// This function convert a double value to an APInt value.
+APInt RoundDoubleToAPInt(double Double, unsigned width);
+
+/// \brief Converts a float value into a APInt.
+///
+/// Converts a float value into an APInt value.
+inline APInt RoundFloatToAPInt(float Float, unsigned width) {
+  return RoundDoubleToAPInt(double(Float), width);
+}
+
+/// \brief Arithmetic right-shift function.
+///
+/// Arithmetic right-shift the APInt by shiftAmt.
+inline APInt ashr(const APInt &LHS, unsigned shiftAmt) {
+  return LHS.ashr(shiftAmt);
+}
+
+/// \brief Logical right-shift function.
+///
+/// Logical right-shift the APInt by shiftAmt.
+inline APInt lshr(const APInt &LHS, unsigned shiftAmt) {
+  return LHS.lshr(shiftAmt);
+}
+
+/// \brief Left-shift function.
+///
+/// Left-shift the APInt by shiftAmt.
+inline APInt shl(const APInt &LHS, unsigned shiftAmt) {
+  return LHS.shl(shiftAmt);
+}
+
+/// \brief Signed division function for APInt.
+///
+/// Signed divide APInt LHS by APInt RHS.
+inline APInt sdiv(const APInt &LHS, const APInt &RHS) { return LHS.sdiv(RHS); }
+
+/// \brief Unsigned division function for APInt.
+///
+/// Unsigned divide APInt LHS by APInt RHS.
+inline APInt udiv(const APInt &LHS, const APInt &RHS) { return LHS.udiv(RHS); }
+
+/// \brief Function for signed remainder operation.
+///
+/// Signed remainder operation on APInt.
+inline APInt srem(const APInt &LHS, const APInt &RHS) { return LHS.srem(RHS); }
+
+/// \brief Function for unsigned remainder operation.
+///
+/// Unsigned remainder operation on APInt.
+inline APInt urem(const APInt &LHS, const APInt &RHS) { return LHS.urem(RHS); }
+
+/// \brief Function for multiplication operation.
+///
+/// Performs multiplication on APInt values.
+inline APInt mul(const APInt &LHS, const APInt &RHS) { return LHS * RHS; }
+
+/// \brief Function for addition operation.
+///
+/// Performs addition on APInt values.
+inline APInt add(const APInt &LHS, const APInt &RHS) { return LHS + RHS; }
+
+/// \brief Function for subtraction operation.
+///
+/// Performs subtraction on APInt values.
+inline APInt sub(const APInt &LHS, const APInt &RHS) { return LHS - RHS; }
+
+/// \brief Bitwise AND function for APInt.
+///
+/// Performs bitwise AND operation on APInt LHS and
+/// APInt RHS.
+inline APInt And(const APInt &LHS, const APInt &RHS) { return LHS & RHS; }
+
+/// \brief Bitwise OR function for APInt.
+///
+/// Performs bitwise OR operation on APInt LHS and APInt RHS.
+inline APInt Or(const APInt &LHS, const APInt &RHS) { return LHS | RHS; }
+
+/// \brief Bitwise XOR function for APInt.
+///
+/// Performs bitwise XOR operation on APInt.
+inline APInt Xor(const APInt &LHS, const APInt &RHS) { return LHS ^ RHS; }
+
+/// \brief Bitwise complement function.
+///
+/// Performs a bitwise complement operation on APInt.
+inline APInt Not(const APInt &APIVal) { return ~APIVal; }
+
+} // End of APIntOps namespace
+
+// See friend declaration above. This additional declaration is required in
+// order to compile LLVM with IBM xlC compiler.
+hash_code hash_value(const APInt &Arg);
+} // End of llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ArrayRef.h b/third_party/llvm-subzero/include/llvm/ADT/ArrayRef.h
new file mode 100644
index 0000000..c1d66c6
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/ArrayRef.h
@@ -0,0 +1,447 @@
+//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ARRAYREF_H
+#define LLVM_ADT_ARRAYREF_H
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
+#include <array>
+#include <vector>
+
+namespace llvm {
+  /// ArrayRef - Represent a constant reference to an array (0 or more elements
+  /// consecutively in memory), i.e. a start pointer and a length.  It allows
+  /// various APIs to take consecutive elements easily and conveniently.
+  ///
+  /// This class does not own the underlying data, it is expected to be used in
+  /// situations where the data resides in some other buffer, whose lifetime
+  /// extends past that of the ArrayRef. For this reason, it is not in general
+  /// safe to store an ArrayRef.
+  ///
+  /// This is intended to be trivially copyable, so it should be passed by
+  /// value.
+  template<typename T>
+  class ArrayRef {
+  public:
+    typedef const T *iterator;
+    typedef const T *const_iterator;
+    typedef size_t size_type;
+
+    typedef std::reverse_iterator<iterator> reverse_iterator;
+
+  private:
+    /// The start of the array, in an external buffer.
+    const T *Data;
+
+    /// The number of elements.
+    size_type Length;
+
+  public:
+    /// @name Constructors
+    /// @{
+
+    /// Construct an empty ArrayRef.
+    /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {}
+
+    /// Construct an empty ArrayRef from None.
+    /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {}
+
+    /// Construct an ArrayRef from a single element.
+    /*implicit*/ ArrayRef(const T &OneElt)
+      : Data(&OneElt), Length(1) {}
+
+    /// Construct an ArrayRef from a pointer and length.
+    /*implicit*/ ArrayRef(const T *data, size_t length)
+      : Data(data), Length(length) {}
+
+    /// Construct an ArrayRef from a range.
+    ArrayRef(const T *begin, const T *end)
+      : Data(begin), Length(end - begin) {}
+
+    /// Construct an ArrayRef from a SmallVector. This is templated in order to
+    /// avoid instantiating SmallVectorTemplateCommon<T> whenever we
+    /// copy-construct an ArrayRef.
+    template<typename U>
+    /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec)
+      : Data(Vec.data()), Length(Vec.size()) {
+    }
+
+    /// Construct an ArrayRef from a std::vector.
+    template<typename A>
+    /*implicit*/ ArrayRef(const std::vector<T, A> &Vec)
+      : Data(Vec.data()), Length(Vec.size()) {}
+
+    /// Construct an ArrayRef from a std::array
+    template <size_t N>
+    /*implicit*/ LLVM_CONSTEXPR ArrayRef(const std::array<T, N> &Arr)
+      : Data(Arr.data()), Length(N) {}
+
+    /// Construct an ArrayRef from a C array.
+    template <size_t N>
+    /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N])
+      : Data(Arr), Length(N) {}
+
+    /// Construct an ArrayRef from a std::initializer_list.
+    /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
+    : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()),
+      Length(Vec.size()) {}
+
+    /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
+    /// ensure that only ArrayRefs of pointers can be converted.
+    template <typename U>
+    ArrayRef(
+        const ArrayRef<U *> &A,
+        typename std::enable_if<
+           std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
+      : Data(A.data()), Length(A.size()) {}
+
+    /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
+    /// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
+    /// whenever we copy-construct an ArrayRef.
+    template<typename U, typename DummyT>
+    /*implicit*/ ArrayRef(
+      const SmallVectorTemplateCommon<U *, DummyT> &Vec,
+      typename std::enable_if<
+          std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
+      : Data(Vec.data()), Length(Vec.size()) {
+    }
+
+    /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE
+    /// to ensure that only vectors of pointers can be converted.
+    template<typename U, typename A>
+    ArrayRef(const std::vector<U *, A> &Vec,
+             typename std::enable_if<
+                 std::is_convertible<U *const *, T const *>::value>::type* = 0)
+      : Data(Vec.data()), Length(Vec.size()) {}
+
+    /// @}
+    /// @name Simple Operations
+    /// @{
+
+    iterator begin() const { return Data; }
+    iterator end() const { return Data + Length; }
+
+    reverse_iterator rbegin() const { return reverse_iterator(end()); }
+    reverse_iterator rend() const { return reverse_iterator(begin()); }
+
+    /// empty - Check if the array is empty.
+    bool empty() const { return Length == 0; }
+
+    const T *data() const { return Data; }
+
+    /// size - Get the array size.
+    size_t size() const { return Length; }
+
+    /// front - Get the first element.
+    const T &front() const {
+      assert(!empty());
+      return Data[0];
+    }
+
+    /// back - Get the last element.
+    const T &back() const {
+      assert(!empty());
+      return Data[Length-1];
+    }
+
+    // copy - Allocate copy in Allocator and return ArrayRef<T> to it.
+    template <typename Allocator> ArrayRef<T> copy(Allocator &A) {
+      T *Buff = A.template Allocate<T>(Length);
+      std::uninitialized_copy(begin(), end(), Buff);
+      return ArrayRef<T>(Buff, Length);
+    }
+
+    /// equals - Check for element-wise equality.
+    bool equals(ArrayRef RHS) const {
+      if (Length != RHS.Length)
+        return false;
+      return std::equal(begin(), end(), RHS.begin());
+    }
+
+    /// slice(n) - Chop off the first N elements of the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    ArrayRef<T> slice(size_t N) const {
+      assert(N <= size() && "Invalid specifier");
+      return ArrayRef<T>(data()+N, size()-N);
+    }
+
+    /// slice(n, m) - Chop off the first N elements of the array, and keep M
+    /// elements in the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    ArrayRef<T> slice(size_t N, size_t M) const {
+      assert(N+M <= size() && "Invalid specifier");
+      return ArrayRef<T>(data()+N, M);
+    }
+
+    /// \brief Drop the first \p N elements of the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    ArrayRef<T> drop_front(size_t N = 1) const {
+      assert(size() >= N && "Dropping more elements than exist");
+      return slice(N, size() - N);
+    }
+
+    /// \brief Drop the last \p N elements of the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    ArrayRef<T> drop_back(size_t N = 1) const {
+      assert(size() >= N && "Dropping more elements than exist");
+      return slice(0, size() - N);
+    }
+
+    /// \brief Return a copy of *this with only the first \p N elements.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    ArrayRef<T> take_front(size_t N = 1) const {
+      if (N >= size())
+        return *this;
+      return drop_back(size() - N);
+    }
+
+    /// \brief Return a copy of *this with only the last \p N elements.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    ArrayRef<T> take_back(size_t N = 1) const {
+      if (N >= size())
+        return *this;
+      return drop_front(size() - N);
+    }
+
+    /// @}
+    /// @name Operator Overloads
+    /// @{
+    const T &operator[](size_t Index) const {
+      assert(Index < Length && "Invalid index!");
+      return Data[Index];
+    }
+
+    /// @}
+    /// @name Expensive Operations
+    /// @{
+    std::vector<T> vec() const {
+      return std::vector<T>(Data, Data+Length);
+    }
+
+    /// @}
+    /// @name Conversion operators
+    /// @{
+    operator std::vector<T>() const {
+      return std::vector<T>(Data, Data+Length);
+    }
+
+    /// @}
+  };
+
+  /// MutableArrayRef - Represent a mutable reference to an array (0 or more
+  /// elements consecutively in memory), i.e. a start pointer and a length.  It
+  /// allows various APIs to take and modify consecutive elements easily and
+  /// conveniently.
+  ///
+  /// This class does not own the underlying data, it is expected to be used in
+  /// situations where the data resides in some other buffer, whose lifetime
+  /// extends past that of the MutableArrayRef. For this reason, it is not in
+  /// general safe to store a MutableArrayRef.
+  ///
+  /// This is intended to be trivially copyable, so it should be passed by
+  /// value.
+  template<typename T>
+  class MutableArrayRef : public ArrayRef<T> {
+  public:
+    typedef T *iterator;
+
+    typedef std::reverse_iterator<iterator> reverse_iterator;
+
+    /// Construct an empty MutableArrayRef.
+    /*implicit*/ MutableArrayRef() : ArrayRef<T>() {}
+
+    /// Construct an empty MutableArrayRef from None.
+    /*implicit*/ MutableArrayRef(NoneType) : ArrayRef<T>() {}
+
+    /// Construct an MutableArrayRef from a single element.
+    /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
+
+    /// Construct an MutableArrayRef from a pointer and length.
+    /*implicit*/ MutableArrayRef(T *data, size_t length)
+      : ArrayRef<T>(data, length) {}
+
+    /// Construct an MutableArrayRef from a range.
+    MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
+
+    /// Construct an MutableArrayRef from a SmallVector.
+    /*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec)
+    : ArrayRef<T>(Vec) {}
+
+    /// Construct a MutableArrayRef from a std::vector.
+    /*implicit*/ MutableArrayRef(std::vector<T> &Vec)
+    : ArrayRef<T>(Vec) {}
+
+    /// Construct an ArrayRef from a std::array
+    template <size_t N>
+    /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(std::array<T, N> &Arr)
+      : ArrayRef<T>(Arr) {}
+
+    /// Construct an MutableArrayRef from a C array.
+    template <size_t N>
+    /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N])
+      : ArrayRef<T>(Arr) {}
+
+    T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }
+
+    iterator begin() const { return data(); }
+    iterator end() const { return data() + this->size(); }
+
+    reverse_iterator rbegin() const { return reverse_iterator(end()); }
+    reverse_iterator rend() const { return reverse_iterator(begin()); }
+
+    /// front - Get the first element.
+    T &front() const {
+      assert(!this->empty());
+      return data()[0];
+    }
+
+    /// back - Get the last element.
+    T &back() const {
+      assert(!this->empty());
+      return data()[this->size()-1];
+    }
+
+    /// slice(n) - Chop off the first N elements of the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    MutableArrayRef<T> slice(size_t N) const {
+      assert(N <= this->size() && "Invalid specifier");
+      return MutableArrayRef<T>(data()+N, this->size()-N);
+    }
+
+    /// slice(n, m) - Chop off the first N elements of the array, and keep M
+    /// elements in the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    MutableArrayRef<T> slice(size_t N, size_t M) const {
+      assert(N+M <= this->size() && "Invalid specifier");
+      return MutableArrayRef<T>(data()+N, M);
+    }
+
+    /// \brief Drop the first \p N elements of the array.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    MutableArrayRef<T> drop_front(size_t N = 1) const {
+      assert(this->size() >= N && "Dropping more elements than exist");
+      return slice(N, this->size() - N);
+    }
+
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    MutableArrayRef<T> drop_back(size_t N = 1) const {
+      assert(this->size() >= N && "Dropping more elements than exist");
+      return slice(0, this->size() - N);
+    }
+
+    /// \brief Return a copy of *this with only the first \p N elements.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    MutableArrayRef<T> take_front(size_t N = 1) const {
+      if (N >= this->size())
+        return *this;
+      return drop_back(this->size() - N);
+    }
+
+    /// \brief Return a copy of *this with only the last \p N elements.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    MutableArrayRef<T> take_back(size_t N = 1) const {
+      if (N >= this->size())
+        return *this;
+      return drop_front(this->size() - N);
+    }
+
+    /// @}
+    /// @name Operator Overloads
+    /// @{
+    T &operator[](size_t Index) const {
+      assert(Index < this->size() && "Invalid index!");
+      return data()[Index];
+    }
+  };
+
+  /// @name ArrayRef Convenience constructors
+  /// @{
+
+  /// Construct an ArrayRef from a single element.
+  template<typename T>
+  ArrayRef<T> makeArrayRef(const T &OneElt) {
+    return OneElt;
+  }
+
+  /// Construct an ArrayRef from a pointer and length.
+  template<typename T>
+  ArrayRef<T> makeArrayRef(const T *data, size_t length) {
+    return ArrayRef<T>(data, length);
+  }
+
+  /// Construct an ArrayRef from a range.
+  template<typename T>
+  ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
+    return ArrayRef<T>(begin, end);
+  }
+
+  /// Construct an ArrayRef from a SmallVector.
+  template <typename T>
+  ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
+    return Vec;
+  }
+
+  /// Construct an ArrayRef from a SmallVector.
+  template <typename T, unsigned N>
+  ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
+    return Vec;
+  }
+
+  /// Construct an ArrayRef from a std::vector.
+  template<typename T>
+  ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
+    return Vec;
+  }
+
+  /// Construct an ArrayRef from an ArrayRef (no-op) (const)
+  template <typename T> ArrayRef<T> makeArrayRef(const ArrayRef<T> &Vec) {
+    return Vec;
+  }
+
+  /// Construct an ArrayRef from an ArrayRef (no-op)
+  template <typename T> ArrayRef<T> &makeArrayRef(ArrayRef<T> &Vec) {
+    return Vec;
+  }
+
+  /// Construct an ArrayRef from a C array.
+  template<typename T, size_t N>
+  ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
+    return ArrayRef<T>(Arr);
+  }
+
+  /// @}
+  /// @name ArrayRef Comparison Operators
+  /// @{
+
+  template<typename T>
+  inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) {
+    return LHS.equals(RHS);
+  }
+
+  template<typename T>
+  inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
+    return !(LHS == RHS);
+  }
+
+  /// @}
+
+  // ArrayRefs can be treated like a POD type.
+  template <typename T> struct isPodLike;
+  template <typename T> struct isPodLike<ArrayRef<T> > {
+    static const bool value = true;
+  };
+
+  template <typename T> hash_code hash_value(ArrayRef<T> S) {
+    return hash_combine_range(S.begin(), S.end());
+  }
+} // end namespace llvm
+
+#endif // LLVM_ADT_ARRAYREF_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/BitVector.h b/third_party/llvm-subzero/include/llvm/ADT/BitVector.h
new file mode 100644
index 0000000..6614371
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/BitVector.h
@@ -0,0 +1,591 @@
+//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the BitVector class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BITVECTOR_H
+#define LLVM_ADT_BITVECTOR_H
+
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+namespace llvm {
+
+class BitVector {
+  typedef unsigned long BitWord;
+
+  enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT };
+
+  static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32,
+                "Unsupported word size");
+
+  BitWord  *Bits;        // Actual bits.
+  unsigned Size;         // Size of bitvector in bits.
+  unsigned Capacity;     // Number of BitWords allocated in the Bits array.
+
+public:
+  typedef unsigned size_type;
+  // Encapsulation of a single bit.
+  class reference {
+    friend class BitVector;
+
+    BitWord *WordRef;
+    unsigned BitPos;
+
+    reference();  // Undefined
+
+  public:
+    reference(BitVector &b, unsigned Idx) {
+      WordRef = &b.Bits[Idx / BITWORD_SIZE];
+      BitPos = Idx % BITWORD_SIZE;
+    }
+
+    reference(const reference&) = default;
+
+    reference &operator=(reference t) {
+      *this = bool(t);
+      return *this;
+    }
+
+    reference& operator=(bool t) {
+      if (t)
+        *WordRef |= BitWord(1) << BitPos;
+      else
+        *WordRef &= ~(BitWord(1) << BitPos);
+      return *this;
+    }
+
+    operator bool() const {
+      return ((*WordRef) & (BitWord(1) << BitPos)) != 0;
+    }
+  };
+
+
+  /// BitVector default ctor - Creates an empty bitvector.
+  BitVector() : Size(0), Capacity(0) {
+    Bits = nullptr;
+  }
+
+  /// BitVector ctor - Creates a bitvector of specified number of bits. All
+  /// bits are initialized to the specified value.
+  explicit BitVector(unsigned s, bool t = false) : Size(s) {
+    Capacity = NumBitWords(s);
+    Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
+    init_words(Bits, Capacity, t);
+    if (t)
+      clear_unused_bits();
+  }
+
+  /// BitVector copy ctor.
+  BitVector(const BitVector &RHS) : Size(RHS.size()) {
+    if (Size == 0) {
+      Bits = nullptr;
+      Capacity = 0;
+      return;
+    }
+
+    Capacity = NumBitWords(RHS.size());
+    Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
+    std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
+  }
+
+  BitVector(BitVector &&RHS)
+    : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
+    RHS.Bits = nullptr;
+    RHS.Size = RHS.Capacity = 0;
+  }
+
+  ~BitVector() {
+    std::free(Bits);
+  }
+
+  /// empty - Tests whether there are no bits in this bitvector.
+  bool empty() const { return Size == 0; }
+
+  /// size - Returns the number of bits in this bitvector.
+  size_type size() const { return Size; }
+
+  /// count - Returns the number of bits which are set.
+  size_type count() const {
+    unsigned NumBits = 0;
+    for (unsigned i = 0; i < NumBitWords(size()); ++i)
+      NumBits += countPopulation(Bits[i]);
+    return NumBits;
+  }
+
+  /// any - Returns true if any bit is set.
+  bool any() const {
+    for (unsigned i = 0; i < NumBitWords(size()); ++i)
+      if (Bits[i] != 0)
+        return true;
+    return false;
+  }
+
+  /// all - Returns true if all bits are set.
+  bool all() const {
+    for (unsigned i = 0; i < Size / BITWORD_SIZE; ++i)
+      if (Bits[i] != ~0UL)
+        return false;
+
+    // If bits remain check that they are ones. The unused bits are always zero.
+    if (unsigned Remainder = Size % BITWORD_SIZE)
+      return Bits[Size / BITWORD_SIZE] == (1UL << Remainder) - 1;
+
+    return true;
+  }
+
+  /// none - Returns true if none of the bits are set.
+  bool none() const {
+    return !any();
+  }
+
+  /// find_first - Returns the index of the first set bit, -1 if none
+  /// of the bits are set.
+  int find_first() const {
+    for (unsigned i = 0; i < NumBitWords(size()); ++i)
+      if (Bits[i] != 0)
+        return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
+    return -1;
+  }
+
+  /// find_next - Returns the index of the next set bit following the
+  /// "Prev" bit. Returns -1 if the next set bit is not found.
+  int find_next(unsigned Prev) const {
+    ++Prev;
+    if (Prev >= Size)
+      return -1;
+
+    unsigned WordPos = Prev / BITWORD_SIZE;
+    unsigned BitPos = Prev % BITWORD_SIZE;
+    BitWord Copy = Bits[WordPos];
+    // Mask off previous bits.
+    Copy &= ~0UL << BitPos;
+
+    if (Copy != 0)
+      return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
+
+    // Check subsequent words.
+    for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
+      if (Bits[i] != 0)
+        return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
+    return -1;
+  }
+
+  /// clear - Clear all bits.
+  void clear() {
+    Size = 0;
+  }
+
+  /// resize - Grow or shrink the bitvector.
+  void resize(unsigned N, bool t = false) {
+    if (N > Capacity * BITWORD_SIZE) {
+      unsigned OldCapacity = Capacity;
+      grow(N);
+      init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t);
+    }
+
+    // Set any old unused bits that are now included in the BitVector. This
+    // may set bits that are not included in the new vector, but we will clear
+    // them back out below.
+    if (N > Size)
+      set_unused_bits(t);
+
+    // Update the size, and clear out any bits that are now unused
+    unsigned OldSize = Size;
+    Size = N;
+    if (t || N < OldSize)
+      clear_unused_bits();
+  }
+
+  void reserve(unsigned N) {
+    if (N > Capacity * BITWORD_SIZE)
+      grow(N);
+  }
+
+  // Set, reset, flip
+  BitVector &set() {
+    init_words(Bits, Capacity, true);
+    clear_unused_bits();
+    return *this;
+  }
+
+  BitVector &set(unsigned Idx) {
+    assert(Bits && "Bits never allocated");
+    Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE);
+    return *this;
+  }
+
+  /// set - Efficiently set a range of bits in [I, E)
+  BitVector &set(unsigned I, unsigned E) {
+    assert(I <= E && "Attempted to set backwards range!");
+    assert(E <= size() && "Attempted to set out-of-bounds range!");
+
+    if (I == E) return *this;
+
+    if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
+      BitWord EMask = 1UL << (E % BITWORD_SIZE);
+      BitWord IMask = 1UL << (I % BITWORD_SIZE);
+      BitWord Mask = EMask - IMask;
+      Bits[I / BITWORD_SIZE] |= Mask;
+      return *this;
+    }
+
+    BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
+    Bits[I / BITWORD_SIZE] |= PrefixMask;
+    I = alignTo(I, BITWORD_SIZE);
+
+    for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
+      Bits[I / BITWORD_SIZE] = ~0UL;
+
+    BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
+    if (I < E)
+      Bits[I / BITWORD_SIZE] |= PostfixMask;
+
+    return *this;
+  }
+
+  BitVector &reset() {
+    init_words(Bits, Capacity, false);
+    return *this;
+  }
+
+  BitVector &reset(unsigned Idx) {
+    Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE));
+    return *this;
+  }
+
+  /// reset - Efficiently reset a range of bits in [I, E)
+  BitVector &reset(unsigned I, unsigned E) {
+    assert(I <= E && "Attempted to reset backwards range!");
+    assert(E <= size() && "Attempted to reset out-of-bounds range!");
+
+    if (I == E) return *this;
+
+    if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
+      BitWord EMask = 1UL << (E % BITWORD_SIZE);
+      BitWord IMask = 1UL << (I % BITWORD_SIZE);
+      BitWord Mask = EMask - IMask;
+      Bits[I / BITWORD_SIZE] &= ~Mask;
+      return *this;
+    }
+
+    BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
+    Bits[I / BITWORD_SIZE] &= ~PrefixMask;
+    I = alignTo(I, BITWORD_SIZE);
+
+    for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
+      Bits[I / BITWORD_SIZE] = 0UL;
+
+    BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
+    if (I < E)
+      Bits[I / BITWORD_SIZE] &= ~PostfixMask;
+
+    return *this;
+  }
+
+  BitVector &flip() {
+    for (unsigned i = 0; i < NumBitWords(size()); ++i)
+      Bits[i] = ~Bits[i];
+    clear_unused_bits();
+    return *this;
+  }
+
+  BitVector &flip(unsigned Idx) {
+    Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE);
+    return *this;
+  }
+
+  // Indexing.
+  reference operator[](unsigned Idx) {
+    assert (Idx < Size && "Out-of-bounds Bit access.");
+    return reference(*this, Idx);
+  }
+
+  bool operator[](unsigned Idx) const {
+    assert (Idx < Size && "Out-of-bounds Bit access.");
+    BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE);
+    return (Bits[Idx / BITWORD_SIZE] & Mask) != 0;
+  }
+
+  bool test(unsigned Idx) const {
+    return (*this)[Idx];
+  }
+
+  /// Test if any common bits are set.
+  bool anyCommon(const BitVector &RHS) const {
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i)
+      if (Bits[i] & RHS.Bits[i])
+        return true;
+    return false;
+  }
+
+  // Comparison operators.
+  bool operator==(const BitVector &RHS) const {
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    unsigned i;
+    for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
+      if (Bits[i] != RHS.Bits[i])
+        return false;
+
+    // Verify that any extra words are all zeros.
+    if (i != ThisWords) {
+      for (; i != ThisWords; ++i)
+        if (Bits[i])
+          return false;
+    } else if (i != RHSWords) {
+      for (; i != RHSWords; ++i)
+        if (RHS.Bits[i])
+          return false;
+    }
+    return true;
+  }
+
+  bool operator!=(const BitVector &RHS) const {
+    return !(*this == RHS);
+  }
+
+  /// Intersection, union, disjoint union.
+  BitVector &operator&=(const BitVector &RHS) {
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    unsigned i;
+    for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
+      Bits[i] &= RHS.Bits[i];
+
+    // Any bits that are just in this bitvector become zero, because they aren't
+    // in the RHS bit vector.  Any words only in RHS are ignored because they
+    // are already zero in the LHS.
+    for (; i != ThisWords; ++i)
+      Bits[i] = 0;
+
+    return *this;
+  }
+
+  /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
+  BitVector &reset(const BitVector &RHS) {
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    unsigned i;
+    for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
+      Bits[i] &= ~RHS.Bits[i];
+    return *this;
+  }
+
+  /// test - Check if (This - RHS) is zero.
+  /// This is the same as reset(RHS) and any().
+  bool test(const BitVector &RHS) const {
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    unsigned i;
+    for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
+      if ((Bits[i] & ~RHS.Bits[i]) != 0)
+        return true;
+
+    for (; i != ThisWords ; ++i)
+      if (Bits[i] != 0)
+        return true;
+
+    return false;
+  }
+
+  BitVector &operator|=(const BitVector &RHS) {
+    if (size() < RHS.size())
+      resize(RHS.size());
+    for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
+      Bits[i] |= RHS.Bits[i];
+    return *this;
+  }
+
+  BitVector &operator^=(const BitVector &RHS) {
+    if (size() < RHS.size())
+      resize(RHS.size());
+    for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
+      Bits[i] ^= RHS.Bits[i];
+    return *this;
+  }
+
+  // Assignment operator.
+  const BitVector &operator=(const BitVector &RHS) {
+    if (this == &RHS) return *this;
+
+    Size = RHS.size();
+    unsigned RHSWords = NumBitWords(Size);
+    if (Size <= Capacity * BITWORD_SIZE) {
+      if (Size)
+        std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord));
+      clear_unused_bits();
+      return *this;
+    }
+
+    // Grow the bitvector to have enough elements.
+    Capacity = RHSWords;
+    assert(Capacity > 0 && "negative capacity?");
+    BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
+    std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord));
+
+    // Destroy the old bits.
+    std::free(Bits);
+    Bits = NewBits;
+
+    return *this;
+  }
+
+  const BitVector &operator=(BitVector &&RHS) {
+    if (this == &RHS) return *this;
+
+    std::free(Bits);
+    Bits = RHS.Bits;
+    Size = RHS.Size;
+    Capacity = RHS.Capacity;
+
+    RHS.Bits = nullptr;
+    RHS.Size = RHS.Capacity = 0;
+
+    return *this;
+  }
+
+  void swap(BitVector &RHS) {
+    std::swap(Bits, RHS.Bits);
+    std::swap(Size, RHS.Size);
+    std::swap(Capacity, RHS.Capacity);
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Portable bit mask operations.
+  //===--------------------------------------------------------------------===//
+  //
+  // These methods all operate on arrays of uint32_t, each holding 32 bits. The
+  // fixed word size makes it easier to work with literal bit vector constants
+  // in portable code.
+  //
+  // The LSB in each word is the lowest numbered bit.  The size of a portable
+  // bit mask is always a whole multiple of 32 bits.  If no bit mask size is
+  // given, the bit mask is assumed to cover the entire BitVector.
+
+  /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
+  /// This computes "*this |= Mask".
+  void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
+    applyMask<true, false>(Mask, MaskWords);
+  }
+
+  /// clearBitsInMask - Clear any bits in this vector that are set in Mask.
+  /// Don't resize. This computes "*this &= ~Mask".
+  void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
+    applyMask<false, false>(Mask, MaskWords);
+  }
+
+  /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
+  /// Don't resize.  This computes "*this |= ~Mask".
+  void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
+    applyMask<true, true>(Mask, MaskWords);
+  }
+
+  /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
+  /// Don't resize.  This computes "*this &= Mask".
+  void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
+    applyMask<false, true>(Mask, MaskWords);
+  }
+
+private:
+  unsigned NumBitWords(unsigned S) const {
+    return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
+  }
+
+  // Set the unused bits in the high words.
+  void set_unused_bits(bool t = true) {
+    //  Set high words first.
+    unsigned UsedWords = NumBitWords(Size);
+    if (Capacity > UsedWords)
+      init_words(&Bits[UsedWords], (Capacity-UsedWords), t);
+
+    //  Then set any stray high bits of the last used word.
+    unsigned ExtraBits = Size % BITWORD_SIZE;
+    if (ExtraBits) {
+      BitWord ExtraBitMask = ~0UL << ExtraBits;
+      if (t)
+        Bits[UsedWords-1] |= ExtraBitMask;
+      else
+        Bits[UsedWords-1] &= ~ExtraBitMask;
+    }
+  }
+
+  // Clear the unused bits in the high words.
+  void clear_unused_bits() {
+    set_unused_bits(false);
+  }
+
+  void grow(unsigned NewSize) {
+    Capacity = std::max(NumBitWords(NewSize), Capacity * 2);
+    assert(Capacity > 0 && "realloc-ing zero space");
+    Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord));
+
+    clear_unused_bits();
+  }
+
+  void init_words(BitWord *B, unsigned NumWords, bool t) {
+    memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
+  }
+
+  template<bool AddBits, bool InvertMask>
+  void applyMask(const uint32_t *Mask, unsigned MaskWords) {
+    static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size.");
+    MaskWords = std::min(MaskWords, (size() + 31) / 32);
+    const unsigned Scale = BITWORD_SIZE / 32;
+    unsigned i;
+    for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) {
+      BitWord BW = Bits[i];
+      // This inner loop should unroll completely when BITWORD_SIZE > 32.
+      for (unsigned b = 0; b != BITWORD_SIZE; b += 32) {
+        uint32_t M = *Mask++;
+        if (InvertMask) M = ~M;
+        if (AddBits) BW |=   BitWord(M) << b;
+        else         BW &= ~(BitWord(M) << b);
+      }
+      Bits[i] = BW;
+    }
+    for (unsigned b = 0; MaskWords; b += 32, --MaskWords) {
+      uint32_t M = *Mask++;
+      if (InvertMask) M = ~M;
+      if (AddBits) Bits[i] |=   BitWord(M) << b;
+      else         Bits[i] &= ~(BitWord(M) << b);
+    }
+    if (AddBits)
+      clear_unused_bits();
+  }
+
+public:
+  /// Return the size (in bytes) of the bit vector.
+  size_t getMemorySize() const { return Capacity * sizeof(BitWord); }
+};
+
+static inline size_t capacity_in_bytes(const BitVector &X) {
+  return X.getMemorySize();
+}
+
+} // end namespace llvm
+
+namespace std {
+  /// Implement std::swap in terms of BitVector swap.
+  inline void
+  swap(llvm::BitVector &LHS, llvm::BitVector &RHS) {
+    LHS.swap(RHS);
+  }
+} // end namespace std
+
+#endif // LLVM_ADT_BITVECTOR_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h b/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h
new file mode 100644
index 0000000..f3910b1
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h
@@ -0,0 +1,1121 @@
+//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DenseMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_DENSEMAP_H
+#define LLVM_ADT_DENSEMAP_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/EpochTracker.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <new>
+#include <utility>
+
+namespace llvm {
+
+namespace detail {
+
+// We extend a pair to allow users to override the bucket type with their own
+// implementation without requiring two members.
+template <typename KeyT, typename ValueT>
+struct DenseMapPair : public std::pair<KeyT, ValueT> {
+  KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
+  const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
+  ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
+  const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }
+};
+
+} // end namespace detail
+
+template <
+    typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,
+    typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false>
+class DenseMapIterator;
+
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+          typename BucketT>
+class DenseMapBase : public DebugEpochBase {
+public:
+  typedef unsigned size_type;
+  typedef KeyT key_type;
+  typedef ValueT mapped_type;
+  typedef BucketT value_type;
+
+  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator;
+  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>
+      const_iterator;
+  inline iterator begin() {
+    // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
+    return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
+  }
+  inline iterator end() {
+    return iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
+  }
+  inline const_iterator begin() const {
+    return empty() ? end()
+                   : const_iterator(getBuckets(), getBucketsEnd(), *this);
+  }
+  inline const_iterator end() const {
+    return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
+  }
+
+  bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
+    return getNumEntries() == 0;
+  }
+  unsigned size() const { return getNumEntries(); }
+
+  /// Grow the densemap so that it can contain at least \p NumEntries items
+  /// before resizing again.
+  void reserve(size_type NumEntries) {
+    auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
+    incrementEpoch();
+    if (NumBuckets > getNumBuckets())
+      grow(NumBuckets);
+  }
+
+  void clear() {
+    incrementEpoch();
+    if (getNumEntries() == 0 && getNumTombstones() == 0) return;
+
+    // If the capacity of the array is huge, and the # elements used is small,
+    // shrink the array.
+    if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
+      shrink_and_clear();
+      return;
+    }
+
+    const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+    unsigned NumEntries = getNumEntries();
+    for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+      if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
+        if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
+          P->getSecond().~ValueT();
+          --NumEntries;
+        }
+        P->getFirst() = EmptyKey;
+      }
+    }
+    assert(NumEntries == 0 && "Node count imbalance!");
+    setNumEntries(0);
+    setNumTombstones(0);
+  }
+
+  /// Return 1 if the specified key is in the map, 0 otherwise.
+  size_type count(const KeyT &Val) const {
+    const BucketT *TheBucket;
+    return LookupBucketFor(Val, TheBucket) ? 1 : 0;
+  }
+
+  iterator find(const KeyT &Val) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Val, TheBucket))
+      return iterator(TheBucket, getBucketsEnd(), *this, true);
+    return end();
+  }
+  const_iterator find(const KeyT &Val) const {
+    const BucketT *TheBucket;
+    if (LookupBucketFor(Val, TheBucket))
+      return const_iterator(TheBucket, getBucketsEnd(), *this, true);
+    return end();
+  }
+
+  /// Alternate version of find() which allows a different, and possibly
+  /// less expensive, key type.
+  /// The DenseMapInfo is responsible for supplying methods
+  /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+  /// type used.
+  template<class LookupKeyT>
+  iterator find_as(const LookupKeyT &Val) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Val, TheBucket))
+      return iterator(TheBucket, getBucketsEnd(), *this, true);
+    return end();
+  }
+  template<class LookupKeyT>
+  const_iterator find_as(const LookupKeyT &Val) const {
+    const BucketT *TheBucket;
+    if (LookupBucketFor(Val, TheBucket))
+      return const_iterator(TheBucket, getBucketsEnd(), *this, true);
+    return end();
+  }
+
+  /// lookup - Return the entry for the specified key, or a default
+  /// constructed value if no such entry exists.
+  ValueT lookup(const KeyT &Val) const {
+    const BucketT *TheBucket;
+    if (LookupBucketFor(Val, TheBucket))
+      return TheBucket->getSecond();
+    return ValueT();
+  }
+
+  // Inserts key,value pair into the map if the key isn't already in the map.
+  // If the key is already in the map, it returns false and doesn't update the
+  // value.
+  std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
+    return try_emplace(KV.first, KV.second);
+  }
+
+  // Inserts key,value pair into the map if the key isn't already in the map.
+  // If the key is already in the map, it returns false and doesn't update the
+  // value.
+  std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
+    return try_emplace(std::move(KV.first), std::move(KV.second));
+  }
+
+  // Inserts key,value pair into the map if the key isn't already in the map.
+  // The value is constructed in-place if the key is not in the map, otherwise
+  // it is not moved.
+  template <typename... Ts>
+  std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Key, TheBucket))
+      return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+                            false); // Already in map.
+
+    // Otherwise, insert the new element.
+    TheBucket =
+        InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
+    return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+                          true);
+  }
+
+  // Inserts key,value pair into the map if the key isn't already in the map.
+  // The value is constructed in-place if the key is not in the map, otherwise
+  // it is not moved.
+  template <typename... Ts>
+  std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Key, TheBucket))
+      return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+                            false); // Already in map.
+
+    // Otherwise, insert the new element.
+    TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
+    return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+                          true);
+  }
+
+  /// Alternate version of insert() which allows a different, and possibly
+  /// less expensive, key type.
+  /// The DenseMapInfo is responsible for supplying methods
+  /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+  /// type used.
+  template <typename LookupKeyT>
+  std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
+                                      const LookupKeyT &Val) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Val, TheBucket))
+      return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+                            false); // Already in map.
+
+    // Otherwise, insert the new element.
+    TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first),
+                                           std::move(KV.second), Val);
+    return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
+                          true);
+  }
+
+  /// insert - Range insertion of pairs.
+  template<typename InputIt>
+  void insert(InputIt I, InputIt E) {
+    for (; I != E; ++I)
+      insert(*I);
+  }
+
+  bool erase(const KeyT &Val) {
+    BucketT *TheBucket;
+    if (!LookupBucketFor(Val, TheBucket))
+      return false; // not in map.
+
+    TheBucket->getSecond().~ValueT();
+    TheBucket->getFirst() = getTombstoneKey();
+    decrementNumEntries();
+    incrementNumTombstones();
+    return true;
+  }
+  void erase(iterator I) {
+    BucketT *TheBucket = &*I;
+    TheBucket->getSecond().~ValueT();
+    TheBucket->getFirst() = getTombstoneKey();
+    decrementNumEntries();
+    incrementNumTombstones();
+  }
+
+  value_type& FindAndConstruct(const KeyT &Key) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Key, TheBucket))
+      return *TheBucket;
+
+    return *InsertIntoBucket(TheBucket, Key);
+  }
+
+  ValueT &operator[](const KeyT &Key) {
+    return FindAndConstruct(Key).second;
+  }
+
+  value_type& FindAndConstruct(KeyT &&Key) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Key, TheBucket))
+      return *TheBucket;
+
+    return *InsertIntoBucket(TheBucket, std::move(Key));
+  }
+
+  ValueT &operator[](KeyT &&Key) {
+    return FindAndConstruct(std::move(Key)).second;
+  }
+
+  /// isPointerIntoBucketsArray - Return true if the specified pointer points
+  /// somewhere into the DenseMap's array of buckets (i.e. either to a key or
+  /// value in the DenseMap).
+  bool isPointerIntoBucketsArray(const void *Ptr) const {
+    return Ptr >= getBuckets() && Ptr < getBucketsEnd();
+  }
+
+  /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
+  /// array.  In conjunction with the previous method, this can be used to
+  /// determine whether an insertion caused the DenseMap to reallocate.
+  const void *getPointerIntoBucketsArray() const { return getBuckets(); }
+
+protected:
+  DenseMapBase() = default;
+
+  void destroyAll() {
+    if (getNumBuckets() == 0) // Nothing to do.
+      return;
+
+    const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+    for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+      if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+          !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
+        P->getSecond().~ValueT();
+      P->getFirst().~KeyT();
+    }
+  }
+
+  void initEmpty() {
+    setNumEntries(0);
+    setNumTombstones(0);
+
+    assert((getNumBuckets() & (getNumBuckets()-1)) == 0 &&
+           "# initial buckets must be a power of two!");
+    const KeyT EmptyKey = getEmptyKey();
+    for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
+      ::new (&B->getFirst()) KeyT(EmptyKey);
+  }
+
+  /// Returns the number of buckets to allocate to ensure that the DenseMap can
+  /// accommodate \p NumEntries without need to grow().
+  unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
+    // Ensure that "NumEntries * 4 < NumBuckets * 3"
+    if (NumEntries == 0)
+      return 0;
+    // +1 is required because of the strict equality.
+    // For example if NumEntries is 48, we need to return 401.
+    return NextPowerOf2(NumEntries * 4 / 3 + 1);
+  }
+
+  void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
+    initEmpty();
+
+    // Insert all the old elements.
+    const KeyT EmptyKey = getEmptyKey();
+    const KeyT TombstoneKey = getTombstoneKey();
+    for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
+      if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
+          !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
+        // Insert the key/value into the new table.
+        BucketT *DestBucket;
+        bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
+        (void)FoundVal; // silence warning.
+        assert(!FoundVal && "Key already in new map?");
+        DestBucket->getFirst() = std::move(B->getFirst());
+        ::new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond()));
+        incrementNumEntries();
+
+        // Free the value.
+        B->getSecond().~ValueT();
+      }
+      B->getFirst().~KeyT();
+    }
+  }
+
+  template <typename OtherBaseT>
+  void copyFrom(
+      const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
+    assert(&other != this);
+    assert(getNumBuckets() == other.getNumBuckets());
+
+    setNumEntries(other.getNumEntries());
+    setNumTombstones(other.getNumTombstones());
+
+    if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
+      memcpy(getBuckets(), other.getBuckets(),
+             getNumBuckets() * sizeof(BucketT));
+    else
+      for (size_t i = 0; i < getNumBuckets(); ++i) {
+        ::new (&getBuckets()[i].getFirst())
+            KeyT(other.getBuckets()[i].getFirst());
+        if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
+            !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
+          ::new (&getBuckets()[i].getSecond())
+              ValueT(other.getBuckets()[i].getSecond());
+      }
+  }
+
+  static unsigned getHashValue(const KeyT &Val) {
+    return KeyInfoT::getHashValue(Val);
+  }
+  template<typename LookupKeyT>
+  static unsigned getHashValue(const LookupKeyT &Val) {
+    return KeyInfoT::getHashValue(Val);
+  }
+  static const KeyT getEmptyKey() {
+    return KeyInfoT::getEmptyKey();
+  }
+  static const KeyT getTombstoneKey() {
+    return KeyInfoT::getTombstoneKey();
+  }
+
+private:
+  unsigned getNumEntries() const {
+    return static_cast<const DerivedT *>(this)->getNumEntries();
+  }
+  void setNumEntries(unsigned Num) {
+    static_cast<DerivedT *>(this)->setNumEntries(Num);
+  }
+  void incrementNumEntries() {
+    setNumEntries(getNumEntries() + 1);
+  }
+  void decrementNumEntries() {
+    setNumEntries(getNumEntries() - 1);
+  }
+  unsigned getNumTombstones() const {
+    return static_cast<const DerivedT *>(this)->getNumTombstones();
+  }
+  void setNumTombstones(unsigned Num) {
+    static_cast<DerivedT *>(this)->setNumTombstones(Num);
+  }
+  void incrementNumTombstones() {
+    setNumTombstones(getNumTombstones() + 1);
+  }
+  void decrementNumTombstones() {
+    setNumTombstones(getNumTombstones() - 1);
+  }
+  const BucketT *getBuckets() const {
+    return static_cast<const DerivedT *>(this)->getBuckets();
+  }
+  BucketT *getBuckets() {
+    return static_cast<DerivedT *>(this)->getBuckets();
+  }
+  unsigned getNumBuckets() const {
+    return static_cast<const DerivedT *>(this)->getNumBuckets();
+  }
+  BucketT *getBucketsEnd() {
+    return getBuckets() + getNumBuckets();
+  }
+  const BucketT *getBucketsEnd() const {
+    return getBuckets() + getNumBuckets();
+  }
+
+  void grow(unsigned AtLeast) {
+    static_cast<DerivedT *>(this)->grow(AtLeast);
+  }
+
+  void shrink_and_clear() {
+    static_cast<DerivedT *>(this)->shrink_and_clear();
+  }
+
+  template <typename KeyArg, typename... ValueArgs>
+  BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
+                            ValueArgs &&... Values) {
+    TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
+
+    TheBucket->getFirst() = std::forward<KeyArg>(Key);
+    ::new (&TheBucket->getSecond()) ValueT(std::forward<ValueArgs>(Values)...);
+    return TheBucket;
+  }
+
+  template <typename LookupKeyT>
+  BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
+                                      ValueT &&Value, LookupKeyT &Lookup) {
+    TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
+
+    TheBucket->getFirst() = std::move(Key);
+    ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
+    return TheBucket;
+  }
+
+  template <typename LookupKeyT>
+  BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
+                                BucketT *TheBucket) {
+    incrementEpoch();
+
+    // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
+    // the buckets are empty (meaning that many are filled with tombstones),
+    // grow the table.
+    //
+    // The later case is tricky.  For example, if we had one empty bucket with
+    // tons of tombstones, failing lookups (e.g. for insertion) would have to
+    // probe almost the entire table until it found the empty bucket.  If the
+    // table completely filled with tombstones, no lookup would ever succeed,
+    // causing infinite loops in lookup.
+    unsigned NewNumEntries = getNumEntries() + 1;
+    unsigned NumBuckets = getNumBuckets();
+    if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
+      this->grow(NumBuckets * 2);
+      LookupBucketFor(Lookup, TheBucket);
+      NumBuckets = getNumBuckets();
+    } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
+                             NumBuckets/8)) {
+      this->grow(NumBuckets);
+      LookupBucketFor(Lookup, TheBucket);
+    }
+    assert(TheBucket);
+
+    // Only update the state after we've grown our bucket space appropriately
+    // so that when growing buckets we have self-consistent entry count.
+    incrementNumEntries();
+
+    // If we are writing over a tombstone, remember this.
+    const KeyT EmptyKey = getEmptyKey();
+    if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
+      decrementNumTombstones();
+
+    return TheBucket;
+  }
+
+  /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
+  /// FoundBucket.  If the bucket contains the key and a value, this returns
+  /// true, otherwise it returns a bucket with an empty marker or tombstone and
+  /// returns false.
+  template<typename LookupKeyT>
+  bool LookupBucketFor(const LookupKeyT &Val,
+                       const BucketT *&FoundBucket) const {
+    const BucketT *BucketsPtr = getBuckets();
+    const unsigned NumBuckets = getNumBuckets();
+
+    if (NumBuckets == 0) {
+      FoundBucket = nullptr;
+      return false;
+    }
+
+    // FoundTombstone - Keep track of whether we find a tombstone while probing.
+    const BucketT *FoundTombstone = nullptr;
+    const KeyT EmptyKey = getEmptyKey();
+    const KeyT TombstoneKey = getTombstoneKey();
+    assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
+           !KeyInfoT::isEqual(Val, TombstoneKey) &&
+           "Empty/Tombstone value shouldn't be inserted into map!");
+
+    unsigned BucketNo = getHashValue(Val) & (NumBuckets-1);
+    unsigned ProbeAmt = 1;
+    while (true) {
+      const BucketT *ThisBucket = BucketsPtr + BucketNo;
+      // Found Val's bucket?  If so, return it.
+      if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
+        FoundBucket = ThisBucket;
+        return true;
+      }
+
+      // If we found an empty bucket, the key doesn't exist in the set.
+      // Insert it and return the default value.
+      if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
+        // If we've already seen a tombstone while probing, fill it in instead
+        // of the empty bucket we eventually probed to.
+        FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
+        return false;
+      }
+
+      // If this is a tombstone, remember it.  If Val ends up not in the map, we
+      // prefer to return it than something that would require more probing.
+      if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
+          !FoundTombstone)
+        FoundTombstone = ThisBucket;  // Remember the first tombstone found.
+
+      // Otherwise, it's a hash collision or a tombstone, continue quadratic
+      // probing.
+      BucketNo += ProbeAmt++;
+      BucketNo &= (NumBuckets-1);
+    }
+  }
+
+  template <typename LookupKeyT>
+  bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
+    const BucketT *ConstFoundBucket;
+    bool Result = const_cast<const DenseMapBase *>(this)
+      ->LookupBucketFor(Val, ConstFoundBucket);
+    FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
+    return Result;
+  }
+
+public:
+  /// Return the approximate size (in bytes) of the actual map.
+  /// This is just the raw memory used by DenseMap.
+  /// If entries are pointers to objects, the size of the referenced objects
+  /// are not included.
+  size_t getMemorySize() const {
+    return getNumBuckets() * sizeof(BucketT);
+  }
+};
+
+template <typename KeyT, typename ValueT,
+          typename KeyInfoT = DenseMapInfo<KeyT>,
+          typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
+                                     KeyT, ValueT, KeyInfoT, BucketT> {
+  // Lift some types from the dependent base class into this class for
+  // simplicity of referring to them.
+  typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
+  friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+  BucketT *Buckets;
+  unsigned NumEntries;
+  unsigned NumTombstones;
+  unsigned NumBuckets;
+
+public:
+  /// Create a DenseMap wth an optional \p InitialReserve that guarantee that
+  /// this number of elements can be inserted in the map without grow()
+  explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); }
+
+  DenseMap(const DenseMap &other) : BaseT() {
+    init(0);
+    copyFrom(other);
+  }
+
+  DenseMap(DenseMap &&other) : BaseT() {
+    init(0);
+    swap(other);
+  }
+
+  template<typename InputIt>
+  DenseMap(const InputIt &I, const InputIt &E) {
+    init(std::distance(I, E));
+    this->insert(I, E);
+  }
+
+  ~DenseMap() {
+    this->destroyAll();
+    operator delete(Buckets);
+  }
+
+  void swap(DenseMap& RHS) {
+    this->incrementEpoch();
+    RHS.incrementEpoch();
+    std::swap(Buckets, RHS.Buckets);
+    std::swap(NumEntries, RHS.NumEntries);
+    std::swap(NumTombstones, RHS.NumTombstones);
+    std::swap(NumBuckets, RHS.NumBuckets);
+  }
+
+  DenseMap& operator=(const DenseMap& other) {
+    if (&other != this)
+      copyFrom(other);
+    return *this;
+  }
+
+  DenseMap& operator=(DenseMap &&other) {
+    this->destroyAll();
+    operator delete(Buckets);
+    init(0);
+    swap(other);
+    return *this;
+  }
+
+  void copyFrom(const DenseMap& other) {
+    this->destroyAll();
+    operator delete(Buckets);
+    if (allocateBuckets(other.NumBuckets)) {
+      this->BaseT::copyFrom(other);
+    } else {
+      NumEntries = 0;
+      NumTombstones = 0;
+    }
+  }
+
+  void init(unsigned InitNumEntries) {
+    auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
+    if (allocateBuckets(InitBuckets)) {
+      this->BaseT::initEmpty();
+    } else {
+      NumEntries = 0;
+      NumTombstones = 0;
+    }
+  }
+
+  void grow(unsigned AtLeast) {
+    unsigned OldNumBuckets = NumBuckets;
+    BucketT *OldBuckets = Buckets;
+
+    allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1))));
+    assert(Buckets);
+    if (!OldBuckets) {
+      this->BaseT::initEmpty();
+      return;
+    }
+
+    this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets);
+
+    // Free the old table.
+    operator delete(OldBuckets);
+  }
+
+  void shrink_and_clear() {
+    unsigned OldNumEntries = NumEntries;
+    this->destroyAll();
+
+    // Reduce the number of buckets.
+    unsigned NewNumBuckets = 0;
+    if (OldNumEntries)
+      NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1));
+    if (NewNumBuckets == NumBuckets) {
+      this->BaseT::initEmpty();
+      return;
+    }
+
+    operator delete(Buckets);
+    init(NewNumBuckets);
+  }
+
+private:
+  unsigned getNumEntries() const {
+    return NumEntries;
+  }
+  void setNumEntries(unsigned Num) {
+    NumEntries = Num;
+  }
+
+  unsigned getNumTombstones() const {
+    return NumTombstones;
+  }
+  void setNumTombstones(unsigned Num) {
+    NumTombstones = Num;
+  }
+
+  BucketT *getBuckets() const {
+    return Buckets;
+  }
+
+  unsigned getNumBuckets() const {
+    return NumBuckets;
+  }
+
+  bool allocateBuckets(unsigned Num) {
+    NumBuckets = Num;
+    if (NumBuckets == 0) {
+      Buckets = nullptr;
+      return false;
+    }
+
+    Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets));
+    return true;
+  }
+};
+
+template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
+          typename KeyInfoT = DenseMapInfo<KeyT>,
+          typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+class SmallDenseMap
+    : public DenseMapBase<
+          SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
+          ValueT, KeyInfoT, BucketT> {
+  // Lift some types from the dependent base class into this class for
+  // simplicity of referring to them.
+  typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
+  friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+  unsigned Small : 1;
+  unsigned NumEntries : 31;
+  unsigned NumTombstones;
+
+  struct LargeRep {
+    BucketT *Buckets;
+    unsigned NumBuckets;
+  };
+
+  /// A "union" of an inline bucket array and the struct representing
+  /// a large bucket. This union will be discriminated by the 'Small' bit.
+  AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage;
+
+public:
+  explicit SmallDenseMap(unsigned NumInitBuckets = 0) {
+    init(NumInitBuckets);
+  }
+
+  SmallDenseMap(const SmallDenseMap &other) : BaseT() {
+    init(0);
+    copyFrom(other);
+  }
+
+  SmallDenseMap(SmallDenseMap &&other) : BaseT() {
+    init(0);
+    swap(other);
+  }
+
+  template<typename InputIt>
+  SmallDenseMap(const InputIt &I, const InputIt &E) {
+    init(NextPowerOf2(std::distance(I, E)));
+    this->insert(I, E);
+  }
+
+  ~SmallDenseMap() {
+    this->destroyAll();
+    deallocateBuckets();
+  }
+
+  void swap(SmallDenseMap& RHS) {
+    unsigned TmpNumEntries = RHS.NumEntries;
+    RHS.NumEntries = NumEntries;
+    NumEntries = TmpNumEntries;
+    std::swap(NumTombstones, RHS.NumTombstones);
+
+    const KeyT EmptyKey = this->getEmptyKey();
+    const KeyT TombstoneKey = this->getTombstoneKey();
+    if (Small && RHS.Small) {
+      // If we're swapping inline bucket arrays, we have to cope with some of
+      // the tricky bits of DenseMap's storage system: the buckets are not
+      // fully initialized. Thus we swap every key, but we may have
+      // a one-directional move of the value.
+      for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
+        BucketT *LHSB = &getInlineBuckets()[i],
+                *RHSB = &RHS.getInlineBuckets()[i];
+        bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&
+                            !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));
+        bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&
+                            !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));
+        if (hasLHSValue && hasRHSValue) {
+          // Swap together if we can...
+          std::swap(*LHSB, *RHSB);
+          continue;
+        }
+        // Swap separately and handle any assymetry.
+        std::swap(LHSB->getFirst(), RHSB->getFirst());
+        if (hasLHSValue) {
+          ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
+          LHSB->getSecond().~ValueT();
+        } else if (hasRHSValue) {
+          ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));
+          RHSB->getSecond().~ValueT();
+        }
+      }
+      return;
+    }
+    if (!Small && !RHS.Small) {
+      std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets);
+      std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets);
+      return;
+    }
+
+    SmallDenseMap &SmallSide = Small ? *this : RHS;
+    SmallDenseMap &LargeSide = Small ? RHS : *this;
+
+    // First stash the large side's rep and move the small side across.
+    LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
+    LargeSide.getLargeRep()->~LargeRep();
+    LargeSide.Small = true;
+    // This is similar to the standard move-from-old-buckets, but the bucket
+    // count hasn't actually rotated in this case. So we have to carefully
+    // move construct the keys and values into their new locations, but there
+    // is no need to re-hash things.
+    for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
+      BucketT *NewB = &LargeSide.getInlineBuckets()[i],
+              *OldB = &SmallSide.getInlineBuckets()[i];
+      ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));
+      OldB->getFirst().~KeyT();
+      if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&
+          !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {
+        ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));
+        OldB->getSecond().~ValueT();
+      }
+    }
+
+    // The hard part of moving the small buckets across is done, just move
+    // the TmpRep into its new home.
+    SmallSide.Small = false;
+    new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
+  }
+
+  SmallDenseMap& operator=(const SmallDenseMap& other) {
+    if (&other != this)
+      copyFrom(other);
+    return *this;
+  }
+
+  SmallDenseMap& operator=(SmallDenseMap &&other) {
+    this->destroyAll();
+    deallocateBuckets();
+    init(0);
+    swap(other);
+    return *this;
+  }
+
+  void copyFrom(const SmallDenseMap& other) {
+    this->destroyAll();
+    deallocateBuckets();
+    Small = true;
+    if (other.getNumBuckets() > InlineBuckets) {
+      Small = false;
+      new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets()));
+    }
+    this->BaseT::copyFrom(other);
+  }
+
+  void init(unsigned InitBuckets) {
+    Small = true;
+    if (InitBuckets > InlineBuckets) {
+      Small = false;
+      new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets));
+    }
+    this->BaseT::initEmpty();
+  }
+
+  void grow(unsigned AtLeast) {
+    if (AtLeast >= InlineBuckets)
+      AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1));
+
+    if (Small) {
+      if (AtLeast < InlineBuckets)
+        return; // Nothing to do.
+
+      // First move the inline buckets into a temporary storage.
+      AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage;
+      BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer);
+      BucketT *TmpEnd = TmpBegin;
+
+      // Loop over the buckets, moving non-empty, non-tombstones into the
+      // temporary storage. Have the loop move the TmpEnd forward as it goes.
+      const KeyT EmptyKey = this->getEmptyKey();
+      const KeyT TombstoneKey = this->getTombstoneKey();
+      for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) {
+        if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+            !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
+          assert(size_t(TmpEnd - TmpBegin) < InlineBuckets &&
+                 "Too many inline buckets!");
+          ::new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst()));
+          ::new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond()));
+          ++TmpEnd;
+          P->getSecond().~ValueT();
+        }
+        P->getFirst().~KeyT();
+      }
+
+      // Now make this map use the large rep, and move all the entries back
+      // into it.
+      Small = false;
+      new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
+      this->moveFromOldBuckets(TmpBegin, TmpEnd);
+      return;
+    }
+
+    LargeRep OldRep = std::move(*getLargeRep());
+    getLargeRep()->~LargeRep();
+    if (AtLeast <= InlineBuckets) {
+      Small = true;
+    } else {
+      new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
+    }
+
+    this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets);
+
+    // Free the old table.
+    operator delete(OldRep.Buckets);
+  }
+
+  void shrink_and_clear() {
+    unsigned OldSize = this->size();
+    this->destroyAll();
+
+    // Reduce the number of buckets.
+    unsigned NewNumBuckets = 0;
+    if (OldSize) {
+      NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1);
+      if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u)
+        NewNumBuckets = 64;
+    }
+    if ((Small && NewNumBuckets <= InlineBuckets) ||
+        (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) {
+      this->BaseT::initEmpty();
+      return;
+    }
+
+    deallocateBuckets();
+    init(NewNumBuckets);
+  }
+
+private:
+  unsigned getNumEntries() const {
+    return NumEntries;
+  }
+  void setNumEntries(unsigned Num) {
+    // NumEntries is hardcoded to be 31 bits wide.
+    assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
+    NumEntries = Num;
+  }
+
+  unsigned getNumTombstones() const {
+    return NumTombstones;
+  }
+  void setNumTombstones(unsigned Num) {
+    NumTombstones = Num;
+  }
+
+  const BucketT *getInlineBuckets() const {
+    assert(Small);
+    // Note that this cast does not violate aliasing rules as we assert that
+    // the memory's dynamic type is the small, inline bucket buffer, and the
+    // 'storage.buffer' static type is 'char *'.
+    return reinterpret_cast<const BucketT *>(storage.buffer);
+  }
+  BucketT *getInlineBuckets() {
+    return const_cast<BucketT *>(
+      const_cast<const SmallDenseMap *>(this)->getInlineBuckets());
+  }
+  const LargeRep *getLargeRep() const {
+    assert(!Small);
+    // Note, same rule about aliasing as with getInlineBuckets.
+    return reinterpret_cast<const LargeRep *>(storage.buffer);
+  }
+  LargeRep *getLargeRep() {
+    return const_cast<LargeRep *>(
+      const_cast<const SmallDenseMap *>(this)->getLargeRep());
+  }
+
+  const BucketT *getBuckets() const {
+    return Small ? getInlineBuckets() : getLargeRep()->Buckets;
+  }
+  BucketT *getBuckets() {
+    return const_cast<BucketT *>(
+      const_cast<const SmallDenseMap *>(this)->getBuckets());
+  }
+  unsigned getNumBuckets() const {
+    return Small ? InlineBuckets : getLargeRep()->NumBuckets;
+  }
+
+  void deallocateBuckets() {
+    if (Small)
+      return;
+
+    operator delete(getLargeRep()->Buckets);
+    getLargeRep()->~LargeRep();
+  }
+
+  LargeRep allocateBuckets(unsigned Num) {
+    assert(Num > InlineBuckets && "Must allocate more buckets than are inline");
+    LargeRep Rep = {
+      static_cast<BucketT*>(operator new(sizeof(BucketT) * Num)), Num
+    };
+    return Rep;
+  }
+};
+
+template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
+          bool IsConst>
+class DenseMapIterator : DebugEpochBase::HandleBase {
+  typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
+  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+  friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
+
+public:
+  typedef ptrdiff_t difference_type;
+  typedef typename std::conditional<IsConst, const Bucket, Bucket>::type
+  value_type;
+  typedef value_type *pointer;
+  typedef value_type &reference;
+  typedef std::forward_iterator_tag iterator_category;
+
+private:
+  pointer Ptr, End;
+
+public:
+  DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
+
+  DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
+                   bool NoAdvance = false)
+      : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
+    assert(isHandleInSync() && "invalid construction!");
+    if (!NoAdvance) AdvancePastEmptyBuckets();
+  }
+
+  // Converting ctor from non-const iterators to const iterators. SFINAE'd out
+  // for const iterator destinations so it doesn't end up as a user defined copy
+  // constructor.
+  template <bool IsConstSrc,
+            typename = typename std::enable_if<!IsConstSrc && IsConst>::type>
+  DenseMapIterator(
+      const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
+      : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
+
+  reference operator*() const {
+    assert(isHandleInSync() && "invalid iterator access!");
+    return *Ptr;
+  }
+  pointer operator->() const {
+    assert(isHandleInSync() && "invalid iterator access!");
+    return Ptr;
+  }
+
+  bool operator==(const ConstIterator &RHS) const {
+    assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+    assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
+    assert(getEpochAddress() == RHS.getEpochAddress() &&
+           "comparing incomparable iterators!");
+    return Ptr == RHS.Ptr;
+  }
+  bool operator!=(const ConstIterator &RHS) const {
+    assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+    assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
+    assert(getEpochAddress() == RHS.getEpochAddress() &&
+           "comparing incomparable iterators!");
+    return Ptr != RHS.Ptr;
+  }
+
+  inline DenseMapIterator& operator++() {  // Preincrement
+    assert(isHandleInSync() && "invalid iterator access!");
+    ++Ptr;
+    AdvancePastEmptyBuckets();
+    return *this;
+  }
+  DenseMapIterator operator++(int) {  // Postincrement
+    assert(isHandleInSync() && "invalid iterator access!");
+    DenseMapIterator tmp = *this; ++*this; return tmp;
+  }
+
+private:
+  void AdvancePastEmptyBuckets() {
+    const KeyT Empty = KeyInfoT::getEmptyKey();
+    const KeyT Tombstone = KeyInfoT::getTombstoneKey();
+
+    while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) ||
+                          KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))
+      ++Ptr;
+  }
+};
+
+template<typename KeyT, typename ValueT, typename KeyInfoT>
+static inline size_t
+capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {
+  return X.getMemorySize();
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_DENSEMAP_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/DenseMapInfo.h b/third_party/llvm-subzero/include/llvm/ADT/DenseMapInfo.h
new file mode 100644
index 0000000..18c692e
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/DenseMapInfo.h
@@ -0,0 +1,251 @@
+//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines DenseMapInfo traits for DenseMap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_DENSEMAPINFO_H
+#define LLVM_ADT_DENSEMAPINFO_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
+
+namespace llvm {
+
+template<typename T>
+struct DenseMapInfo {
+  //static inline T getEmptyKey();
+  //static inline T getTombstoneKey();
+  //static unsigned getHashValue(const T &Val);
+  //static bool isEqual(const T &LHS, const T &RHS);
+};
+
+template <typename T> struct CachedHash {
+  CachedHash(T Val) : Val(std::move(Val)) {
+    Hash = DenseMapInfo<T>::getHashValue(Val);
+  }
+  CachedHash(T Val, unsigned Hash) : Val(std::move(Val)), Hash(Hash) {}
+  T Val;
+  unsigned Hash;
+};
+
+// Provide DenseMapInfo for all CachedHash<T>.
+template <typename T> struct DenseMapInfo<CachedHash<T>> {
+  static CachedHash<T> getEmptyKey() {
+    T N = DenseMapInfo<T>::getEmptyKey();
+    return {N, 0};
+  }
+  static CachedHash<T> getTombstoneKey() {
+    T N = DenseMapInfo<T>::getTombstoneKey();
+    return {N, 0};
+  }
+  static unsigned getHashValue(CachedHash<T> Val) {
+    assert(!isEqual(Val, getEmptyKey()) && "Cannot hash the empty key!");
+    assert(!isEqual(Val, getTombstoneKey()) &&
+           "Cannot hash the tombstone key!");
+    return Val.Hash;
+  }
+  static bool isEqual(CachedHash<T> A, CachedHash<T> B) {
+    return DenseMapInfo<T>::isEqual(A.Val, B.Val);
+  }
+};
+
+// Provide DenseMapInfo for all pointers.
+template<typename T>
+struct DenseMapInfo<T*> {
+  static inline T* getEmptyKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
+    return reinterpret_cast<T*>(Val);
+  }
+  static inline T* getTombstoneKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-2);
+    Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
+    return reinterpret_cast<T*>(Val);
+  }
+  static unsigned getHashValue(const T *PtrVal) {
+    return (unsigned((uintptr_t)PtrVal) >> 4) ^
+           (unsigned((uintptr_t)PtrVal) >> 9);
+  }
+  static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
+};
+
+// Provide DenseMapInfo for chars.
+template<> struct DenseMapInfo<char> {
+  static inline char getEmptyKey() { return ~0; }
+  static inline char getTombstoneKey() { return ~0 - 1; }
+  static unsigned getHashValue(const char& Val) { return Val * 37U; }
+  static bool isEqual(const char &LHS, const char &RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned ints.
+template<> struct DenseMapInfo<unsigned> {
+  static inline unsigned getEmptyKey() { return ~0U; }
+  static inline unsigned getTombstoneKey() { return ~0U - 1; }
+  static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
+  static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned longs.
+template<> struct DenseMapInfo<unsigned long> {
+  static inline unsigned long getEmptyKey() { return ~0UL; }
+  static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
+  static unsigned getHashValue(const unsigned long& Val) {
+    return (unsigned)(Val * 37UL);
+  }
+  static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned long longs.
+template<> struct DenseMapInfo<unsigned long long> {
+  static inline unsigned long long getEmptyKey() { return ~0ULL; }
+  static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
+  static unsigned getHashValue(const unsigned long long& Val) {
+    return (unsigned)(Val * 37ULL);
+  }
+  static bool isEqual(const unsigned long long& LHS,
+                      const unsigned long long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for ints.
+template<> struct DenseMapInfo<int> {
+  static inline int getEmptyKey() { return 0x7fffffff; }
+  static inline int getTombstoneKey() { return -0x7fffffff - 1; }
+  static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
+  static bool isEqual(const int& LHS, const int& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for longs.
+template<> struct DenseMapInfo<long> {
+  static inline long getEmptyKey() {
+    return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
+  }
+  static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
+  static unsigned getHashValue(const long& Val) {
+    return (unsigned)(Val * 37UL);
+  }
+  static bool isEqual(const long& LHS, const long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for long longs.
+template<> struct DenseMapInfo<long long> {
+  static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
+  static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
+  static unsigned getHashValue(const long long& Val) {
+    return (unsigned)(Val * 37ULL);
+  }
+  static bool isEqual(const long long& LHS,
+                      const long long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for all pairs whose members have info.
+template<typename T, typename U>
+struct DenseMapInfo<std::pair<T, U> > {
+  typedef std::pair<T, U> Pair;
+  typedef DenseMapInfo<T> FirstInfo;
+  typedef DenseMapInfo<U> SecondInfo;
+
+  static inline Pair getEmptyKey() {
+    return std::make_pair(FirstInfo::getEmptyKey(),
+                          SecondInfo::getEmptyKey());
+  }
+  static inline Pair getTombstoneKey() {
+    return std::make_pair(FirstInfo::getTombstoneKey(),
+                          SecondInfo::getTombstoneKey());
+  }
+  static unsigned getHashValue(const Pair& PairVal) {
+    uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
+          | (uint64_t)SecondInfo::getHashValue(PairVal.second);
+    key += ~(key << 32);
+    key ^= (key >> 22);
+    key += ~(key << 13);
+    key ^= (key >> 8);
+    key += (key << 3);
+    key ^= (key >> 15);
+    key += ~(key << 27);
+    key ^= (key >> 31);
+    return (unsigned)key;
+  }
+  static bool isEqual(const Pair &LHS, const Pair &RHS) {
+    return FirstInfo::isEqual(LHS.first, RHS.first) &&
+           SecondInfo::isEqual(LHS.second, RHS.second);
+  }
+};
+
+// Provide DenseMapInfo for StringRefs.
+template <> struct DenseMapInfo<StringRef> {
+  static inline StringRef getEmptyKey() {
+    return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
+                     0);
+  }
+  static inline StringRef getTombstoneKey() {
+    return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
+                     0);
+  }
+  static unsigned getHashValue(StringRef Val) {
+    assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
+    assert(Val.data() != getTombstoneKey().data() &&
+           "Cannot hash the tombstone key!");
+    return (unsigned)(hash_value(Val));
+  }
+  static bool isEqual(StringRef LHS, StringRef RHS) {
+    if (RHS.data() == getEmptyKey().data())
+      return LHS.data() == getEmptyKey().data();
+    if (RHS.data() == getTombstoneKey().data())
+      return LHS.data() == getTombstoneKey().data();
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for ArrayRefs.
+template <typename T> struct DenseMapInfo<ArrayRef<T>> {
+  static inline ArrayRef<T> getEmptyKey() {
+    return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
+                       size_t(0));
+  }
+  static inline ArrayRef<T> getTombstoneKey() {
+    return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
+                       size_t(0));
+  }
+  static unsigned getHashValue(ArrayRef<T> Val) {
+    assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
+    assert(Val.data() != getTombstoneKey().data() &&
+           "Cannot hash the tombstone key!");
+    return (unsigned)(hash_value(Val));
+  }
+  static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
+    if (RHS.data() == getEmptyKey().data())
+      return LHS.data() == getEmptyKey().data();
+    if (RHS.data() == getTombstoneKey().data())
+      return LHS.data() == getTombstoneKey().data();
+    return LHS == RHS;
+  }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/EpochTracker.h b/third_party/llvm-subzero/include/llvm/ADT/EpochTracker.h
new file mode 100644
index 0000000..582d581
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/EpochTracker.h
@@ -0,0 +1,99 @@
+//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
+// These can be used to write iterators that are fail-fast when LLVM is built
+// with asserts enabled.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_EPOCH_TRACKER_H
+#define LLVM_ADT_EPOCH_TRACKER_H
+
+#include "llvm/Config/llvm-config.h"
+
+#include <cstdint>
+
+namespace llvm {
+
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+
+class DebugEpochBase {
+public:
+  void incrementEpoch() {}
+
+  class HandleBase {
+  public:
+    HandleBase() = default;
+    explicit HandleBase(const DebugEpochBase *) {}
+    bool isHandleInSync() const { return true; }
+    const void *getEpochAddress() const { return nullptr; }
+  };
+};
+
+#else
+
+/// \brief A base class for data structure classes wishing to make iterators
+/// ("handles") pointing into themselves fail-fast.  When building without
+/// asserts, this class is empty and does nothing.
+///
+/// DebugEpochBase does not by itself track handles pointing into itself.  The
+/// expectation is that routines touching the handles will poll on
+/// isHandleInSync at appropriate points to assert that the handle they're using
+/// is still valid.
+///
+class DebugEpochBase {
+  uint64_t Epoch;
+
+public:
+  DebugEpochBase() : Epoch(0) {}
+
+  /// \brief Calling incrementEpoch invalidates all handles pointing into the
+  /// calling instance.
+  void incrementEpoch() { ++Epoch; }
+
+  /// \brief The destructor calls incrementEpoch to make use-after-free bugs
+  /// more likely to crash deterministically.
+  ~DebugEpochBase() { incrementEpoch(); }
+
+  /// \brief A base class for iterator classes ("handles") that wish to poll for
+  /// iterator invalidating modifications in the underlying data structure.
+  /// When LLVM is built without asserts, this class is empty and does nothing.
+  ///
+  /// HandleBase does not track the parent data structure by itself.  It expects
+  /// the routines modifying the data structure to call incrementEpoch when they
+  /// make an iterator-invalidating modification.
+  ///
+  class HandleBase {
+    const uint64_t *EpochAddress;
+    uint64_t EpochAtCreation;
+
+  public:
+    HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
+
+    explicit HandleBase(const DebugEpochBase *Parent)
+        : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
+
+    /// \brief Returns true if the DebugEpochBase this Handle is linked to has
+    /// not called incrementEpoch on itself since the creation of this
+    /// HandleBase instance.
+    bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
+
+    /// \brief Returns a pointer to the epoch word stored in the data structure
+    /// this handle points into.  Can be used to check if two iterators point
+    /// into the same data structure.
+    const void *getEpochAddress() const { return EpochAddress; }
+  };
+};
+
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h b/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h
new file mode 100644
index 0000000..f16258a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h
@@ -0,0 +1,764 @@
+//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a hash set that can be used to remove duplication of nodes
+// in a graph.  This code was originally created by Chris Lattner for use with
+// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_FOLDINGSET_H
+#define LLVM_ADT_FOLDINGSET_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Allocator.h"
+
+namespace llvm {
+/// This folding set used for two purposes:
+///   1. Given information about a node we want to create, look up the unique
+///      instance of the node in the set.  If the node already exists, return
+///      it, otherwise return the bucket it should be inserted into.
+///   2. Given a node that has already been created, remove it from the set.
+///
+/// This class is implemented as a single-link chained hash table, where the
+/// "buckets" are actually the nodes themselves (the next pointer is in the
+/// node).  The last node points back to the bucket to simplify node removal.
+///
+/// Any node that is to be included in the folding set must be a subclass of
+/// FoldingSetNode.  The node class must also define a Profile method used to
+/// establish the unique bits of data for the node.  The Profile method is
+/// passed a FoldingSetNodeID object which is used to gather the bits.  Just
+/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class.
+/// NOTE: That the folding set does not own the nodes and it is the
+/// responsibility of the user to dispose of the nodes.
+///
+/// Eg.
+///    class MyNode : public FoldingSetNode {
+///    private:
+///      std::string Name;
+///      unsigned Value;
+///    public:
+///      MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
+///       ...
+///      void Profile(FoldingSetNodeID &ID) const {
+///        ID.AddString(Name);
+///        ID.AddInteger(Value);
+///      }
+///      ...
+///    };
+///
+/// To define the folding set itself use the FoldingSet template;
+///
+/// Eg.
+///    FoldingSet<MyNode> MyFoldingSet;
+///
+/// Four public methods are available to manipulate the folding set;
+///
+/// 1) If you have an existing node that you want add to the set but unsure
+/// that the node might already exist then call;
+///
+///    MyNode *M = MyFoldingSet.GetOrInsertNode(N);
+///
+/// If The result is equal to the input then the node has been inserted.
+/// Otherwise, the result is the node existing in the folding set, and the
+/// input can be discarded (use the result instead.)
+///
+/// 2) If you are ready to construct a node but want to check if it already
+/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
+/// check;
+///
+///   FoldingSetNodeID ID;
+///   ID.AddString(Name);
+///   ID.AddInteger(Value);
+///   void *InsertPoint;
+///
+///    MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
+///
+/// If found then M with be non-NULL, else InsertPoint will point to where it
+/// should be inserted using InsertNode.
+///
+/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new
+/// node with FindNodeOrInsertPos;
+///
+///    InsertNode(N, InsertPoint);
+///
+/// 4) Finally, if you want to remove a node from the folding set call;
+///
+///    bool WasRemoved = RemoveNode(N);
+///
+/// The result indicates whether the node existed in the folding set.
+
+class FoldingSetNodeID;
+class StringRef;
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetImpl - Implements the folding set functionality.  The main
+/// structure is an array of buckets.  Each bucket is indexed by the hash of
+/// the nodes it contains.  The bucket itself points to the nodes contained
+/// in the bucket via a singly linked list.  The last node in the list points
+/// back to the bucket to facilitate node removal.
+///
+class FoldingSetImpl {
+  virtual void anchor(); // Out of line virtual method.
+
+protected:
+  /// Buckets - Array of bucket chains.
+  ///
+  void **Buckets;
+
+  /// NumBuckets - Length of the Buckets array.  Always a power of 2.
+  ///
+  unsigned NumBuckets;
+
+  /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes
+  /// is greater than twice the number of buckets.
+  unsigned NumNodes;
+
+  explicit FoldingSetImpl(unsigned Log2InitSize = 6);
+  FoldingSetImpl(FoldingSetImpl &&Arg);
+  FoldingSetImpl &operator=(FoldingSetImpl &&RHS);
+  ~FoldingSetImpl();
+
+public:
+  //===--------------------------------------------------------------------===//
+  /// Node - This class is used to maintain the singly linked bucket list in
+  /// a folding set.
+  ///
+  class Node {
+  private:
+    // NextInFoldingSetBucket - next link in the bucket list.
+    void *NextInFoldingSetBucket;
+
+  public:
+    Node() : NextInFoldingSetBucket(nullptr) {}
+
+    // Accessors
+    void *getNextInBucket() const { return NextInFoldingSetBucket; }
+    void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; }
+  };
+
+  /// clear - Remove all nodes from the folding set.
+  void clear();
+
+  /// RemoveNode - Remove a node from the folding set, returning true if one
+  /// was removed or false if the node was not in the folding set.
+  bool RemoveNode(Node *N);
+
+  /// GetOrInsertNode - If there is an existing simple Node exactly
+  /// equal to the specified node, return it.  Otherwise, insert 'N' and return
+  /// it instead.
+  Node *GetOrInsertNode(Node *N);
+
+  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
+  /// return it.  If not, return the insertion token that will make insertion
+  /// faster.
+  Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
+
+  /// InsertNode - Insert the specified node into the folding set, knowing that
+  /// it is not already in the folding set.  InsertPos must be obtained from
+  /// FindNodeOrInsertPos.
+  void InsertNode(Node *N, void *InsertPos);
+
+  /// InsertNode - Insert the specified node into the folding set, knowing that
+  /// it is not already in the folding set.
+  void InsertNode(Node *N) {
+    Node *Inserted = GetOrInsertNode(N);
+    (void)Inserted;
+    assert(Inserted == N && "Node already inserted!");
+  }
+
+  /// size - Returns the number of nodes in the folding set.
+  unsigned size() const { return NumNodes; }
+
+  /// empty - Returns true if there are no nodes in the folding set.
+  bool empty() const { return NumNodes == 0; }
+
+  /// reserve - Increase the number of buckets such that adding the
+  /// EltCount-th node won't cause a rebucket operation. reserve is permitted
+  /// to allocate more space than requested by EltCount.
+  void reserve(unsigned EltCount);
+  /// capacity - Returns the number of nodes permitted in the folding set
+  /// before a rebucket operation is performed.
+  unsigned capacity() {
+    // We allow a load factor of up to 2.0,
+    // so that means our capacity is NumBuckets * 2
+    return NumBuckets * 2;
+  }
+
+private:
+  /// GrowHashTable - Double the size of the hash table and rehash everything.
+  void GrowHashTable();
+
+  /// GrowBucketCount - resize the hash table and rehash everything.
+  /// NewBucketCount must be a power of two, and must be greater than the old
+  /// bucket count.
+  void GrowBucketCount(unsigned NewBucketCount);
+protected:
+  /// GetNodeProfile - Instantiations of the FoldingSet template implement
+  /// this function to gather data bits for the given node.
+  virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0;
+  /// NodeEquals - Instantiations of the FoldingSet template implement
+  /// this function to compare the given node with the given ID.
+  virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
+                          FoldingSetNodeID &TempID) const=0;
+  /// ComputeNodeHash - Instantiations of the FoldingSet template implement
+  /// this function to compute a hash value for the given node.
+  virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
+};
+
+//===----------------------------------------------------------------------===//
+
+template<typename T> struct FoldingSetTrait;
+
+/// DefaultFoldingSetTrait - This class provides default implementations
+/// for FoldingSetTrait implementations.
+///
+template<typename T> struct DefaultFoldingSetTrait {
+  static void Profile(const T &X, FoldingSetNodeID &ID) {
+    X.Profile(ID);
+  }
+  static void Profile(T &X, FoldingSetNodeID &ID) {
+    X.Profile(ID);
+  }
+
+  // Equals - Test if the profile for X would match ID, using TempID
+  // to compute a temporary ID if necessary. The default implementation
+  // just calls Profile and does a regular comparison. Implementations
+  // can override this to provide more efficient implementations.
+  static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
+                            FoldingSetNodeID &TempID);
+
+  // ComputeHash - Compute a hash value for X, using TempID to
+  // compute a temporary ID if necessary. The default implementation
+  // just calls Profile and does a regular hash computation.
+  // Implementations can override this to provide more efficient
+  // implementations.
+  static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
+};
+
+/// FoldingSetTrait - This trait class is used to define behavior of how
+/// to "profile" (in the FoldingSet parlance) an object of a given type.
+/// The default behavior is to invoke a 'Profile' method on an object, but
+/// through template specialization the behavior can be tailored for specific
+/// types.  Combined with the FoldingSetNodeWrapper class, one can add objects
+/// to FoldingSets that were not originally designed to have that behavior.
+template<typename T> struct FoldingSetTrait
+  : public DefaultFoldingSetTrait<T> {};
+
+template<typename T, typename Ctx> struct ContextualFoldingSetTrait;
+
+/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but
+/// for ContextualFoldingSets.
+template<typename T, typename Ctx>
+struct DefaultContextualFoldingSetTrait {
+  static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
+    X.Profile(ID, Context);
+  }
+  static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
+                            FoldingSetNodeID &TempID, Ctx Context);
+  static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
+                                     Ctx Context);
+};
+
+/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for
+/// ContextualFoldingSets.
+template<typename T, typename Ctx> struct ContextualFoldingSetTrait
+  : public DefaultContextualFoldingSetTrait<T, Ctx> {};
+
+//===--------------------------------------------------------------------===//
+/// FoldingSetNodeIDRef - This class describes a reference to an interned
+/// FoldingSetNodeID, which can be a useful to store node id data rather
+/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
+/// is often much larger than necessary, and the possibility of heap
+/// allocation means it requires a non-trivial destructor call.
+class FoldingSetNodeIDRef {
+  const unsigned *Data;
+  size_t Size;
+
+public:
+  FoldingSetNodeIDRef() : Data(nullptr), Size(0) {}
+  FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
+
+  /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
+  /// used to lookup the node in the FoldingSetImpl.
+  unsigned ComputeHash() const;
+
+  bool operator==(FoldingSetNodeIDRef) const;
+
+  bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
+
+  /// Used to compare the "ordering" of two nodes as defined by the
+  /// profiled bits and their ordering defined by memcmp().
+  bool operator<(FoldingSetNodeIDRef) const;
+
+  const unsigned *getData() const { return Data; }
+  size_t getSize() const { return Size; }
+};
+
+//===--------------------------------------------------------------------===//
+/// FoldingSetNodeID - This class is used to gather all the unique data bits of
+/// a node.  When all the bits are gathered this class is used to produce a
+/// hash value for the node.
+///
+class FoldingSetNodeID {
+  /// Bits - Vector of all the data bits that make the node unique.
+  /// Use a SmallVector to avoid a heap allocation in the common case.
+  SmallVector<unsigned, 32> Bits;
+
+public:
+  FoldingSetNodeID() {}
+
+  FoldingSetNodeID(FoldingSetNodeIDRef Ref)
+    : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
+
+  /// Add* - Add various data types to Bit data.
+  ///
+  void AddPointer(const void *Ptr);
+  void AddInteger(signed I);
+  void AddInteger(unsigned I);
+  void AddInteger(long I);
+  void AddInteger(unsigned long I);
+  void AddInteger(long long I);
+  void AddInteger(unsigned long long I);
+  void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
+  void AddString(StringRef String);
+  void AddNodeID(const FoldingSetNodeID &ID);
+
+  template <typename T>
+  inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); }
+
+  /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID
+  /// object to be used to compute a new profile.
+  inline void clear() { Bits.clear(); }
+
+  /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used
+  /// to lookup the node in the FoldingSetImpl.
+  unsigned ComputeHash() const;
+
+  /// operator== - Used to compare two nodes to each other.
+  ///
+  bool operator==(const FoldingSetNodeID &RHS) const;
+  bool operator==(const FoldingSetNodeIDRef RHS) const;
+
+  bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
+  bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);}
+
+  /// Used to compare the "ordering" of two nodes as defined by the
+  /// profiled bits and their ordering defined by memcmp().
+  bool operator<(const FoldingSetNodeID &RHS) const;
+  bool operator<(const FoldingSetNodeIDRef RHS) const;
+
+  /// Intern - Copy this node's data to a memory region allocated from the
+  /// given allocator and return a FoldingSetNodeIDRef describing the
+  /// interned data.
+  FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
+};
+
+// Convenience type to hide the implementation of the folding set.
+typedef FoldingSetImpl::Node FoldingSetNode;
+template<class T> class FoldingSetIterator;
+template<class T> class FoldingSetBucketIterator;
+
+// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
+// require the definition of FoldingSetNodeID.
+template<typename T>
+inline bool
+DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
+                                  unsigned /*IDHash*/,
+                                  FoldingSetNodeID &TempID) {
+  FoldingSetTrait<T>::Profile(X, TempID);
+  return TempID == ID;
+}
+template<typename T>
+inline unsigned
+DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) {
+  FoldingSetTrait<T>::Profile(X, TempID);
+  return TempID.ComputeHash();
+}
+template<typename T, typename Ctx>
+inline bool
+DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X,
+                                                 const FoldingSetNodeID &ID,
+                                                 unsigned /*IDHash*/,
+                                                 FoldingSetNodeID &TempID,
+                                                 Ctx Context) {
+  ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
+  return TempID == ID;
+}
+template<typename T, typename Ctx>
+inline unsigned
+DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
+                                                      FoldingSetNodeID &TempID,
+                                                      Ctx Context) {
+  ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
+  return TempID.ComputeHash();
+}
+
+//===----------------------------------------------------------------------===//
+/// FoldingSet - This template class is used to instantiate a specialized
+/// implementation of the folding set to the node class T.  T must be a
+/// subclass of FoldingSetNode and implement a Profile function.
+///
+/// Note that this set type is movable and move-assignable. However, its
+/// moved-from state is not a valid state for anything other than
+/// move-assigning and destroying. This is primarily to enable movable APIs
+/// that incorporate these objects.
+template <class T> class FoldingSet final : public FoldingSetImpl {
+private:
+  /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
+  /// way to convert nodes into a unique specifier.
+  void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
+    T *TN = static_cast<T *>(N);
+    FoldingSetTrait<T>::Profile(*TN, ID);
+  }
+  /// NodeEquals - Instantiations may optionally provide a way to compare a
+  /// node with a specified ID.
+  bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
+                  FoldingSetNodeID &TempID) const override {
+    T *TN = static_cast<T *>(N);
+    return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
+  }
+  /// ComputeNodeHash - Instantiations may optionally provide a way to compute a
+  /// hash value directly from a node.
+  unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override {
+    T *TN = static_cast<T *>(N);
+    return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
+  }
+
+public:
+  explicit FoldingSet(unsigned Log2InitSize = 6)
+      : FoldingSetImpl(Log2InitSize) {}
+
+  FoldingSet(FoldingSet &&Arg) : FoldingSetImpl(std::move(Arg)) {}
+  FoldingSet &operator=(FoldingSet &&RHS) {
+    (void)FoldingSetImpl::operator=(std::move(RHS));
+    return *this;
+  }
+
+  typedef FoldingSetIterator<T> iterator;
+  iterator begin() { return iterator(Buckets); }
+  iterator end() { return iterator(Buckets+NumBuckets); }
+
+  typedef FoldingSetIterator<const T> const_iterator;
+  const_iterator begin() const { return const_iterator(Buckets); }
+  const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
+
+  typedef FoldingSetBucketIterator<T> bucket_iterator;
+
+  bucket_iterator bucket_begin(unsigned hash) {
+    return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
+  }
+
+  bucket_iterator bucket_end(unsigned hash) {
+    return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
+  }
+
+  /// GetOrInsertNode - If there is an existing simple Node exactly
+  /// equal to the specified node, return it.  Otherwise, insert 'N' and
+  /// return it instead.
+  T *GetOrInsertNode(Node *N) {
+    return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
+  }
+
+  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
+  /// return it.  If not, return the insertion token that will make insertion
+  /// faster.
+  T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+    return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// ContextualFoldingSet - This template class is a further refinement
+/// of FoldingSet which provides a context argument when calling
+/// Profile on its nodes.  Currently, that argument is fixed at
+/// initialization time.
+///
+/// T must be a subclass of FoldingSetNode and implement a Profile
+/// function with signature
+///   void Profile(llvm::FoldingSetNodeID &, Ctx);
+template <class T, class Ctx>
+class ContextualFoldingSet final : public FoldingSetImpl {
+  // Unfortunately, this can't derive from FoldingSet<T> because the
+  // construction vtable for FoldingSet<T> requires
+  // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
+  // requires a single-argument T::Profile().
+
+private:
+  Ctx Context;
+
+  /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
+  /// way to convert nodes into a unique specifier.
+  void GetNodeProfile(FoldingSetImpl::Node *N,
+                      FoldingSetNodeID &ID) const override {
+    T *TN = static_cast<T *>(N);
+    ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
+  }
+  bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID,
+                  unsigned IDHash, FoldingSetNodeID &TempID) const override {
+    T *TN = static_cast<T *>(N);
+    return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
+                                                     Context);
+  }
+  unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
+                           FoldingSetNodeID &TempID) const override {
+    T *TN = static_cast<T *>(N);
+    return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
+  }
+
+public:
+  explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
+  : FoldingSetImpl(Log2InitSize), Context(Context)
+  {}
+
+  Ctx getContext() const { return Context; }
+
+  typedef FoldingSetIterator<T> iterator;
+  iterator begin() { return iterator(Buckets); }
+  iterator end() { return iterator(Buckets+NumBuckets); }
+
+  typedef FoldingSetIterator<const T> const_iterator;
+  const_iterator begin() const { return const_iterator(Buckets); }
+  const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
+
+  typedef FoldingSetBucketIterator<T> bucket_iterator;
+
+  bucket_iterator bucket_begin(unsigned hash) {
+    return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
+  }
+
+  bucket_iterator bucket_end(unsigned hash) {
+    return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
+  }
+
+  /// GetOrInsertNode - If there is an existing simple Node exactly
+  /// equal to the specified node, return it.  Otherwise, insert 'N'
+  /// and return it instead.
+  T *GetOrInsertNode(Node *N) {
+    return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
+  }
+
+  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it
+  /// exists, return it.  If not, return the insertion token that will
+  /// make insertion faster.
+  T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+    return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetVector - This template class combines a FoldingSet and a vector
+/// to provide the interface of FoldingSet but with deterministic iteration
+/// order based on the insertion order. T must be a subclass of FoldingSetNode
+/// and implement a Profile function.
+template <class T, class VectorT = SmallVector<T*, 8> >
+class FoldingSetVector {
+  FoldingSet<T> Set;
+  VectorT Vector;
+
+public:
+  explicit FoldingSetVector(unsigned Log2InitSize = 6)
+      : Set(Log2InitSize) {
+  }
+
+  typedef pointee_iterator<typename VectorT::iterator> iterator;
+  iterator begin() { return Vector.begin(); }
+  iterator end()   { return Vector.end(); }
+
+  typedef pointee_iterator<typename VectorT::const_iterator> const_iterator;
+  const_iterator begin() const { return Vector.begin(); }
+  const_iterator end()   const { return Vector.end(); }
+
+  /// clear - Remove all nodes from the folding set.
+  void clear() { Set.clear(); Vector.clear(); }
+
+  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
+  /// return it.  If not, return the insertion token that will make insertion
+  /// faster.
+  T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+    return Set.FindNodeOrInsertPos(ID, InsertPos);
+  }
+
+  /// GetOrInsertNode - If there is an existing simple Node exactly
+  /// equal to the specified node, return it.  Otherwise, insert 'N' and
+  /// return it instead.
+  T *GetOrInsertNode(T *N) {
+    T *Result = Set.GetOrInsertNode(N);
+    if (Result == N) Vector.push_back(N);
+    return Result;
+  }
+
+  /// InsertNode - Insert the specified node into the folding set, knowing that
+  /// it is not already in the folding set.  InsertPos must be obtained from
+  /// FindNodeOrInsertPos.
+  void InsertNode(T *N, void *InsertPos) {
+    Set.InsertNode(N, InsertPos);
+    Vector.push_back(N);
+  }
+
+  /// InsertNode - Insert the specified node into the folding set, knowing that
+  /// it is not already in the folding set.
+  void InsertNode(T *N) {
+    Set.InsertNode(N);
+    Vector.push_back(N);
+  }
+
+  /// size - Returns the number of nodes in the folding set.
+  unsigned size() const { return Set.size(); }
+
+  /// empty - Returns true if there are no nodes in the folding set.
+  bool empty() const { return Set.empty(); }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetIteratorImpl - This is the common iterator support shared by all
+/// folding sets, which knows how to walk the folding set hash table.
+class FoldingSetIteratorImpl {
+protected:
+  FoldingSetNode *NodePtr;
+  FoldingSetIteratorImpl(void **Bucket);
+  void advance();
+
+public:
+  bool operator==(const FoldingSetIteratorImpl &RHS) const {
+    return NodePtr == RHS.NodePtr;
+  }
+  bool operator!=(const FoldingSetIteratorImpl &RHS) const {
+    return NodePtr != RHS.NodePtr;
+  }
+};
+
+template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl {
+public:
+  explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {}
+
+  T &operator*() const {
+    return *static_cast<T*>(NodePtr);
+  }
+
+  T *operator->() const {
+    return static_cast<T*>(NodePtr);
+  }
+
+  inline FoldingSetIterator &operator++() {          // Preincrement
+    advance();
+    return *this;
+  }
+  FoldingSetIterator operator++(int) {        // Postincrement
+    FoldingSetIterator tmp = *this; ++*this; return tmp;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support
+/// shared by all folding sets, which knows how to walk a particular bucket
+/// of a folding set hash table.
+
+class FoldingSetBucketIteratorImpl {
+protected:
+  void *Ptr;
+
+  explicit FoldingSetBucketIteratorImpl(void **Bucket);
+
+  FoldingSetBucketIteratorImpl(void **Bucket, bool)
+    : Ptr(Bucket) {}
+
+  void advance() {
+    void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket();
+    uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1;
+    Ptr = reinterpret_cast<void*>(x);
+  }
+
+public:
+  bool operator==(const FoldingSetBucketIteratorImpl &RHS) const {
+    return Ptr == RHS.Ptr;
+  }
+  bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const {
+    return Ptr != RHS.Ptr;
+  }
+};
+
+template <class T>
+class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl {
+public:
+  explicit FoldingSetBucketIterator(void **Bucket) :
+    FoldingSetBucketIteratorImpl(Bucket) {}
+
+  FoldingSetBucketIterator(void **Bucket, bool) :
+    FoldingSetBucketIteratorImpl(Bucket, true) {}
+
+  T &operator*() const { return *static_cast<T*>(Ptr); }
+  T *operator->() const { return static_cast<T*>(Ptr); }
+
+  inline FoldingSetBucketIterator &operator++() { // Preincrement
+    advance();
+    return *this;
+  }
+  FoldingSetBucketIterator operator++(int) {      // Postincrement
+    FoldingSetBucketIterator tmp = *this; ++*this; return tmp;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary
+/// types in an enclosing object so that they can be inserted into FoldingSets.
+template <typename T>
+class FoldingSetNodeWrapper : public FoldingSetNode {
+  T data;
+
+public:
+  template <typename... Ts>
+  explicit FoldingSetNodeWrapper(Ts &&... Args)
+      : data(std::forward<Ts>(Args)...) {}
+
+  void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); }
+
+  T &getValue() { return data; }
+  const T &getValue() const { return data; }
+
+  operator T&() { return data; }
+  operator const T&() const { return data; }
+};
+
+//===----------------------------------------------------------------------===//
+/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores
+/// a FoldingSetNodeID value rather than requiring the node to recompute it
+/// each time it is needed. This trades space for speed (which can be
+/// significant if the ID is long), and it also permits nodes to drop
+/// information that would otherwise only be required for recomputing an ID.
+class FastFoldingSetNode : public FoldingSetNode {
+  FoldingSetNodeID FastID;
+
+protected:
+  explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
+
+public:
+  void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
+};
+
+//===----------------------------------------------------------------------===//
+// Partial specializations of FoldingSetTrait.
+
+template<typename T> struct FoldingSetTrait<T*> {
+  static inline void Profile(T *X, FoldingSetNodeID &ID) {
+    ID.AddPointer(X);
+  }
+};
+template <typename T1, typename T2>
+struct FoldingSetTrait<std::pair<T1, T2>> {
+  static inline void Profile(const std::pair<T1, T2> &P,
+                             llvm::FoldingSetNodeID &ID) {
+    ID.Add(P.first);
+    ID.Add(P.second);
+  }
+};
+} // End of namespace llvm.
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Hashing.h b/third_party/llvm-subzero/include/llvm/ADT/Hashing.h
new file mode 100644
index 0000000..c3b5741
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/Hashing.h
@@ -0,0 +1,661 @@
+//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the newly proposed standard C++ interfaces for hashing
+// arbitrary data and building hash functions for user-defined types. This
+// interface was originally proposed in N3333[1] and is currently under review
+// for inclusion in a future TR and/or standard.
+//
+// The primary interfaces provide are comprised of one type and three functions:
+//
+//  -- 'hash_code' class is an opaque type representing the hash code for some
+//     data. It is the intended product of hashing, and can be used to implement
+//     hash tables, checksumming, and other common uses of hashes. It is not an
+//     integer type (although it can be converted to one) because it is risky
+//     to assume much about the internals of a hash_code. In particular, each
+//     execution of the program has a high probability of producing a different
+//     hash_code for a given input. Thus their values are not stable to save or
+//     persist, and should only be used during the execution for the
+//     construction of hashing datastructures.
+//
+//  -- 'hash_value' is a function designed to be overloaded for each
+//     user-defined type which wishes to be used within a hashing context. It
+//     should be overloaded within the user-defined type's namespace and found
+//     via ADL. Overloads for primitive types are provided by this library.
+//
+//  -- 'hash_combine' and 'hash_combine_range' are functions designed to aid
+//      programmers in easily and intuitively combining a set of data into
+//      a single hash_code for their object. They should only logically be used
+//      within the implementation of a 'hash_value' routine or similar context.
+//
+// Note that 'hash_combine_range' contains very special logic for hashing
+// a contiguous array of integers or pointers. This logic is *extremely* fast,
+// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were
+// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys
+// under 32-bytes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_HASHING_H
+#define LLVM_ADT_HASHING_H
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <string>
+#include <utility>
+
+namespace llvm {
+
+/// \brief An opaque object representing a hash code.
+///
+/// This object represents the result of hashing some entity. It is intended to
+/// be used to implement hashtables or other hashing-based data structures.
+/// While it wraps and exposes a numeric value, this value should not be
+/// trusted to be stable or predictable across processes or executions.
+///
+/// In order to obtain the hash_code for an object 'x':
+/// \code
+///   using llvm::hash_value;
+///   llvm::hash_code code = hash_value(x);
+/// \endcode
+class hash_code {
+  size_t value;
+
+public:
+  /// \brief Default construct a hash_code.
+  /// Note that this leaves the value uninitialized.
+  hash_code() = default;
+
+  /// \brief Form a hash code directly from a numerical value.
+  hash_code(size_t value) : value(value) {}
+
+  /// \brief Convert the hash code to its numerical value for use.
+  /*explicit*/ operator size_t() const { return value; }
+
+  friend bool operator==(const hash_code &lhs, const hash_code &rhs) {
+    return lhs.value == rhs.value;
+  }
+  friend bool operator!=(const hash_code &lhs, const hash_code &rhs) {
+    return lhs.value != rhs.value;
+  }
+
+  /// \brief Allow a hash_code to be directly run through hash_value.
+  friend size_t hash_value(const hash_code &code) { return code.value; }
+};
+
+/// \brief Compute a hash_code for any integer value.
+///
+/// Note that this function is intended to compute the same hash_code for
+/// a particular value without regard to the pre-promotion type. This is in
+/// contrast to hash_combine which may produce different hash_codes for
+/// differing argument types even if they would implicit promote to a common
+/// type without changing the value.
+template <typename T>
+typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
+hash_value(T value);
+
+/// \brief Compute a hash_code for a pointer's address.
+///
+/// N.B.: This hashes the *address*. Not the value and not the type.
+template <typename T> hash_code hash_value(const T *ptr);
+
+/// \brief Compute a hash_code for a pair of objects.
+template <typename T, typename U>
+hash_code hash_value(const std::pair<T, U> &arg);
+
+/// \brief Compute a hash_code for a standard string.
+template <typename T>
+hash_code hash_value(const std::basic_string<T> &arg);
+
+
+/// \brief Override the execution seed with a fixed value.
+///
+/// This hashing library uses a per-execution seed designed to change on each
+/// run with high probability in order to ensure that the hash codes are not
+/// attackable and to ensure that output which is intended to be stable does
+/// not rely on the particulars of the hash codes produced.
+///
+/// That said, there are use cases where it is important to be able to
+/// reproduce *exactly* a specific behavior. To that end, we provide a function
+/// which will forcibly set the seed to a fixed value. This must be done at the
+/// start of the program, before any hashes are computed. Also, it cannot be
+/// undone. This makes it thread-hostile and very hard to use outside of
+/// immediately on start of a simple program designed for reproducible
+/// behavior.
+void set_fixed_execution_hash_seed(size_t fixed_value);
+
+
+// All of the implementation details of actually computing the various hash
+// code values are held within this namespace. These routines are included in
+// the header file mainly to allow inlining and constant propagation.
+namespace hashing {
+namespace detail {
+
+inline uint64_t fetch64(const char *p) {
+  uint64_t result;
+  memcpy(&result, p, sizeof(result));
+  if (sys::IsBigEndianHost)
+    sys::swapByteOrder(result);
+  return result;
+}
+
+inline uint32_t fetch32(const char *p) {
+  uint32_t result;
+  memcpy(&result, p, sizeof(result));
+  if (sys::IsBigEndianHost)
+    sys::swapByteOrder(result);
+  return result;
+}
+
+/// Some primes between 2^63 and 2^64 for various uses.
+static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
+static const uint64_t k1 = 0xb492b66fbe98f273ULL;
+static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
+static const uint64_t k3 = 0xc949d7c7509e6557ULL;
+
+/// \brief Bitwise right rotate.
+/// Normally this will compile to a single instruction, especially if the
+/// shift is a manifest constant.
+inline uint64_t rotate(uint64_t val, size_t shift) {
+  // Avoid shifting by 64: doing so yields an undefined result.
+  return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
+}
+
+inline uint64_t shift_mix(uint64_t val) {
+  return val ^ (val >> 47);
+}
+
+inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) {
+  // Murmur-inspired hashing.
+  const uint64_t kMul = 0x9ddfea08eb382d69ULL;
+  uint64_t a = (low ^ high) * kMul;
+  a ^= (a >> 47);
+  uint64_t b = (high ^ a) * kMul;
+  b ^= (b >> 47);
+  b *= kMul;
+  return b;
+}
+
+inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) {
+  uint8_t a = s[0];
+  uint8_t b = s[len >> 1];
+  uint8_t c = s[len - 1];
+  uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
+  uint32_t z = len + (static_cast<uint32_t>(c) << 2);
+  return shift_mix(y * k2 ^ z * k3 ^ seed) * k2;
+}
+
+inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) {
+  uint64_t a = fetch32(s);
+  return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4));
+}
+
+inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) {
+  uint64_t a = fetch64(s);
+  uint64_t b = fetch64(s + len - 8);
+  return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b;
+}
+
+inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) {
+  uint64_t a = fetch64(s) * k1;
+  uint64_t b = fetch64(s + 8);
+  uint64_t c = fetch64(s + len - 8) * k2;
+  uint64_t d = fetch64(s + len - 16) * k0;
+  return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d,
+                       a + rotate(b ^ k3, 20) - c + len + seed);
+}
+
+inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) {
+  uint64_t z = fetch64(s + 24);
+  uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0;
+  uint64_t b = rotate(a + z, 52);
+  uint64_t c = rotate(a, 37);
+  a += fetch64(s + 8);
+  c += rotate(a, 7);
+  a += fetch64(s + 16);
+  uint64_t vf = a + z;
+  uint64_t vs = b + rotate(a, 31) + c;
+  a = fetch64(s + 16) + fetch64(s + len - 32);
+  z = fetch64(s + len - 8);
+  b = rotate(a + z, 52);
+  c = rotate(a, 37);
+  a += fetch64(s + len - 24);
+  c += rotate(a, 7);
+  a += fetch64(s + len - 16);
+  uint64_t wf = a + z;
+  uint64_t ws = b + rotate(a, 31) + c;
+  uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0);
+  return shift_mix((seed ^ (r * k0)) + vs) * k2;
+}
+
+inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
+  if (length >= 4 && length <= 8)
+    return hash_4to8_bytes(s, length, seed);
+  if (length > 8 && length <= 16)
+    return hash_9to16_bytes(s, length, seed);
+  if (length > 16 && length <= 32)
+    return hash_17to32_bytes(s, length, seed);
+  if (length > 32)
+    return hash_33to64_bytes(s, length, seed);
+  if (length != 0)
+    return hash_1to3_bytes(s, length, seed);
+
+  return k2 ^ seed;
+}
+
+/// \brief The intermediate state used during hashing.
+/// Currently, the algorithm for computing hash codes is based on CityHash and
+/// keeps 56 bytes of arbitrary state.
+struct hash_state {
+  uint64_t h0, h1, h2, h3, h4, h5, h6;
+
+  /// \brief Create a new hash_state structure and initialize it based on the
+  /// seed and the first 64-byte chunk.
+  /// This effectively performs the initial mix.
+  static hash_state create(const char *s, uint64_t seed) {
+    hash_state state = {
+      0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49),
+      seed * k1, shift_mix(seed), 0 };
+    state.h6 = hash_16_bytes(state.h4, state.h5);
+    state.mix(s);
+    return state;
+  }
+
+  /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a'
+  /// and 'b', including whatever is already in 'a' and 'b'.
+  static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) {
+    a += fetch64(s);
+    uint64_t c = fetch64(s + 24);
+    b = rotate(b + a + c, 21);
+    uint64_t d = a;
+    a += fetch64(s + 8) + fetch64(s + 16);
+    b += rotate(a, 44) + d;
+    a += c;
+  }
+
+  /// \brief Mix in a 64-byte buffer of data.
+  /// We mix all 64 bytes even when the chunk length is smaller, but we
+  /// record the actual length.
+  void mix(const char *s) {
+    h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
+    h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1;
+    h0 ^= h6;
+    h1 += h3 + fetch64(s + 40);
+    h2 = rotate(h2 + h5, 33) * k1;
+    h3 = h4 * k1;
+    h4 = h0 + h5;
+    mix_32_bytes(s, h3, h4);
+    h5 = h2 + h6;
+    h6 = h1 + fetch64(s + 16);
+    mix_32_bytes(s + 32, h5, h6);
+    std::swap(h2, h0);
+  }
+
+  /// \brief Compute the final 64-bit hash code value based on the current
+  /// state and the length of bytes hashed.
+  uint64_t finalize(size_t length) {
+    return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2,
+                         hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0);
+  }
+};
+
+
+/// \brief A global, fixed seed-override variable.
+///
+/// This variable can be set using the \see llvm::set_fixed_execution_seed
+/// function. See that function for details. Do not, under any circumstances,
+/// set or read this variable.
+extern size_t fixed_seed_override;
+
+inline size_t get_execution_seed() {
+  // FIXME: This needs to be a per-execution seed. This is just a placeholder
+  // implementation. Switching to a per-execution seed is likely to flush out
+  // instability bugs and so will happen as its own commit.
+  //
+  // However, if there is a fixed seed override set the first time this is
+  // called, return that instead of the per-execution seed.
+  const uint64_t seed_prime = 0xff51afd7ed558ccdULL;
+  static size_t seed = fixed_seed_override ? fixed_seed_override
+                                           : (size_t)seed_prime;
+  return seed;
+}
+
+
+/// \brief Trait to indicate whether a type's bits can be hashed directly.
+///
+/// A type trait which is true if we want to combine values for hashing by
+/// reading the underlying data. It is false if values of this type must
+/// first be passed to hash_value, and the resulting hash_codes combined.
+//
+// FIXME: We want to replace is_integral_or_enum and is_pointer here with
+// a predicate which asserts that comparing the underlying storage of two
+// values of the type for equality is equivalent to comparing the two values
+// for equality. For all the platforms we care about, this holds for integers
+// and pointers, but there are platforms where it doesn't and we would like to
+// support user-defined types which happen to satisfy this property.
+template <typename T> struct is_hashable_data
+  : std::integral_constant<bool, ((is_integral_or_enum<T>::value ||
+                                   std::is_pointer<T>::value) &&
+                                  64 % sizeof(T) == 0)> {};
+
+// Special case std::pair to detect when both types are viable and when there
+// is no alignment-derived padding in the pair. This is a bit of a lie because
+// std::pair isn't truly POD, but it's close enough in all reasonable
+// implementations for our use case of hashing the underlying data.
+template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
+  : std::integral_constant<bool, (is_hashable_data<T>::value &&
+                                  is_hashable_data<U>::value &&
+                                  (sizeof(T) + sizeof(U)) ==
+                                   sizeof(std::pair<T, U>))> {};
+
+/// \brief Helper to get the hashable data representation for a type.
+/// This variant is enabled when the type itself can be used.
+template <typename T>
+typename std::enable_if<is_hashable_data<T>::value, T>::type
+get_hashable_data(const T &value) {
+  return value;
+}
+/// \brief Helper to get the hashable data representation for a type.
+/// This variant is enabled when we must first call hash_value and use the
+/// result as our data.
+template <typename T>
+typename std::enable_if<!is_hashable_data<T>::value, size_t>::type
+get_hashable_data(const T &value) {
+  using ::llvm::hash_value;
+  return hash_value(value);
+}
+
+/// \brief Helper to store data from a value into a buffer and advance the
+/// pointer into that buffer.
+///
+/// This routine first checks whether there is enough space in the provided
+/// buffer, and if not immediately returns false. If there is space, it
+/// copies the underlying bytes of value into the buffer, advances the
+/// buffer_ptr past the copied bytes, and returns true.
+template <typename T>
+bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
+                       size_t offset = 0) {
+  size_t store_size = sizeof(value) - offset;
+  if (buffer_ptr + store_size > buffer_end)
+    return false;
+  const char *value_data = reinterpret_cast<const char *>(&value);
+  memcpy(buffer_ptr, value_data + offset, store_size);
+  buffer_ptr += store_size;
+  return true;
+}
+
+/// \brief Implement the combining of integral values into a hash_code.
+///
+/// This overload is selected when the value type of the iterator is
+/// integral. Rather than computing a hash_code for each object and then
+/// combining them, this (as an optimization) directly combines the integers.
+template <typename InputIteratorT>
+hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
+  const size_t seed = get_execution_seed();
+  char buffer[64], *buffer_ptr = buffer;
+  char *const buffer_end = std::end(buffer);
+  while (first != last && store_and_advance(buffer_ptr, buffer_end,
+                                            get_hashable_data(*first)))
+    ++first;
+  if (first == last)
+    return hash_short(buffer, buffer_ptr - buffer, seed);
+  assert(buffer_ptr == buffer_end);
+
+  hash_state state = state.create(buffer, seed);
+  size_t length = 64;
+  while (first != last) {
+    // Fill up the buffer. We don't clear it, which re-mixes the last round
+    // when only a partial 64-byte chunk is left.
+    buffer_ptr = buffer;
+    while (first != last && store_and_advance(buffer_ptr, buffer_end,
+                                              get_hashable_data(*first)))
+      ++first;
+
+    // Rotate the buffer if we did a partial fill in order to simulate doing
+    // a mix of the last 64-bytes. That is how the algorithm works when we
+    // have a contiguous byte sequence, and we want to emulate that here.
+    std::rotate(buffer, buffer_ptr, buffer_end);
+
+    // Mix this chunk into the current state.
+    state.mix(buffer);
+    length += buffer_ptr - buffer;
+  };
+
+  return state.finalize(length);
+}
+
+/// \brief Implement the combining of integral values into a hash_code.
+///
+/// This overload is selected when the value type of the iterator is integral
+/// and when the input iterator is actually a pointer. Rather than computing
+/// a hash_code for each object and then combining them, this (as an
+/// optimization) directly combines the integers. Also, because the integers
+/// are stored in contiguous memory, this routine avoids copying each value
+/// and directly reads from the underlying memory.
+template <typename ValueT>
+typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type
+hash_combine_range_impl(ValueT *first, ValueT *last) {
+  const size_t seed = get_execution_seed();
+  const char *s_begin = reinterpret_cast<const char *>(first);
+  const char *s_end = reinterpret_cast<const char *>(last);
+  const size_t length = std::distance(s_begin, s_end);
+  if (length <= 64)
+    return hash_short(s_begin, length, seed);
+
+  const char *s_aligned_end = s_begin + (length & ~63);
+  hash_state state = state.create(s_begin, seed);
+  s_begin += 64;
+  while (s_begin != s_aligned_end) {
+    state.mix(s_begin);
+    s_begin += 64;
+  }
+  if (length & 63)
+    state.mix(s_end - 64);
+
+  return state.finalize(length);
+}
+
+} // namespace detail
+} // namespace hashing
+
+
+/// \brief Compute a hash_code for a sequence of values.
+///
+/// This hashes a sequence of values. It produces the same hash_code as
+/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences
+/// and is significantly faster given pointers and types which can be hashed as
+/// a sequence of bytes.
+template <typename InputIteratorT>
+hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) {
+  return ::llvm::hashing::detail::hash_combine_range_impl(first, last);
+}
+
+
+// Implementation details for hash_combine.
+namespace hashing {
+namespace detail {
+
+/// \brief Helper class to manage the recursive combining of hash_combine
+/// arguments.
+///
+/// This class exists to manage the state and various calls involved in the
+/// recursive combining of arguments used in hash_combine. It is particularly
+/// useful at minimizing the code in the recursive calls to ease the pain
+/// caused by a lack of variadic functions.
+struct hash_combine_recursive_helper {
+  char buffer[64];
+  hash_state state;
+  const size_t seed;
+
+public:
+  /// \brief Construct a recursive hash combining helper.
+  ///
+  /// This sets up the state for a recursive hash combine, including getting
+  /// the seed and buffer setup.
+  hash_combine_recursive_helper()
+    : seed(get_execution_seed()) {}
+
+  /// \brief Combine one chunk of data into the current in-flight hash.
+  ///
+  /// This merges one chunk of data into the hash. First it tries to buffer
+  /// the data. If the buffer is full, it hashes the buffer into its
+  /// hash_state, empties it, and then merges the new chunk in. This also
+  /// handles cases where the data straddles the end of the buffer.
+  template <typename T>
+  char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
+    if (!store_and_advance(buffer_ptr, buffer_end, data)) {
+      // Check for skew which prevents the buffer from being packed, and do
+      // a partial store into the buffer to fill it. This is only a concern
+      // with the variadic combine because that formation can have varying
+      // argument types.
+      size_t partial_store_size = buffer_end - buffer_ptr;
+      memcpy(buffer_ptr, &data, partial_store_size);
+
+      // If the store fails, our buffer is full and ready to hash. We have to
+      // either initialize the hash state (on the first full buffer) or mix
+      // this buffer into the existing hash state. Length tracks the *hashed*
+      // length, not the buffered length.
+      if (length == 0) {
+        state = state.create(buffer, seed);
+        length = 64;
+      } else {
+        // Mix this chunk into the current state and bump length up by 64.
+        state.mix(buffer);
+        length += 64;
+      }
+      // Reset the buffer_ptr to the head of the buffer for the next chunk of
+      // data.
+      buffer_ptr = buffer;
+
+      // Try again to store into the buffer -- this cannot fail as we only
+      // store types smaller than the buffer.
+      if (!store_and_advance(buffer_ptr, buffer_end, data,
+                             partial_store_size))
+        abort();
+    }
+    return buffer_ptr;
+  }
+
+  /// \brief Recursive, variadic combining method.
+  ///
+  /// This function recurses through each argument, combining that argument
+  /// into a single hash.
+  template <typename T, typename ...Ts>
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+                    const T &arg, const Ts &...args) {
+    buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
+
+    // Recurse to the next argument.
+    return combine(length, buffer_ptr, buffer_end, args...);
+  }
+
+  /// \brief Base case for recursive, variadic combining.
+  ///
+  /// The base case when combining arguments recursively is reached when all
+  /// arguments have been handled. It flushes the remaining buffer and
+  /// constructs a hash_code.
+  hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
+    // Check whether the entire set of values fit in the buffer. If so, we'll
+    // use the optimized short hashing routine and skip state entirely.
+    if (length == 0)
+      return hash_short(buffer, buffer_ptr - buffer, seed);
+
+    // Mix the final buffer, rotating it if we did a partial fill in order to
+    // simulate doing a mix of the last 64-bytes. That is how the algorithm
+    // works when we have a contiguous byte sequence, and we want to emulate
+    // that here.
+    std::rotate(buffer, buffer_ptr, buffer_end);
+
+    // Mix this chunk into the current state.
+    state.mix(buffer);
+    length += buffer_ptr - buffer;
+
+    return state.finalize(length);
+  }
+};
+
+} // namespace detail
+} // namespace hashing
+
+/// \brief Combine values into a single hash_code.
+///
+/// This routine accepts a varying number of arguments of any type. It will
+/// attempt to combine them into a single hash_code. For user-defined types it
+/// attempts to call a \see hash_value overload (via ADL) for the type. For
+/// integer and pointer types it directly combines their data into the
+/// resulting hash_code.
+///
+/// The result is suitable for returning from a user's hash_value
+/// *implementation* for their user-defined type. Consumers of a type should
+/// *not* call this routine, they should instead call 'hash_value'.
+template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
+  // Recursively hash each argument using a helper class.
+  ::llvm::hashing::detail::hash_combine_recursive_helper helper;
+  return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
+}
+
+// Implementation details for implementations of hash_value overloads provided
+// here.
+namespace hashing {
+namespace detail {
+
+/// \brief Helper to hash the value of a single integer.
+///
+/// Overloads for smaller integer types are not provided to ensure consistent
+/// behavior in the presence of integral promotions. Essentially,
+/// "hash_value('4')" and "hash_value('0' + 4)" should be the same.
+inline hash_code hash_integer_value(uint64_t value) {
+  // Similar to hash_4to8_bytes but using a seed instead of length.
+  const uint64_t seed = get_execution_seed();
+  const char *s = reinterpret_cast<const char *>(&value);
+  const uint64_t a = fetch32(s);
+  return hash_16_bytes(seed + (a << 3), fetch32(s + 4));
+}
+
+} // namespace detail
+} // namespace hashing
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T>
+typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
+hash_value(T value) {
+  return ::llvm::hashing::detail::hash_integer_value(
+      static_cast<uint64_t>(value));
+}
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T> hash_code hash_value(const T *ptr) {
+  return ::llvm::hashing::detail::hash_integer_value(
+    reinterpret_cast<uintptr_t>(ptr));
+}
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T, typename U>
+hash_code hash_value(const std::pair<T, U> &arg) {
+  return hash_combine(arg.first, arg.second);
+}
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T>
+hash_code hash_value(const std::basic_string<T> &arg) {
+  return hash_combine_range(arg.begin(), arg.end());
+}
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/IntrusiveRefCntPtr.h b/third_party/llvm-subzero/include/llvm/ADT/IntrusiveRefCntPtr.h
new file mode 100644
index 0000000..3417e9c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -0,0 +1,288 @@
+//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines IntrusiveRefCntPtr, a template class that
+// implements a "smart" pointer for objects that maintain their own
+// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two
+// generic base classes for objects that wish to have their lifetimes
+// managed using reference counting.
+//
+// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added
+// LLVM-style casting.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
+#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+
+namespace llvm {
+
+  template <class T>
+  class IntrusiveRefCntPtr;
+
+//===----------------------------------------------------------------------===//
+/// RefCountedBase - A generic base class for objects that wish to
+///  have their lifetimes managed using reference counts. Classes
+///  subclass RefCountedBase to obtain such functionality, and are
+///  typically handled with IntrusiveRefCntPtr "smart pointers" (see below)
+///  which automatically handle the management of reference counts.
+///  Objects that subclass RefCountedBase should not be allocated on
+///  the stack, as invoking "delete" (which is called when the
+///  reference count hits 0) on such objects is an error.
+//===----------------------------------------------------------------------===//
+  template <class Derived>
+  class RefCountedBase {
+    mutable unsigned ref_cnt;
+
+  public:
+    RefCountedBase() : ref_cnt(0) {}
+    RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
+
+    void Retain() const { ++ref_cnt; }
+    void Release() const {
+      assert (ref_cnt > 0 && "Reference count is already zero.");
+      if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
+    }
+  };
+
+//===----------------------------------------------------------------------===//
+/// RefCountedBaseVPTR - A class that has the same function as
+///  RefCountedBase, but with a virtual destructor. Should be used
+///  instead of RefCountedBase for classes that already have virtual
+///  methods to enforce dynamic allocation via 'new'. Classes that
+///  inherit from RefCountedBaseVPTR can't be allocated on stack -
+///  attempting to do this will produce a compile error.
+//===----------------------------------------------------------------------===//
+  class RefCountedBaseVPTR {
+    mutable unsigned ref_cnt;
+    virtual void anchor();
+
+  protected:
+    RefCountedBaseVPTR() : ref_cnt(0) {}
+    RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
+
+    virtual ~RefCountedBaseVPTR() {}
+
+    void Retain() const { ++ref_cnt; }
+    void Release() const {
+      assert (ref_cnt > 0 && "Reference count is already zero.");
+      if (--ref_cnt == 0) delete this;
+    }
+
+    template <typename T>
+    friend struct IntrusiveRefCntPtrInfo;
+  };
+
+
+  template <typename T> struct IntrusiveRefCntPtrInfo {
+    static void retain(T *obj) { obj->Retain(); }
+    static void release(T *obj) { obj->Release(); }
+  };
+
+/// \brief A thread-safe version of \c llvm::RefCountedBase.
+///
+/// A generic base class for objects that wish to have their lifetimes managed
+/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
+/// obtain such functionality, and are typically handled with
+/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
+/// management of reference counts.
+template <class Derived>
+class ThreadSafeRefCountedBase {
+  mutable std::atomic<int> RefCount;
+
+protected:
+  ThreadSafeRefCountedBase() : RefCount(0) {}
+
+public:
+  void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }
+
+  void Release() const {
+    int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1;
+    assert(NewRefCount >= 0 && "Reference count was already zero.");
+    if (NewRefCount == 0)
+      delete static_cast<const Derived*>(this);
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
+///  that assumes the wrapped object has a reference count associated
+///  with it that can be managed via calls to
+///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
+///  manage reference counts via the RAII idiom: upon creation of
+///  smart pointer the reference count of the wrapped object is
+///  incremented and upon destruction of the smart pointer the
+///  reference count is decremented.  This class also safely handles
+///  wrapping NULL pointers.
+///
+/// Reference counting is implemented via calls to
+///  Obj->Retain()/Obj->Release(). Release() is required to destroy
+///  the object when the reference count reaches zero. Inheriting from
+///  RefCountedBase/RefCountedBaseVPTR takes care of this
+///  automatically.
+//===----------------------------------------------------------------------===//
+  template <typename T>
+  class IntrusiveRefCntPtr {
+    T* Obj;
+
+  public:
+    typedef T element_type;
+
+    explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
+
+    IntrusiveRefCntPtr(T* obj) : Obj(obj) {
+      retain();
+    }
+
+    IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
+      retain();
+    }
+
+    IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
+      S.Obj = nullptr;
+    }
+
+    template <class X>
+    IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
+      S.Obj = nullptr;
+    }
+
+    template <class X>
+    IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
+      : Obj(S.get()) {
+      retain();
+    }
+
+    IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
+      swap(S);
+      return *this;
+    }
+
+    ~IntrusiveRefCntPtr() { release(); }
+
+    T& operator*() const { return *Obj; }
+
+    T* operator->() const { return Obj; }
+
+    T* get() const { return Obj; }
+
+    explicit operator bool() const { return Obj; }
+
+    void swap(IntrusiveRefCntPtr& other) {
+      T* tmp = other.Obj;
+      other.Obj = Obj;
+      Obj = tmp;
+    }
+
+    void reset() {
+      release();
+      Obj = nullptr;
+    }
+
+    void resetWithoutRelease() {
+      Obj = nullptr;
+    }
+
+  private:
+    void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
+    void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
+
+    template <typename X>
+    friend class IntrusiveRefCntPtr;
+  };
+
+  template<class T, class U>
+  inline bool operator==(const IntrusiveRefCntPtr<T>& A,
+                         const IntrusiveRefCntPtr<U>& B)
+  {
+    return A.get() == B.get();
+  }
+
+  template<class T, class U>
+  inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
+                         const IntrusiveRefCntPtr<U>& B)
+  {
+    return A.get() != B.get();
+  }
+
+  template<class T, class U>
+  inline bool operator==(const IntrusiveRefCntPtr<T>& A,
+                         U* B)
+  {
+    return A.get() == B;
+  }
+
+  template<class T, class U>
+  inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
+                         U* B)
+  {
+    return A.get() != B;
+  }
+
+  template<class T, class U>
+  inline bool operator==(T* A,
+                         const IntrusiveRefCntPtr<U>& B)
+  {
+    return A == B.get();
+  }
+
+  template<class T, class U>
+  inline bool operator!=(T* A,
+                         const IntrusiveRefCntPtr<U>& B)
+  {
+    return A != B.get();
+  }
+
+  template <class T>
+  bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
+    return !B;
+  }
+
+  template <class T>
+  bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
+    return B == A;
+  }
+
+  template <class T>
+  bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
+    return !(A == B);
+  }
+
+  template <class T>
+  bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
+    return !(A == B);
+  }
+
+//===----------------------------------------------------------------------===//
+// LLVM-style downcasting support for IntrusiveRefCntPtr objects
+//===----------------------------------------------------------------------===//
+
+  template <typename From> struct simplify_type;
+
+  template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
+    typedef T* SimpleType;
+    static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
+      return Val.get();
+    }
+  };
+
+  template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
+    typedef /*const*/ T* SimpleType;
+    static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
+      return Val.get();
+    }
+  };
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/None.h b/third_party/llvm-subzero/include/llvm/ADT/None.h
new file mode 100644
index 0000000..d69ec17
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/None.h
@@ -0,0 +1,26 @@
+//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides None, an enumerator for use in implicit constructors
+//  of various (usually templated) types to make such construction more
+//  terse.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_NONE_H
+#define LLVM_ADT_NONE_H
+
+namespace llvm {
+/// \brief A simple null object to allow implicit construction of Optional<T>
+/// and similar types without having to spell out the specialization's name.
+enum class NoneType { None };
+const NoneType None = None;
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Optional.h b/third_party/llvm-subzero/include/llvm/ADT/Optional.h
new file mode 100644
index 0000000..20568c5
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/Optional.h
@@ -0,0 +1,289 @@
+//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides Optional, a template class modeled in the spirit of
+//  OCaml's 'opt' variant.  The idea is to strongly type whether or not
+//  a value can be optional.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_OPTIONAL_H
+#define LLVM_ADT_OPTIONAL_H
+
+#include "llvm/ADT/None.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <new>
+#include <utility>
+
+namespace llvm {
+
+template<typename T>
+class Optional {
+  AlignedCharArrayUnion<T> storage;
+  bool hasVal;
+public:
+  typedef T value_type;
+
+  Optional(NoneType) : hasVal(false) {}
+  explicit Optional() : hasVal(false) {}
+  Optional(const T &y) : hasVal(true) {
+    new (storage.buffer) T(y);
+  }
+  Optional(const Optional &O) : hasVal(O.hasVal) {
+    if (hasVal)
+      new (storage.buffer) T(*O);
+  }
+
+  Optional(T &&y) : hasVal(true) {
+    new (storage.buffer) T(std::forward<T>(y));
+  }
+  Optional(Optional<T> &&O) : hasVal(O) {
+    if (O) {
+      new (storage.buffer) T(std::move(*O));
+      O.reset();
+    }
+  }
+  Optional &operator=(T &&y) {
+    if (hasVal)
+      **this = std::move(y);
+    else {
+      new (storage.buffer) T(std::move(y));
+      hasVal = true;
+    }
+    return *this;
+  }
+  Optional &operator=(Optional &&O) {
+    if (!O)
+      reset();
+    else {
+      *this = std::move(*O);
+      O.reset();
+    }
+    return *this;
+  }
+
+  /// Create a new object by constructing it in place with the given arguments.
+  template<typename ...ArgTypes>
+  void emplace(ArgTypes &&...Args) {
+    reset();
+    hasVal = true;
+    new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
+  }
+
+  static inline Optional create(const T* y) {
+    return y ? Optional(*y) : Optional();
+  }
+
+  // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
+  // could be made more efficient by passing by value, possibly unifying them
+  // with the rvalue versions above - but this could place a different set of
+  // requirements (notably: the existence of a default ctor) when implemented
+  // in that way. Careful SFINAE to avoid such pitfalls would be required.
+  Optional &operator=(const T &y) {
+    if (hasVal)
+      **this = y;
+    else {
+      new (storage.buffer) T(y);
+      hasVal = true;
+    }
+    return *this;
+  }
+
+  Optional &operator=(const Optional &O) {
+    if (!O)
+      reset();
+    else
+      *this = *O;
+    return *this;
+  }
+
+  void reset() {
+    if (hasVal) {
+      (**this).~T();
+      hasVal = false;
+    }
+  }
+
+  ~Optional() {
+    reset();
+  }
+
+  const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
+  T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
+  const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
+  T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
+
+  explicit operator bool() const { return hasVal; }
+  bool hasValue() const { return hasVal; }
+  const T* operator->() const { return getPointer(); }
+  T* operator->() { return getPointer(); }
+  const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
+  T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
+
+  template <typename U>
+  LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
+    return hasValue() ? getValue() : std::forward<U>(value);
+  }
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+  T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
+  T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
+
+  template <typename U>
+  T getValueOr(U &&value) && {
+    return hasValue() ? std::move(getValue()) : std::forward<U>(value);
+  }
+#endif
+};
+
+template <typename T> struct isPodLike;
+template <typename T> struct isPodLike<Optional<T> > {
+  // An Optional<T> is pod-like if T is.
+  static const bool value = isPodLike<T>::value;
+};
+
+template <typename T, typename U>
+bool operator==(const Optional<T> &X, const Optional<U> &Y) {
+  if (X && Y)
+    return *X == *Y;
+  return X.hasValue() == Y.hasValue();
+}
+
+template <typename T, typename U>
+bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
+  return !(X == Y);
+}
+
+template <typename T, typename U>
+bool operator<(const Optional<T> &X, const Optional<U> &Y) {
+  if (X && Y)
+    return *X < *Y;
+  return X.hasValue() < Y.hasValue();
+}
+
+template <typename T, typename U>
+bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
+  return !(Y < X);
+}
+
+template <typename T, typename U>
+bool operator>(const Optional<T> &X, const Optional<U> &Y) {
+  return Y < X;
+}
+
+template <typename T, typename U>
+bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
+  return !(X < Y);
+}
+
+template<typename T>
+bool operator==(const Optional<T> &X, NoneType) {
+  return !X;
+}
+
+template<typename T>
+bool operator==(NoneType, const Optional<T> &X) {
+  return X == None;
+}
+
+template<typename T>
+bool operator!=(const Optional<T> &X, NoneType) {
+  return !(X == None);
+}
+
+template<typename T>
+bool operator!=(NoneType, const Optional<T> &X) {
+  return X != None;
+}
+
+template <typename T> bool operator<(const Optional<T> &X, NoneType) {
+  return false;
+}
+
+template <typename T> bool operator<(NoneType, const Optional<T> &X) {
+  return X.hasValue();
+}
+
+template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
+  return !(None < X);
+}
+
+template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
+  return !(X < None);
+}
+
+template <typename T> bool operator>(const Optional<T> &X, NoneType) {
+  return None < X;
+}
+
+template <typename T> bool operator>(NoneType, const Optional<T> &X) {
+  return X < None;
+}
+
+template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
+  return None <= X;
+}
+
+template <typename T> bool operator>=(NoneType, const Optional<T> &X) {
+  return X <= None;
+}
+
+template <typename T> bool operator==(const Optional<T> &X, const T &Y) {
+  return X && *X == Y;
+}
+
+template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
+  return Y && X == *Y;
+}
+
+template <typename T> bool operator!=(const Optional<T> &X, const T &Y) {
+  return !(X == Y);
+}
+
+template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
+  return !(X == Y);
+}
+
+template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
+  return !X || *X < Y;
+}
+
+template <typename T> bool operator<(const T &X, const Optional<T> &Y) {
+  return Y && X < *Y;
+}
+
+template <typename T> bool operator<=(const Optional<T> &X, const T &Y) {
+  return !(Y < X);
+}
+
+template <typename T> bool operator<=(const T &X, const Optional<T> &Y) {
+  return !(Y < X);
+}
+
+template <typename T> bool operator>(const Optional<T> &X, const T &Y) {
+  return Y < X;
+}
+
+template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
+  return Y < X;
+}
+
+template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
+  return !(X < Y);
+}
+
+template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
+  return !(X < Y);
+}
+
+} // end llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/PointerIntPair.h b/third_party/llvm-subzero/include/llvm/ADT/PointerIntPair.h
new file mode 100644
index 0000000..83fbf12
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/PointerIntPair.h
@@ -0,0 +1,223 @@
+//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PointerIntPair class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_POINTERINTPAIR_H
+#define LLVM_ADT_POINTERINTPAIR_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <limits>
+
+namespace llvm {
+
+template <typename T> struct DenseMapInfo;
+
+template <typename PointerT, unsigned IntBits, typename PtrTraits>
+struct PointerIntPairInfo;
+
+/// PointerIntPair - This class implements a pair of a pointer and small
+/// integer.  It is designed to represent this in the space required by one
+/// pointer by bitmangling the integer into the low part of the pointer.  This
+/// can only be done for small integers: typically up to 3 bits, but it depends
+/// on the number of bits available according to PointerLikeTypeTraits for the
+/// type.
+///
+/// Note that PointerIntPair always puts the IntVal part in the highest bits
+/// possible.  For example, PointerIntPair<void*, 1, bool> will put the bit for
+/// the bool into bit #2, not bit #0, which allows the low two bits to be used
+/// for something else.  For example, this allows:
+///   PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool>
+/// ... and the two bools will land in different bits.
+///
+template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
+          typename PtrTraits = PointerLikeTypeTraits<PointerTy>,
+          typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>>
+class PointerIntPair {
+  intptr_t Value;
+
+public:
+  PointerIntPair() : Value(0) {}
+  PointerIntPair(PointerTy PtrVal, IntType IntVal) {
+    setPointerAndInt(PtrVal, IntVal);
+  }
+  explicit PointerIntPair(PointerTy PtrVal) { initWithPointer(PtrVal); }
+
+  PointerTy getPointer() const { return Info::getPointer(Value); }
+
+  IntType getInt() const {
+    return (IntType)Info::getInt(Value);
+  }
+
+  void setPointer(PointerTy PtrVal) {
+    Value = Info::updatePointer(Value, PtrVal);
+  }
+
+  void setInt(IntType IntVal) {
+    Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal));
+  }
+
+  void initWithPointer(PointerTy PtrVal) {
+    Value = Info::updatePointer(0, PtrVal);
+  }
+
+  void setPointerAndInt(PointerTy PtrVal, IntType IntVal) {
+    Value = Info::updateInt(Info::updatePointer(0, PtrVal),
+                            static_cast<intptr_t>(IntVal));
+  }
+
+  PointerTy const *getAddrOfPointer() const {
+    return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
+  }
+
+  PointerTy *getAddrOfPointer() {
+    assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
+           "Can only return the address if IntBits is cleared and "
+           "PtrTraits doesn't change the pointer");
+    return reinterpret_cast<PointerTy *>(&Value);
+  }
+
+  void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); }
+  void setFromOpaqueValue(void *Val) {
+    Value = reinterpret_cast<intptr_t>(Val);
+  }
+
+  static PointerIntPair getFromOpaqueValue(void *V) {
+    PointerIntPair P;
+    P.setFromOpaqueValue(V);
+    return P;
+  }
+
+  // Allow PointerIntPairs to be created from const void * if and only if the
+  // pointer type could be created from a const void *.
+  static PointerIntPair getFromOpaqueValue(const void *V) {
+    (void)PtrTraits::getFromVoidPointer(V);
+    return getFromOpaqueValue(const_cast<void *>(V));
+  }
+
+  bool operator==(const PointerIntPair &RHS) const {
+    return Value == RHS.Value;
+  }
+  bool operator!=(const PointerIntPair &RHS) const {
+    return Value != RHS.Value;
+  }
+  bool operator<(const PointerIntPair &RHS) const { return Value < RHS.Value; }
+  bool operator>(const PointerIntPair &RHS) const { return Value > RHS.Value; }
+  bool operator<=(const PointerIntPair &RHS) const {
+    return Value <= RHS.Value;
+  }
+  bool operator>=(const PointerIntPair &RHS) const {
+    return Value >= RHS.Value;
+  }
+};
+
+template <typename PointerT, unsigned IntBits, typename PtrTraits>
+struct PointerIntPairInfo {
+  static_assert(PtrTraits::NumLowBitsAvailable <
+                    std::numeric_limits<uintptr_t>::digits,
+                "cannot use a pointer type that has all bits free");
+  static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
+                "PointerIntPair with integer size too large for pointer");
+  enum : uintptr_t {
+    /// PointerBitMask - The bits that come from the pointer.
+    PointerBitMask =
+        ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1),
+
+    /// IntShift - The number of low bits that we reserve for other uses, and
+    /// keep zero.
+    IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable - IntBits,
+
+    /// IntMask - This is the unshifted mask for valid bits of the int type.
+    IntMask = (uintptr_t)(((intptr_t)1 << IntBits) - 1),
+
+    // ShiftedIntMask - This is the bits for the integer shifted in place.
+    ShiftedIntMask = (uintptr_t)(IntMask << IntShift)
+  };
+
+  static PointerT getPointer(intptr_t Value) {
+    return PtrTraits::getFromVoidPointer(
+        reinterpret_cast<void *>(Value & PointerBitMask));
+  }
+
+  static intptr_t getInt(intptr_t Value) {
+    return (Value >> IntShift) & IntMask;
+  }
+
+  static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr) {
+    intptr_t PtrWord =
+        reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr));
+    assert((PtrWord & ~PointerBitMask) == 0 &&
+           "Pointer is not sufficiently aligned");
+    // Preserve all low bits, just update the pointer.
+    return PtrWord | (OrigValue & ~PointerBitMask);
+  }
+
+  static intptr_t updateInt(intptr_t OrigValue, intptr_t Int) {
+    intptr_t IntWord = static_cast<intptr_t>(Int);
+    assert((IntWord & ~IntMask) == 0 && "Integer too large for field");
+
+    // Preserve all bits other than the ones we are updating.
+    return (OrigValue & ~ShiftedIntMask) | IntWord << IntShift;
+  }
+};
+
+template <typename T> struct isPodLike;
+template <typename PointerTy, unsigned IntBits, typename IntType>
+struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType>> {
+  static const bool value = true;
+};
+
+// Provide specialization of DenseMapInfo for PointerIntPair.
+template <typename PointerTy, unsigned IntBits, typename IntType>
+struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> {
+  typedef PointerIntPair<PointerTy, IntBits, IntType> Ty;
+  static Ty getEmptyKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable;
+    return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
+  }
+  static Ty getTombstoneKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-2);
+    Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
+    return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
+  }
+  static unsigned getHashValue(Ty V) {
+    uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
+    return unsigned(IV) ^ unsigned(IV >> 9);
+  }
+  static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
+};
+
+// Teach SmallPtrSet that PointerIntPair is "basically a pointer".
+template <typename PointerTy, unsigned IntBits, typename IntType,
+          typename PtrTraits>
+class PointerLikeTypeTraits<
+    PointerIntPair<PointerTy, IntBits, IntType, PtrTraits>> {
+public:
+  static inline void *
+  getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) {
+    return P.getOpaqueValue();
+  }
+  static inline PointerIntPair<PointerTy, IntBits, IntType>
+  getFromVoidPointer(void *P) {
+    return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
+  }
+  static inline PointerIntPair<PointerTy, IntBits, IntType>
+  getFromVoidPointer(const void *P) {
+    return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
+  }
+  enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits };
+};
+
+} // end namespace llvm
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/PointerUnion.h b/third_party/llvm-subzero/include/llvm/ADT/PointerUnion.h
new file mode 100644
index 0000000..6b3fe57
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/PointerUnion.h
@@ -0,0 +1,474 @@
+//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PointerUnion class, which is a discriminated union of
+// pointer types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_POINTERUNION_H
+#define LLVM_ADT_POINTERUNION_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+template <typename T> struct PointerUnionTypeSelectorReturn {
+  typedef T Return;
+};
+
+/// Get a type based on whether two types are the same or not.
+///
+/// For:
+/// 
+/// \code
+///   typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
+/// \endcode
+///
+/// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
+template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
+struct PointerUnionTypeSelector {
+  typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
+};
+
+template <typename T, typename RET_EQ, typename RET_NE>
+struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
+  typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
+};
+
+template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
+struct PointerUnionTypeSelectorReturn<
+    PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> {
+  typedef
+      typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return Return;
+};
+
+/// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
+/// for the two template arguments.
+template <typename PT1, typename PT2> class PointerUnionUIntTraits {
+public:
+  static inline void *getAsVoidPointer(void *P) { return P; }
+  static inline void *getFromVoidPointer(void *P) { return P; }
+  enum {
+    PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
+    PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
+    NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
+  };
+};
+
+/// A discriminated union of two pointer types, with the discriminator in the
+/// low bit of the pointer.
+///
+/// This implementation is extremely efficient in space due to leveraging the
+/// low bits of the pointer, while exposing a natural and type-safe API.
+///
+/// Common use patterns would be something like this:
+///    PointerUnion<int*, float*> P;
+///    P = (int*)0;
+///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
+///    X = P.get<int*>();     // ok.
+///    Y = P.get<float*>();   // runtime assertion failure.
+///    Z = P.get<double*>();  // compile time failure.
+///    P = (float*)0;
+///    Y = P.get<float*>();   // ok.
+///    X = P.get<int*>();     // runtime assertion failure.
+template <typename PT1, typename PT2> class PointerUnion {
+public:
+  typedef PointerIntPair<void *, 1, bool, PointerUnionUIntTraits<PT1, PT2>>
+      ValTy;
+
+private:
+  ValTy Val;
+
+  struct IsPT1 {
+    static const int Num = 0;
+  };
+  struct IsPT2 {
+    static const int Num = 1;
+  };
+  template <typename T> struct UNION_DOESNT_CONTAIN_TYPE {};
+
+public:
+  PointerUnion() {}
+
+  PointerUnion(PT1 V)
+      : Val(const_cast<void *>(
+            PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {}
+  PointerUnion(PT2 V)
+      : Val(const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)),
+            1) {}
+
+  /// Test if the pointer held in the union is null, regardless of
+  /// which type it is.
+  bool isNull() const {
+    // Convert from the void* to one of the pointer types, to make sure that
+    // we recursively strip off low bits if we have a nested PointerUnion.
+    return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
+  }
+  explicit operator bool() const { return !isNull(); }
+
+  /// Test if the Union currently holds the type matching T.
+  template <typename T> int is() const {
+    typedef typename ::llvm::PointerUnionTypeSelector<
+        PT1, T, IsPT1, ::llvm::PointerUnionTypeSelector<
+                           PT2, T, IsPT2, UNION_DOESNT_CONTAIN_TYPE<T>>>::Return
+        Ty;
+    int TyNo = Ty::Num;
+    return static_cast<int>(Val.getInt()) == TyNo;
+  }
+
+  /// Returns the value of the specified pointer type.
+  ///
+  /// If the specified pointer type is incorrect, assert.
+  template <typename T> T get() const {
+    assert(is<T>() && "Invalid accessor called");
+    return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
+  }
+
+  /// Returns the current pointer if it is of the specified pointer type,
+  /// otherwises returns null.
+  template <typename T> T dyn_cast() const {
+    if (is<T>())
+      return get<T>();
+    return T();
+  }
+
+  /// If the union is set to the first pointer type get an address pointing to
+  /// it.
+  PT1 const *getAddrOfPtr1() const {
+    return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
+  }
+
+  /// If the union is set to the first pointer type get an address pointing to
+  /// it.
+  PT1 *getAddrOfPtr1() {
+    assert(is<PT1>() && "Val is not the first pointer");
+    assert(
+        get<PT1>() == Val.getPointer() &&
+        "Can't get the address because PointerLikeTypeTraits changes the ptr");
+    return (PT1 *)Val.getAddrOfPointer();
+  }
+
+  /// Assignment from nullptr which just clears the union.
+  const PointerUnion &operator=(std::nullptr_t) {
+    Val.initWithPointer(nullptr);
+    return *this;
+  }
+
+  /// Assignment operators - Allow assigning into this union from either
+  /// pointer type, setting the discriminator to remember what it came from.
+  const PointerUnion &operator=(const PT1 &RHS) {
+    Val.initWithPointer(
+        const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
+    return *this;
+  }
+  const PointerUnion &operator=(const PT2 &RHS) {
+    Val.setPointerAndInt(
+        const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
+        1);
+    return *this;
+  }
+
+  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
+  static inline PointerUnion getFromOpaqueValue(void *VP) {
+    PointerUnion V;
+    V.Val = ValTy::getFromOpaqueValue(VP);
+    return V;
+  }
+};
+
+template <typename PT1, typename PT2>
+static bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
+  return lhs.getOpaqueValue() == rhs.getOpaqueValue();
+}
+
+template <typename PT1, typename PT2>
+static bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
+  return lhs.getOpaqueValue() != rhs.getOpaqueValue();
+}
+
+template <typename PT1, typename PT2>
+static bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
+  return lhs.getOpaqueValue() < rhs.getOpaqueValue();
+}
+
+// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
+// # low bits available = min(PT1bits,PT2bits)-1.
+template <typename PT1, typename PT2>
+class PointerLikeTypeTraits<PointerUnion<PT1, PT2>> {
+public:
+  static inline void *getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
+    return P.getOpaqueValue();
+  }
+  static inline PointerUnion<PT1, PT2> getFromVoidPointer(void *P) {
+    return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
+  }
+
+  // The number of bits available are the min of the two pointer types.
+  enum {
+    NumLowBitsAvailable = PointerLikeTypeTraits<
+        typename PointerUnion<PT1, PT2>::ValTy>::NumLowBitsAvailable
+  };
+};
+
+/// A pointer union of three pointer types. See documentation for PointerUnion
+/// for usage.
+template <typename PT1, typename PT2, typename PT3> class PointerUnion3 {
+public:
+  typedef PointerUnion<PT1, PT2> InnerUnion;
+  typedef PointerUnion<InnerUnion, PT3> ValTy;
+
+private:
+  ValTy Val;
+
+  struct IsInnerUnion {
+    ValTy Val;
+    IsInnerUnion(ValTy val) : Val(val) {}
+    template <typename T> int is() const {
+      return Val.template is<InnerUnion>() &&
+             Val.template get<InnerUnion>().template is<T>();
+    }
+    template <typename T> T get() const {
+      return Val.template get<InnerUnion>().template get<T>();
+    }
+  };
+
+  struct IsPT3 {
+    ValTy Val;
+    IsPT3(ValTy val) : Val(val) {}
+    template <typename T> int is() const { return Val.template is<T>(); }
+    template <typename T> T get() const { return Val.template get<T>(); }
+  };
+
+public:
+  PointerUnion3() {}
+
+  PointerUnion3(PT1 V) { Val = InnerUnion(V); }
+  PointerUnion3(PT2 V) { Val = InnerUnion(V); }
+  PointerUnion3(PT3 V) { Val = V; }
+
+  /// Test if the pointer held in the union is null, regardless of
+  /// which type it is.
+  bool isNull() const { return Val.isNull(); }
+  explicit operator bool() const { return !isNull(); }
+
+  /// Test if the Union currently holds the type matching T.
+  template <typename T> int is() const {
+    // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
+    typedef typename ::llvm::PointerUnionTypeSelector<
+        PT1, T, IsInnerUnion,
+        ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return
+        Ty;
+    return Ty(Val).template is<T>();
+  }
+
+  /// Returns the value of the specified pointer type.
+  ///
+  /// If the specified pointer type is incorrect, assert.
+  template <typename T> T get() const {
+    assert(is<T>() && "Invalid accessor called");
+    // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
+    typedef typename ::llvm::PointerUnionTypeSelector<
+        PT1, T, IsInnerUnion,
+        ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return
+        Ty;
+    return Ty(Val).template get<T>();
+  }
+
+  /// Returns the current pointer if it is of the specified pointer type,
+  /// otherwises returns null.
+  template <typename T> T dyn_cast() const {
+    if (is<T>())
+      return get<T>();
+    return T();
+  }
+
+  /// Assignment from nullptr which just clears the union.
+  const PointerUnion3 &operator=(std::nullptr_t) {
+    Val = nullptr;
+    return *this;
+  }
+
+  /// Assignment operators - Allow assigning into this union from either
+  /// pointer type, setting the discriminator to remember what it came from.
+  const PointerUnion3 &operator=(const PT1 &RHS) {
+    Val = InnerUnion(RHS);
+    return *this;
+  }
+  const PointerUnion3 &operator=(const PT2 &RHS) {
+    Val = InnerUnion(RHS);
+    return *this;
+  }
+  const PointerUnion3 &operator=(const PT3 &RHS) {
+    Val = RHS;
+    return *this;
+  }
+
+  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
+  static inline PointerUnion3 getFromOpaqueValue(void *VP) {
+    PointerUnion3 V;
+    V.Val = ValTy::getFromOpaqueValue(VP);
+    return V;
+  }
+};
+
+// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
+// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
+template <typename PT1, typename PT2, typename PT3>
+class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3>> {
+public:
+  static inline void *getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
+    return P.getOpaqueValue();
+  }
+  static inline PointerUnion3<PT1, PT2, PT3> getFromVoidPointer(void *P) {
+    return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
+  }
+
+  // The number of bits available are the min of the two pointer types.
+  enum {
+    NumLowBitsAvailable = PointerLikeTypeTraits<
+        typename PointerUnion3<PT1, PT2, PT3>::ValTy>::NumLowBitsAvailable
+  };
+};
+
+/// A pointer union of four pointer types. See documentation for PointerUnion
+/// for usage.
+template <typename PT1, typename PT2, typename PT3, typename PT4>
+class PointerUnion4 {
+public:
+  typedef PointerUnion<PT1, PT2> InnerUnion1;
+  typedef PointerUnion<PT3, PT4> InnerUnion2;
+  typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
+
+private:
+  ValTy Val;
+
+public:
+  PointerUnion4() {}
+
+  PointerUnion4(PT1 V) { Val = InnerUnion1(V); }
+  PointerUnion4(PT2 V) { Val = InnerUnion1(V); }
+  PointerUnion4(PT3 V) { Val = InnerUnion2(V); }
+  PointerUnion4(PT4 V) { Val = InnerUnion2(V); }
+
+  /// Test if the pointer held in the union is null, regardless of
+  /// which type it is.
+  bool isNull() const { return Val.isNull(); }
+  explicit operator bool() const { return !isNull(); }
+
+  /// Test if the Union currently holds the type matching T.
+  template <typename T> int is() const {
+    // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
+    typedef typename ::llvm::PointerUnionTypeSelector<
+        PT1, T, InnerUnion1, ::llvm::PointerUnionTypeSelector<
+                                 PT2, T, InnerUnion1, InnerUnion2>>::Return Ty;
+    return Val.template is<Ty>() && Val.template get<Ty>().template is<T>();
+  }
+
+  /// Returns the value of the specified pointer type.
+  ///
+  /// If the specified pointer type is incorrect, assert.
+  template <typename T> T get() const {
+    assert(is<T>() && "Invalid accessor called");
+    // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
+    typedef typename ::llvm::PointerUnionTypeSelector<
+        PT1, T, InnerUnion1, ::llvm::PointerUnionTypeSelector<
+                                 PT2, T, InnerUnion1, InnerUnion2>>::Return Ty;
+    return Val.template get<Ty>().template get<T>();
+  }
+
+  /// Returns the current pointer if it is of the specified pointer type,
+  /// otherwises returns null.
+  template <typename T> T dyn_cast() const {
+    if (is<T>())
+      return get<T>();
+    return T();
+  }
+
+  /// Assignment from nullptr which just clears the union.
+  const PointerUnion4 &operator=(std::nullptr_t) {
+    Val = nullptr;
+    return *this;
+  }
+
+  /// Assignment operators - Allow assigning into this union from either
+  /// pointer type, setting the discriminator to remember what it came from.
+  const PointerUnion4 &operator=(const PT1 &RHS) {
+    Val = InnerUnion1(RHS);
+    return *this;
+  }
+  const PointerUnion4 &operator=(const PT2 &RHS) {
+    Val = InnerUnion1(RHS);
+    return *this;
+  }
+  const PointerUnion4 &operator=(const PT3 &RHS) {
+    Val = InnerUnion2(RHS);
+    return *this;
+  }
+  const PointerUnion4 &operator=(const PT4 &RHS) {
+    Val = InnerUnion2(RHS);
+    return *this;
+  }
+
+  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
+  static inline PointerUnion4 getFromOpaqueValue(void *VP) {
+    PointerUnion4 V;
+    V.Val = ValTy::getFromOpaqueValue(VP);
+    return V;
+  }
+};
+
+// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
+// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
+template <typename PT1, typename PT2, typename PT3, typename PT4>
+class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4>> {
+public:
+  static inline void *
+  getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
+    return P.getOpaqueValue();
+  }
+  static inline PointerUnion4<PT1, PT2, PT3, PT4> getFromVoidPointer(void *P) {
+    return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
+  }
+
+  // The number of bits available are the min of the two pointer types.
+  enum {
+    NumLowBitsAvailable = PointerLikeTypeTraits<
+        typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>::NumLowBitsAvailable
+  };
+};
+
+// Teach DenseMap how to use PointerUnions as keys.
+template <typename T, typename U> struct DenseMapInfo<PointerUnion<T, U>> {
+  typedef PointerUnion<T, U> Pair;
+  typedef DenseMapInfo<T> FirstInfo;
+  typedef DenseMapInfo<U> SecondInfo;
+
+  static inline Pair getEmptyKey() { return Pair(FirstInfo::getEmptyKey()); }
+  static inline Pair getTombstoneKey() {
+    return Pair(FirstInfo::getTombstoneKey());
+  }
+  static unsigned getHashValue(const Pair &PairVal) {
+    intptr_t key = (intptr_t)PairVal.getOpaqueValue();
+    return DenseMapInfo<intptr_t>::getHashValue(key);
+  }
+  static bool isEqual(const Pair &LHS, const Pair &RHS) {
+    return LHS.template is<T>() == RHS.template is<T>() &&
+           (LHS.template is<T>() ? FirstInfo::isEqual(LHS.template get<T>(),
+                                                      RHS.template get<T>())
+                                 : SecondInfo::isEqual(LHS.template get<U>(),
+                                                       RHS.template get<U>()));
+  }
+};
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/STLExtras.h b/third_party/llvm-subzero/include/llvm/ADT/STLExtras.h
new file mode 100644
index 0000000..e6215e4
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/STLExtras.h
@@ -0,0 +1,631 @@
+//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some templates that are useful if you are working with the
+// STL at all.
+//
+// No library is required when using these functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STLEXTRAS_H
+#define LLVM_ADT_STLEXTRAS_H
+
+#include <algorithm> // for std::all_of
+#include <cassert>
+#include <cstddef> // for std::size_t
+#include <cstdlib> // for qsort
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <utility> // for std::pair
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+namespace detail {
+
+template <typename RangeT>
+using IterOfRange = decltype(std::begin(std::declval<RangeT>()));
+
+} // End detail namespace
+
+//===----------------------------------------------------------------------===//
+//     Extra additions to <functional>
+//===----------------------------------------------------------------------===//
+
+template<class Ty>
+struct identity : public std::unary_function<Ty, Ty> {
+  Ty &operator()(Ty &self) const {
+    return self;
+  }
+  const Ty &operator()(const Ty &self) const {
+    return self;
+  }
+};
+
+template<class Ty>
+struct less_ptr : public std::binary_function<Ty, Ty, bool> {
+  bool operator()(const Ty* left, const Ty* right) const {
+    return *left < *right;
+  }
+};
+
+template<class Ty>
+struct greater_ptr : public std::binary_function<Ty, Ty, bool> {
+  bool operator()(const Ty* left, const Ty* right) const {
+    return *right < *left;
+  }
+};
+
+/// An efficient, type-erasing, non-owning reference to a callable. This is
+/// intended for use as the type of a function parameter that is not used
+/// after the function in question returns.
+///
+/// This class does not own the callable, so it is not in general safe to store
+/// a function_ref.
+template<typename Fn> class function_ref;
+
+template<typename Ret, typename ...Params>
+class function_ref<Ret(Params...)> {
+  Ret (*callback)(intptr_t callable, Params ...params);
+  intptr_t callable;
+
+  template<typename Callable>
+  static Ret callback_fn(intptr_t callable, Params ...params) {
+    return (*reinterpret_cast<Callable*>(callable))(
+        std::forward<Params>(params)...);
+  }
+
+public:
+  template <typename Callable>
+  function_ref(Callable &&callable,
+               typename std::enable_if<
+                   !std::is_same<typename std::remove_reference<Callable>::type,
+                                 function_ref>::value>::type * = nullptr)
+      : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+        callable(reinterpret_cast<intptr_t>(&callable)) {}
+  Ret operator()(Params ...params) const {
+    return callback(callable, std::forward<Params>(params)...);
+  }
+};
+
+// deleter - Very very very simple method that is used to invoke operator
+// delete on something.  It is used like this:
+//
+//   for_each(V.begin(), B.end(), deleter<Interval>);
+//
+template <class T>
+inline void deleter(T *Ptr) {
+  delete Ptr;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//     Extra additions to <iterator>
+//===----------------------------------------------------------------------===//
+
+// mapped_iterator - This is a simple iterator adapter that causes a function to
+// be dereferenced whenever operator* is invoked on the iterator.
+//
+template <class RootIt, class UnaryFunc>
+class mapped_iterator {
+  RootIt current;
+  UnaryFunc Fn;
+public:
+  typedef typename std::iterator_traits<RootIt>::iterator_category
+          iterator_category;
+  typedef typename std::iterator_traits<RootIt>::difference_type
+          difference_type;
+  typedef typename std::result_of<
+            UnaryFunc(decltype(*std::declval<RootIt>()))>
+          ::type value_type;
+
+  typedef void pointer;
+  //typedef typename UnaryFunc::result_type *pointer;
+  typedef void reference;        // Can't modify value returned by fn
+
+  typedef RootIt iterator_type;
+
+  inline const RootIt &getCurrent() const { return current; }
+  inline const UnaryFunc &getFunc() const { return Fn; }
+
+  inline explicit mapped_iterator(const RootIt &I, UnaryFunc F)
+    : current(I), Fn(F) {}
+
+  inline value_type operator*() const {   // All this work to do this
+    return Fn(*current);         // little change
+  }
+
+  mapped_iterator &operator++() {
+    ++current;
+    return *this;
+  }
+  mapped_iterator &operator--() {
+    --current;
+    return *this;
+  }
+  mapped_iterator operator++(int) {
+    mapped_iterator __tmp = *this;
+    ++current;
+    return __tmp;
+  }
+  mapped_iterator operator--(int) {
+    mapped_iterator __tmp = *this;
+    --current;
+    return __tmp;
+  }
+  mapped_iterator operator+(difference_type n) const {
+    return mapped_iterator(current + n, Fn);
+  }
+  mapped_iterator &operator+=(difference_type n) {
+    current += n;
+    return *this;
+  }
+  mapped_iterator operator-(difference_type n) const {
+    return mapped_iterator(current - n, Fn);
+  }
+  mapped_iterator &operator-=(difference_type n) {
+    current -= n;
+    return *this;
+  }
+  reference operator[](difference_type n) const { return *(*this + n); }
+
+  bool operator!=(const mapped_iterator &X) const { return !operator==(X); }
+  bool operator==(const mapped_iterator &X) const {
+    return current == X.current;
+  }
+  bool operator<(const mapped_iterator &X) const { return current < X.current; }
+
+  difference_type operator-(const mapped_iterator &X) const {
+    return current - X.current;
+  }
+};
+
+template <class Iterator, class Func>
+inline mapped_iterator<Iterator, Func>
+operator+(typename mapped_iterator<Iterator, Func>::difference_type N,
+          const mapped_iterator<Iterator, Func> &X) {
+  return mapped_iterator<Iterator, Func>(X.getCurrent() - N, X.getFunc());
+}
+
+
+// map_iterator - Provide a convenient way to create mapped_iterators, just like
+// make_pair is useful for creating pairs...
+//
+template <class ItTy, class FuncTy>
+inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) {
+  return mapped_iterator<ItTy, FuncTy>(I, F);
+}
+
+/// Helper to determine if type T has a member called rbegin().
+template <typename Ty> class has_rbegin_impl {
+  typedef char yes[1];
+  typedef char no[2];
+
+  template <typename Inner>
+  static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
+
+  template <typename>
+  static no& test(...);
+
+public:
+  static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
+};
+
+/// Metafunction to determine if T& or T has a member called rbegin().
+template <typename Ty>
+struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> {
+};
+
+// Returns an iterator_range over the given container which iterates in reverse.
+// Note that the container must have rbegin()/rend() methods for this to work.
+template <typename ContainerTy>
+auto reverse(ContainerTy &&C,
+             typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
+                 nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
+  return make_range(C.rbegin(), C.rend());
+}
+
+// Returns a std::reverse_iterator wrapped around the given iterator.
+template <typename IteratorTy>
+std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
+  return std::reverse_iterator<IteratorTy>(It);
+}
+
+// Returns an iterator_range over the given container which iterates in reverse.
+// Note that the container must have begin()/end() methods which return
+// bidirectional iterators for this to work.
+template <typename ContainerTy>
+auto reverse(
+    ContainerTy &&C,
+    typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
+    -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
+                           llvm::make_reverse_iterator(std::begin(C)))) {
+  return make_range(llvm::make_reverse_iterator(std::end(C)),
+                    llvm::make_reverse_iterator(std::begin(C)));
+}
+
+/// An iterator adaptor that filters the elements of given inner iterators.
+///
+/// The predicate parameter should be a callable object that accepts the wrapped
+/// iterator's reference type and returns a bool. When incrementing or
+/// decrementing the iterator, it will call the predicate on each element and
+/// skip any where it returns false.
+///
+/// \code
+///   int A[] = { 1, 2, 3, 4 };
+///   auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
+///   // R contains { 1, 3 }.
+/// \endcode
+template <typename WrappedIteratorT, typename PredicateT>
+class filter_iterator
+    : public iterator_adaptor_base<
+          filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT,
+          typename std::common_type<
+              std::forward_iterator_tag,
+              typename std::iterator_traits<
+                  WrappedIteratorT>::iterator_category>::type> {
+  using BaseT = iterator_adaptor_base<
+      filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT,
+      typename std::common_type<
+          std::forward_iterator_tag,
+          typename std::iterator_traits<WrappedIteratorT>::iterator_category>::
+          type>;
+
+  struct PayloadType {
+    WrappedIteratorT End;
+    PredicateT Pred;
+  };
+
+  Optional<PayloadType> Payload;
+
+  void findNextValid() {
+    assert(Payload && "Payload should be engaged when findNextValid is called");
+    while (this->I != Payload->End && !Payload->Pred(*this->I))
+      BaseT::operator++();
+  }
+
+  // Construct the begin iterator. The begin iterator requires to know where end
+  // is, so that it can properly stop when it hits end.
+  filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
+      : BaseT(std::move(Begin)),
+        Payload(PayloadType{std::move(End), std::move(Pred)}) {
+    findNextValid();
+  }
+
+  // Construct the end iterator. It's not incrementable, so Payload doesn't
+  // have to be engaged.
+  filter_iterator(WrappedIteratorT End) : BaseT(End) {}
+
+public:
+  using BaseT::operator++;
+
+  filter_iterator &operator++() {
+    BaseT::operator++();
+    findNextValid();
+    return *this;
+  }
+
+  template <typename RT, typename PT>
+  friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>>
+  make_filter_range(RT &&, PT);
+};
+
+/// Convenience function that takes a range of elements and a predicate,
+/// and return a new filter_iterator range.
+///
+/// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
+/// lifetime of that temporary is not kept by the returned range object, and the
+/// temporary is going to be dropped on the floor after the make_iterator_range
+/// full expression that contains this function call.
+template <typename RangeT, typename PredicateT>
+iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
+make_filter_range(RangeT &&Range, PredicateT Pred) {
+  using FilterIteratorT =
+      filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
+  return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
+                                    std::end(std::forward<RangeT>(Range)),
+                                    std::move(Pred)),
+                    FilterIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
+//===----------------------------------------------------------------------===//
+//     Extra additions to <utility>
+//===----------------------------------------------------------------------===//
+
+/// \brief Function object to check whether the first component of a std::pair
+/// compares less than the first component of another std::pair.
+struct less_first {
+  template <typename T> bool operator()(const T &lhs, const T &rhs) const {
+    return lhs.first < rhs.first;
+  }
+};
+
+/// \brief Function object to check whether the second component of a std::pair
+/// compares less than the second component of another std::pair.
+struct less_second {
+  template <typename T> bool operator()(const T &lhs, const T &rhs) const {
+    return lhs.second < rhs.second;
+  }
+};
+
+// A subset of N3658. More stuff can be added as-needed.
+
+/// \brief Represents a compile-time sequence of integers.
+template <class T, T... I> struct integer_sequence {
+  typedef T value_type;
+
+  static LLVM_CONSTEXPR size_t size() { return sizeof...(I); }
+};
+
+/// \brief Alias for the common case of a sequence of size_ts.
+template <size_t... I>
+struct index_sequence : integer_sequence<std::size_t, I...> {};
+
+template <std::size_t N, std::size_t... I>
+struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {};
+template <std::size_t... I>
+struct build_index_impl<0, I...> : index_sequence<I...> {};
+
+/// \brief Creates a compile-time integer sequence for a parameter pack.
+template <class... Ts>
+struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
+
+/// Utility type to build an inheritance chain that makes it easy to rank
+/// overload candidates.
+template <int N> struct rank : rank<N - 1> {};
+template <> struct rank<0> {};
+
+//===----------------------------------------------------------------------===//
+//     Extra additions for arrays
+//===----------------------------------------------------------------------===//
+
+/// Find the length of an array.
+template <class T, std::size_t N>
+LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) {
+  return N;
+}
+
+/// Adapt std::less<T> for array_pod_sort.
+template<typename T>
+inline int array_pod_sort_comparator(const void *P1, const void *P2) {
+  if (std::less<T>()(*reinterpret_cast<const T*>(P1),
+                     *reinterpret_cast<const T*>(P2)))
+    return -1;
+  if (std::less<T>()(*reinterpret_cast<const T*>(P2),
+                     *reinterpret_cast<const T*>(P1)))
+    return 1;
+  return 0;
+}
+
+/// get_array_pod_sort_comparator - This is an internal helper function used to
+/// get type deduction of T right.
+template<typename T>
+inline int (*get_array_pod_sort_comparator(const T &))
+             (const void*, const void*) {
+  return array_pod_sort_comparator<T>;
+}
+
+
+/// array_pod_sort - This sorts an array with the specified start and end
+/// extent.  This is just like std::sort, except that it calls qsort instead of
+/// using an inlined template.  qsort is slightly slower than std::sort, but
+/// most sorts are not performance critical in LLVM and std::sort has to be
+/// template instantiated for each type, leading to significant measured code
+/// bloat.  This function should generally be used instead of std::sort where
+/// possible.
+///
+/// This function assumes that you have simple POD-like types that can be
+/// compared with std::less and can be moved with memcpy.  If this isn't true,
+/// you should use std::sort.
+///
+/// NOTE: If qsort_r were portable, we could allow a custom comparator and
+/// default to std::less.
+template<class IteratorTy>
+inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
+  // Don't inefficiently call qsort with one element or trigger undefined
+  // behavior with an empty sequence.
+  auto NElts = End - Start;
+  if (NElts <= 1) return;
+  qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
+}
+
+template <class IteratorTy>
+inline void array_pod_sort(
+    IteratorTy Start, IteratorTy End,
+    int (*Compare)(
+        const typename std::iterator_traits<IteratorTy>::value_type *,
+        const typename std::iterator_traits<IteratorTy>::value_type *)) {
+  // Don't inefficiently call qsort with one element or trigger undefined
+  // behavior with an empty sequence.
+  auto NElts = End - Start;
+  if (NElts <= 1) return;
+  qsort(&*Start, NElts, sizeof(*Start),
+        reinterpret_cast<int (*)(const void *, const void *)>(Compare));
+}
+
+//===----------------------------------------------------------------------===//
+//     Extra additions to <algorithm>
+//===----------------------------------------------------------------------===//
+
+/// For a container of pointers, deletes the pointers and then clears the
+/// container.
+template<typename Container>
+void DeleteContainerPointers(Container &C) {
+  for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I)
+    delete *I;
+  C.clear();
+}
+
+/// In a container of pairs (usually a map) whose second element is a pointer,
+/// deletes the second elements and then clears the container.
+template<typename Container>
+void DeleteContainerSeconds(Container &C) {
+  for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I)
+    delete I->second;
+  C.clear();
+}
+
+/// Provide wrappers to std::all_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template<typename R, class UnaryPredicate>
+bool all_of(R &&Range, UnaryPredicate &&P) {
+  return std::all_of(Range.begin(), Range.end(),
+                     std::forward<UnaryPredicate>(P));
+}
+
+/// Provide wrappers to std::any_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, class UnaryPredicate>
+bool any_of(R &&Range, UnaryPredicate &&P) {
+  return std::any_of(Range.begin(), Range.end(),
+                     std::forward<UnaryPredicate>(P));
+}
+
+/// Provide wrappers to std::none_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, class UnaryPredicate>
+bool none_of(R &&Range, UnaryPredicate &&P) {
+  return std::none_of(Range.begin(), Range.end(),
+                      std::forward<UnaryPredicate>(P));
+}
+
+/// Provide wrappers to std::find which take ranges instead of having to pass
+/// begin/end explicitly.
+template<typename R, class T>
+auto find(R &&Range, const T &val) -> decltype(Range.begin()) {
+  return std::find(Range.begin(), Range.end(), val);
+}
+
+/// Provide wrappers to std::find_if which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, class T>
+auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {
+  return std::find_if(Range.begin(), Range.end(), Pred);
+}
+
+/// Provide wrappers to std::remove_if which take ranges instead of having to
+/// pass begin/end explicitly.
+template<typename R, class UnaryPredicate>
+auto remove_if(R &&Range, UnaryPredicate &&P) -> decltype(Range.begin()) {
+  return std::remove_if(Range.begin(), Range.end(), P);
+}
+
+/// Wrapper function around std::find to detect if an element exists
+/// in a container.
+template <typename R, typename E>
+bool is_contained(R &&Range, const E &Element) {
+  return std::find(Range.begin(), Range.end(), Element) != Range.end();
+}
+
+/// Wrapper function around std::count_if to count the number of times an
+/// element satisfying a given predicate occurs in a range.
+template <typename R, typename UnaryPredicate>
+auto count_if(R &&Range, UnaryPredicate &&P)
+    -> typename std::iterator_traits<decltype(Range.begin())>::difference_type {
+  return std::count_if(Range.begin(), Range.end(), P);
+}
+
+/// Wrapper function around std::transform to apply a function to a range and
+/// store the result elsewhere.
+template <typename R, class OutputIt, typename UnaryPredicate>
+OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate &&P) {
+  return std::transform(Range.begin(), Range.end(), d_first,
+                        std::forward<UnaryPredicate>(P));
+}
+
+//===----------------------------------------------------------------------===//
+//     Extra additions to <memory>
+//===----------------------------------------------------------------------===//
+
+// Implement make_unique according to N3656.
+
+/// \brief Constructs a `new T()` with the given args and returns a
+///        `unique_ptr<T>` which owns the object.
+///
+/// Example:
+///
+///     auto p = make_unique<int>();
+///     auto p = make_unique<std::tuple<int, int>>(0, 1);
+template <class T, class... Args>
+typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
+make_unique(Args &&... args) {
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+/// \brief Constructs a `new T[n]` with the given args and returns a
+///        `unique_ptr<T[]>` which owns the object.
+///
+/// \param n size of the new array.
+///
+/// Example:
+///
+///     auto p = make_unique<int[]>(2); // value-initializes the array with 0's.
+template <class T>
+typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0,
+                        std::unique_ptr<T>>::type
+make_unique(size_t n) {
+  return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
+}
+
+/// This function isn't used and is only here to provide better compile errors.
+template <class T, class... Args>
+typename std::enable_if<std::extent<T>::value != 0>::type
+make_unique(Args &&...) = delete;
+
+struct FreeDeleter {
+  void operator()(void* v) {
+    ::free(v);
+  }
+};
+
+template<typename First, typename Second>
+struct pair_hash {
+  size_t operator()(const std::pair<First, Second> &P) const {
+    return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
+  }
+};
+
+/// A functor like C++14's std::less<void> in its absence.
+struct less {
+  template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+    return std::forward<A>(a) < std::forward<B>(b);
+  }
+};
+
+/// A functor like C++14's std::equal<void> in its absence.
+struct equal {
+  template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+    return std::forward<A>(a) == std::forward<B>(b);
+  }
+};
+
+/// Binary functor that adapts to any other binary functor after dereferencing
+/// operands.
+template <typename T> struct deref {
+  T func;
+  // Could be further improved to cope with non-derivable functors and
+  // non-binary functors (should be a variadic template member function
+  // operator()).
+  template <typename A, typename B>
+  auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
+    assert(lhs);
+    assert(rhs);
+    return func(*lhs, *rhs);
+  }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/SmallPtrSet.h b/third_party/llvm-subzero/include/llvm/ADT/SmallPtrSet.h
new file mode 100644
index 0000000..eaed6aa
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/SmallPtrSet.h
@@ -0,0 +1,406 @@
+//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallPtrSet class.  See the doxygen comment for
+// SmallPtrSetImplBase for more details on the algorithm used.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLPTRSET_H
+#define LLVM_ADT_SMALLPTRSET_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <cstdlib>
+#include <iterator>
+#include <utility>
+
+namespace llvm {
+
+class SmallPtrSetIteratorImpl;
+
+/// SmallPtrSetImplBase - This is the common code shared among all the
+/// SmallPtrSet<>'s, which is almost everything.  SmallPtrSet has two modes, one
+/// for small and one for large sets.
+///
+/// Small sets use an array of pointers allocated in the SmallPtrSet object,
+/// which is treated as a simple array of pointers.  When a pointer is added to
+/// the set, the array is scanned to see if the element already exists, if not
+/// the element is 'pushed back' onto the array.  If we run out of space in the
+/// array, we grow into the 'large set' case.  SmallSet should be used when the
+/// sets are often small.  In this case, no memory allocation is used, and only
+/// light-weight and cache-efficient scanning is used.
+///
+/// Large sets use a classic exponentially-probed hash table.  Empty buckets are
+/// represented with an illegal pointer value (-1) to allow null pointers to be
+/// inserted.  Tombstones are represented with another illegal pointer value
+/// (-2), to allow deletion.  The hash table is resized when the table is 3/4 or
+/// more.  When this happens, the table is doubled in size.
+///
+class SmallPtrSetImplBase {
+  friend class SmallPtrSetIteratorImpl;
+
+protected:
+  /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
+  const void **SmallArray;
+  /// CurArray - This is the current set of buckets.  If equal to SmallArray,
+  /// then the set is in 'small mode'.
+  const void **CurArray;
+  /// CurArraySize - The allocated size of CurArray, always a power of two.
+  unsigned CurArraySize;
+
+  /// Number of elements in CurArray that contain a value or are a tombstone.
+  /// If small, all these elements are at the beginning of CurArray and the rest
+  /// is uninitialized.
+  unsigned NumNonEmpty;
+  /// Number of tombstones in CurArray.
+  unsigned NumTombstones;
+
+  // Helpers to copy and move construct a SmallPtrSet.
+  SmallPtrSetImplBase(const void **SmallStorage,
+                      const SmallPtrSetImplBase &that);
+  SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
+                      SmallPtrSetImplBase &&that);
+  explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize)
+      : SmallArray(SmallStorage), CurArray(SmallStorage),
+        CurArraySize(SmallSize), NumNonEmpty(0), NumTombstones(0) {
+    assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
+           "Initial size must be a power of two!");
+  }
+  ~SmallPtrSetImplBase() {
+    if (!isSmall())
+      free(CurArray);
+  }
+
+public:
+  typedef unsigned size_type;
+  bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; }
+  size_type size() const { return NumNonEmpty - NumTombstones; }
+
+  void clear() {
+    // If the capacity of the array is huge, and the # elements used is small,
+    // shrink the array.
+    if (!isSmall()) {
+      if (size() * 4 < CurArraySize && CurArraySize > 32)
+        return shrink_and_clear();
+      // Fill the array with empty markers.
+      memset(CurArray, -1, CurArraySize * sizeof(void *));
+    }
+
+    NumNonEmpty = 0;
+    NumTombstones = 0;
+  }
+
+protected:
+  static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
+  static void *getEmptyMarker() {
+    // Note that -1 is chosen to make clear() efficiently implementable with
+    // memset and because it's not a valid pointer value.
+    return reinterpret_cast<void*>(-1);
+  }
+
+  const void **EndPointer() const {
+    return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize;
+  }
+
+  /// insert_imp - This returns true if the pointer was new to the set, false if
+  /// it was already in the set.  This is hidden from the client so that the
+  /// derived class can check that the right type of pointer is passed in.
+  std::pair<const void *const *, bool> insert_imp(const void *Ptr) {
+    if (isSmall()) {
+      // Check to see if it is already in the set.
+      const void **LastTombstone = nullptr;
+      for (const void **APtr = SmallArray, **E = SmallArray + NumNonEmpty;
+           APtr != E; ++APtr) {
+        const void *Value = *APtr;
+        if (Value == Ptr)
+          return std::make_pair(APtr, false);
+        if (Value == getTombstoneMarker())
+          LastTombstone = APtr;
+      }
+
+      // Did we find any tombstone marker?
+      if (LastTombstone != nullptr) {
+        *LastTombstone = Ptr;
+        --NumTombstones;
+        return std::make_pair(LastTombstone, true);
+      }
+
+      // Nope, there isn't.  If we stay small, just 'pushback' now.
+      if (NumNonEmpty < CurArraySize) {
+        SmallArray[NumNonEmpty++] = Ptr;
+        return std::make_pair(SmallArray + (NumNonEmpty - 1), true);
+      }
+      // Otherwise, hit the big set case, which will call grow.
+    }
+    return insert_imp_big(Ptr);
+  }
+
+  /// erase_imp - If the set contains the specified pointer, remove it and
+  /// return true, otherwise return false.  This is hidden from the client so
+  /// that the derived class can check that the right type of pointer is passed
+  /// in.
+  bool erase_imp(const void * Ptr);
+
+  bool count_imp(const void * Ptr) const {
+    if (isSmall()) {
+      // Linear search for the item.
+      for (const void *const *APtr = SmallArray,
+                      *const *E = SmallArray + NumNonEmpty; APtr != E; ++APtr)
+        if (*APtr == Ptr)
+          return true;
+      return false;
+    }
+
+    // Big set case.
+    return *FindBucketFor(Ptr) == Ptr;
+  }
+
+private:
+  bool isSmall() const { return CurArray == SmallArray; }
+
+  std::pair<const void *const *, bool> insert_imp_big(const void *Ptr);
+
+  const void * const *FindBucketFor(const void *Ptr) const;
+  void shrink_and_clear();
+
+  /// Grow - Allocate a larger backing store for the buckets and move it over.
+  void Grow(unsigned NewSize);
+
+  void operator=(const SmallPtrSetImplBase &RHS) = delete;
+
+protected:
+  /// swap - Swaps the elements of two sets.
+  /// Note: This method assumes that both sets have the same small size.
+  void swap(SmallPtrSetImplBase &RHS);
+
+  void CopyFrom(const SmallPtrSetImplBase &RHS);
+  void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
+
+private:
+  /// Code shared by MoveFrom() and move constructor.
+  void MoveHelper(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
+  /// Code shared by CopyFrom() and copy constructor.
+  void CopyHelper(const SmallPtrSetImplBase &RHS);
+};
+
+/// SmallPtrSetIteratorImpl - This is the common base class shared between all
+/// instances of SmallPtrSetIterator.
+class SmallPtrSetIteratorImpl {
+protected:
+  const void *const *Bucket;
+  const void *const *End;
+
+public:
+  explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
+    : Bucket(BP), End(E) {
+    AdvanceIfNotValid();
+  }
+
+  bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
+    return Bucket == RHS.Bucket;
+  }
+  bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
+    return Bucket != RHS.Bucket;
+  }
+
+protected:
+  /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket
+  /// that is.   This is guaranteed to stop because the end() bucket is marked
+  /// valid.
+  void AdvanceIfNotValid() {
+    assert(Bucket <= End);
+    while (Bucket != End &&
+           (*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
+            *Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
+      ++Bucket;
+  }
+};
+
+/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
+template<typename PtrTy>
+class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
+  typedef PointerLikeTypeTraits<PtrTy> PtrTraits;
+
+public:
+  typedef PtrTy                     value_type;
+  typedef PtrTy                     reference;
+  typedef PtrTy                     pointer;
+  typedef std::ptrdiff_t            difference_type;
+  typedef std::forward_iterator_tag iterator_category;
+
+  explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
+    : SmallPtrSetIteratorImpl(BP, E) {}
+
+  // Most methods provided by baseclass.
+
+  const PtrTy operator*() const {
+    assert(Bucket < End);
+    return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
+  }
+
+  inline SmallPtrSetIterator& operator++() {          // Preincrement
+    ++Bucket;
+    AdvanceIfNotValid();
+    return *this;
+  }
+
+  SmallPtrSetIterator operator++(int) {        // Postincrement
+    SmallPtrSetIterator tmp = *this; ++*this; return tmp;
+  }
+};
+
+/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next
+/// power of two (which means N itself if N is already a power of two).
+template<unsigned N>
+struct RoundUpToPowerOfTwo;
+
+/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it.  This is a
+/// helper template used to implement RoundUpToPowerOfTwo.
+template<unsigned N, bool isPowerTwo>
+struct RoundUpToPowerOfTwoH {
+  enum { Val = N };
+};
+template<unsigned N>
+struct RoundUpToPowerOfTwoH<N, false> {
+  enum {
+    // We could just use NextVal = N+1, but this converges faster.  N|(N-1) sets
+    // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
+    Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
+  };
+};
+
+template<unsigned N>
+struct RoundUpToPowerOfTwo {
+  enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
+};
+
+/// \brief A templated base class for \c SmallPtrSet which provides the
+/// typesafe interface that is common across all small sizes.
+///
+/// This is particularly useful for passing around between interface boundaries
+/// to avoid encoding a particular small size in the interface boundary.
+template <typename PtrType>
+class SmallPtrSetImpl : public SmallPtrSetImplBase {
+  typedef PointerLikeTypeTraits<PtrType> PtrTraits;
+
+  SmallPtrSetImpl(const SmallPtrSetImpl &) = delete;
+
+protected:
+  // Constructors that forward to the base.
+  SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
+      : SmallPtrSetImplBase(SmallStorage, that) {}
+  SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize,
+                  SmallPtrSetImpl &&that)
+      : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {}
+  explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize)
+      : SmallPtrSetImplBase(SmallStorage, SmallSize) {}
+
+public:
+  typedef SmallPtrSetIterator<PtrType> iterator;
+  typedef SmallPtrSetIterator<PtrType> const_iterator;
+
+  /// Inserts Ptr if and only if there is no element in the container equal to
+  /// Ptr. The bool component of the returned pair is true if and only if the
+  /// insertion takes place, and the iterator component of the pair points to
+  /// the element equal to Ptr.
+  std::pair<iterator, bool> insert(PtrType Ptr) {
+    auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
+    return std::make_pair(iterator(p.first, EndPointer()), p.second);
+  }
+
+  /// erase - If the set contains the specified pointer, remove it and return
+  /// true, otherwise return false.
+  bool erase(PtrType Ptr) {
+    return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
+  }
+
+  /// count - Return 1 if the specified pointer is in the set, 0 otherwise.
+  size_type count(PtrType Ptr) const {
+    return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0;
+  }
+
+  template <typename IterT>
+  void insert(IterT I, IterT E) {
+    for (; I != E; ++I)
+      insert(*I);
+  }
+
+  inline iterator begin() const {
+    return iterator(CurArray, EndPointer());
+  }
+  inline iterator end() const {
+    const void *const *End = EndPointer();
+    return iterator(End, End);
+  }
+};
+
+/// SmallPtrSet - This class implements a set which is optimized for holding
+/// SmallSize or less elements.  This internally rounds up SmallSize to the next
+/// power of two if it is not already a power of two.  See the comments above
+/// SmallPtrSetImplBase for details of the algorithm.
+template<class PtrType, unsigned SmallSize>
+class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
+  // In small mode SmallPtrSet uses linear search for the elements, so it is
+  // not a good idea to choose this value too high. You may consider using a
+  // DenseSet<> instead if you expect many elements in the set.
+  static_assert(SmallSize <= 32, "SmallSize should be small");
+
+  typedef SmallPtrSetImpl<PtrType> BaseT;
+
+  // Make sure that SmallSize is a power of two, round up if not.
+  enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
+  /// SmallStorage - Fixed size storage used in 'small mode'.
+  const void *SmallStorage[SmallSizePowTwo];
+
+public:
+  SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {}
+  SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {}
+  SmallPtrSet(SmallPtrSet &&that)
+      : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {}
+
+  template<typename It>
+  SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) {
+    this->insert(I, E);
+  }
+
+  SmallPtrSet<PtrType, SmallSize> &
+  operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
+    if (&RHS != this)
+      this->CopyFrom(RHS);
+    return *this;
+  }
+
+  SmallPtrSet<PtrType, SmallSize>&
+  operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) {
+    if (&RHS != this)
+      this->MoveFrom(SmallSizePowTwo, std::move(RHS));
+    return *this;
+  }
+
+  /// swap - Swaps the elements of two sets.
+  void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
+    SmallPtrSetImplBase::swap(RHS);
+  }
+};
+}
+
+namespace std {
+  /// Implement std::swap in terms of SmallPtrSet swap.
+  template<class T, unsigned N>
+  inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
+    LHS.swap(RHS);
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/SmallString.h b/third_party/llvm-subzero/include/llvm/ADT/SmallString.h
new file mode 100644
index 0000000..e569f54
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/SmallString.h
@@ -0,0 +1,297 @@
+//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallString class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLSTRING_H
+#define LLVM_ADT_SMALLSTRING_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+/// SmallString - A SmallString is just a SmallVector with methods and accessors
+/// that make it work better as a string (e.g. operator+ etc).
+template<unsigned InternalLen>
+class SmallString : public SmallVector<char, InternalLen> {
+public:
+  /// Default ctor - Initialize to empty.
+  SmallString() {}
+
+  /// Initialize from a StringRef.
+  SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
+
+  /// Initialize with a range.
+  template<typename ItTy>
+  SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
+
+  // Note that in order to add new overloads for append & assign, we have to
+  // duplicate the inherited versions so as not to inadvertently hide them.
+
+  /// @}
+  /// @name String Assignment
+  /// @{
+
+  /// Assign from a repeated element.
+  void assign(size_t NumElts, char Elt) {
+    this->SmallVectorImpl<char>::assign(NumElts, Elt);
+  }
+
+  /// Assign from an iterator pair.
+  template<typename in_iter>
+  void assign(in_iter S, in_iter E) {
+    this->clear();
+    SmallVectorImpl<char>::append(S, E);
+  }
+
+  /// Assign from a StringRef.
+  void assign(StringRef RHS) {
+    this->clear();
+    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+  }
+
+  /// Assign from a SmallVector.
+  void assign(const SmallVectorImpl<char> &RHS) {
+    this->clear();
+    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+  }
+
+  /// @}
+  /// @name String Concatenation
+  /// @{
+
+  /// Append from an iterator pair.
+  template<typename in_iter>
+  void append(in_iter S, in_iter E) {
+    SmallVectorImpl<char>::append(S, E);
+  }
+
+  void append(size_t NumInputs, char Elt) {
+    SmallVectorImpl<char>::append(NumInputs, Elt);
+  }
+
+
+  /// Append from a StringRef.
+  void append(StringRef RHS) {
+    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+  }
+
+  /// Append from a SmallVector.
+  void append(const SmallVectorImpl<char> &RHS) {
+    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+  }
+
+  /// @}
+  /// @name String Comparison
+  /// @{
+
+  /// Check for string equality.  This is more efficient than compare() when
+  /// the relative ordering of inequal strings isn't needed.
+  bool equals(StringRef RHS) const {
+    return str().equals(RHS);
+  }
+
+  /// Check for string equality, ignoring case.
+  bool equals_lower(StringRef RHS) const {
+    return str().equals_lower(RHS);
+  }
+
+  /// Compare two strings; the result is -1, 0, or 1 if this string is
+  /// lexicographically less than, equal to, or greater than the \p RHS.
+  int compare(StringRef RHS) const {
+    return str().compare(RHS);
+  }
+
+  /// compare_lower - Compare two strings, ignoring case.
+  int compare_lower(StringRef RHS) const {
+    return str().compare_lower(RHS);
+  }
+
+  /// compare_numeric - Compare two strings, treating sequences of digits as
+  /// numbers.
+  int compare_numeric(StringRef RHS) const {
+    return str().compare_numeric(RHS);
+  }
+
+  /// @}
+  /// @name String Predicates
+  /// @{
+
+  /// startswith - Check if this string starts with the given \p Prefix.
+  bool startswith(StringRef Prefix) const {
+    return str().startswith(Prefix);
+  }
+
+  /// endswith - Check if this string ends with the given \p Suffix.
+  bool endswith(StringRef Suffix) const {
+    return str().endswith(Suffix);
+  }
+
+  /// @}
+  /// @name String Searching
+  /// @{
+
+  /// find - Search for the first character \p C in the string.
+  ///
+  /// \return - The index of the first occurrence of \p C, or npos if not
+  /// found.
+  size_t find(char C, size_t From = 0) const {
+    return str().find(C, From);
+  }
+
+  /// Search for the first string \p Str in the string.
+  ///
+  /// \returns The index of the first occurrence of \p Str, or npos if not
+  /// found.
+  size_t find(StringRef Str, size_t From = 0) const {
+    return str().find(Str, From);
+  }
+
+  /// Search for the last character \p C in the string.
+  ///
+  /// \returns The index of the last occurrence of \p C, or npos if not
+  /// found.
+  size_t rfind(char C, size_t From = StringRef::npos) const {
+    return str().rfind(C, From);
+  }
+
+  /// Search for the last string \p Str in the string.
+  ///
+  /// \returns The index of the last occurrence of \p Str, or npos if not
+  /// found.
+  size_t rfind(StringRef Str) const {
+    return str().rfind(Str);
+  }
+
+  /// Find the first character in the string that is \p C, or npos if not
+  /// found. Same as find.
+  size_t find_first_of(char C, size_t From = 0) const {
+    return str().find_first_of(C, From);
+  }
+
+  /// Find the first character in the string that is in \p Chars, or npos if
+  /// not found.
+  ///
+  /// Complexity: O(size() + Chars.size())
+  size_t find_first_of(StringRef Chars, size_t From = 0) const {
+    return str().find_first_of(Chars, From);
+  }
+
+  /// Find the first character in the string that is not \p C or npos if not
+  /// found.
+  size_t find_first_not_of(char C, size_t From = 0) const {
+    return str().find_first_not_of(C, From);
+  }
+
+  /// Find the first character in the string that is not in the string
+  /// \p Chars, or npos if not found.
+  ///
+  /// Complexity: O(size() + Chars.size())
+  size_t find_first_not_of(StringRef Chars, size_t From = 0) const {
+    return str().find_first_not_of(Chars, From);
+  }
+
+  /// Find the last character in the string that is \p C, or npos if not
+  /// found.
+  size_t find_last_of(char C, size_t From = StringRef::npos) const {
+    return str().find_last_of(C, From);
+  }
+
+  /// Find the last character in the string that is in \p C, or npos if not
+  /// found.
+  ///
+  /// Complexity: O(size() + Chars.size())
+  size_t find_last_of(
+      StringRef Chars, size_t From = StringRef::npos) const {
+    return str().find_last_of(Chars, From);
+  }
+
+  /// @}
+  /// @name Helpful Algorithms
+  /// @{
+
+  /// Return the number of occurrences of \p C in the string.
+  size_t count(char C) const {
+    return str().count(C);
+  }
+
+  /// Return the number of non-overlapped occurrences of \p Str in the
+  /// string.
+  size_t count(StringRef Str) const {
+    return str().count(Str);
+  }
+
+  /// @}
+  /// @name Substring Operations
+  /// @{
+
+  /// Return a reference to the substring from [Start, Start + N).
+  ///
+  /// \param Start The index of the starting character in the substring; if
+  /// the index is npos or greater than the length of the string then the
+  /// empty substring will be returned.
+  ///
+  /// \param N The number of characters to included in the substring. If \p N
+  /// exceeds the number of characters remaining in the string, the string
+  /// suffix (starting with \p Start) will be returned.
+  StringRef substr(size_t Start, size_t N = StringRef::npos) const {
+    return str().substr(Start, N);
+  }
+
+  /// Return a reference to the substring from [Start, End).
+  ///
+  /// \param Start The index of the starting character in the substring; if
+  /// the index is npos or greater than the length of the string then the
+  /// empty substring will be returned.
+  ///
+  /// \param End The index following the last character to include in the
+  /// substring. If this is npos, or less than \p Start, or exceeds the
+  /// number of characters remaining in the string, the string suffix
+  /// (starting with \p Start) will be returned.
+  StringRef slice(size_t Start, size_t End) const {
+    return str().slice(Start, End);
+  }
+
+  // Extra methods.
+
+  /// Explicit conversion to StringRef.
+  StringRef str() const { return StringRef(this->begin(), this->size()); }
+
+  // TODO: Make this const, if it's safe...
+  const char* c_str() {
+    this->push_back(0);
+    this->pop_back();
+    return this->data();
+  }
+
+  /// Implicit conversion to StringRef.
+  operator StringRef() const { return str(); }
+
+  // Extra operators.
+  const SmallString &operator=(StringRef RHS) {
+    this->clear();
+    return *this += RHS;
+  }
+
+  SmallString &operator+=(StringRef RHS) {
+    this->append(RHS.begin(), RHS.end());
+    return *this;
+  }
+  SmallString &operator+=(char C) {
+    this->push_back(C);
+    return *this;
+  }
+};
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/SmallVector.h b/third_party/llvm-subzero/include/llvm/ADT/SmallVector.h
new file mode 100644
index 0000000..9403579
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/SmallVector.h
@@ -0,0 +1,927 @@
+//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallVector class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLVECTOR_H
+#define LLVM_ADT_SMALLVECTOR_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+
+namespace llvm {
+
+/// This is all the non-templated stuff common to all SmallVectors.
+class SmallVectorBase {
+protected:
+  void *BeginX, *EndX, *CapacityX;
+
+protected:
+  SmallVectorBase(void *FirstEl, size_t Size)
+    : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
+
+  /// This is an implementation of the grow() method which only works
+  /// on POD-like data types and is out of line to reduce code duplication.
+  void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize);
+
+public:
+  /// This returns size()*sizeof(T).
+  size_t size_in_bytes() const {
+    return size_t((char*)EndX - (char*)BeginX);
+  }
+
+  /// capacity_in_bytes - This returns capacity()*sizeof(T).
+  size_t capacity_in_bytes() const {
+    return size_t((char*)CapacityX - (char*)BeginX);
+  }
+
+  bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; }
+};
+
+template <typename T, unsigned N> struct SmallVectorStorage;
+
+/// This is the part of SmallVectorTemplateBase which does not depend on whether
+/// the type T is a POD. The extra dummy template argument is used by ArrayRef
+/// to avoid unnecessarily requiring T to be complete.
+template <typename T, typename = void>
+class SmallVectorTemplateCommon : public SmallVectorBase {
+private:
+  template <typename, unsigned> friend struct SmallVectorStorage;
+
+  // Allocate raw space for N elements of type T.  If T has a ctor or dtor, we
+  // don't want it to be automatically run, so we need to represent the space as
+  // something else.  Use an array of char of sufficient alignment.
+  typedef llvm::AlignedCharArrayUnion<T> U;
+  U FirstEl;
+  // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
+
+protected:
+  SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {}
+
+  void grow_pod(size_t MinSizeInBytes, size_t TSize) {
+    SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
+  }
+
+  /// Return true if this is a smallvector which has not had dynamic
+  /// memory allocated for it.
+  bool isSmall() const {
+    return BeginX == static_cast<const void*>(&FirstEl);
+  }
+
+  /// Put this vector in a state of being small.
+  void resetToSmall() {
+    BeginX = EndX = CapacityX = &FirstEl;
+  }
+
+  void setEnd(T *P) { this->EndX = P; }
+public:
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef T value_type;
+  typedef T *iterator;
+  typedef const T *const_iterator;
+
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+
+  typedef T &reference;
+  typedef const T &const_reference;
+  typedef T *pointer;
+  typedef const T *const_pointer;
+
+  // forward iterator creation methods.
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  iterator begin() { return (iterator)this->BeginX; }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  const_iterator begin() const { return (const_iterator)this->BeginX; }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  iterator end() { return (iterator)this->EndX; }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  const_iterator end() const { return (const_iterator)this->EndX; }
+protected:
+  iterator capacity_ptr() { return (iterator)this->CapacityX; }
+  const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;}
+public:
+
+  // reverse iterator creation methods.
+  reverse_iterator rbegin()            { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+  reverse_iterator rend()              { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  size_type size() const { return end()-begin(); }
+  size_type max_size() const { return size_type(-1) / sizeof(T); }
+
+  /// Return the total number of elements in the currently allocated buffer.
+  size_t capacity() const { return capacity_ptr() - begin(); }
+
+  /// Return a pointer to the vector's buffer, even if empty().
+  pointer data() { return pointer(begin()); }
+  /// Return a pointer to the vector's buffer, even if empty().
+  const_pointer data() const { return const_pointer(begin()); }
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  reference operator[](size_type idx) {
+    assert(idx < size());
+    return begin()[idx];
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  const_reference operator[](size_type idx) const {
+    assert(idx < size());
+    return begin()[idx];
+  }
+
+  reference front() {
+    assert(!empty());
+    return begin()[0];
+  }
+  const_reference front() const {
+    assert(!empty());
+    return begin()[0];
+  }
+
+  reference back() {
+    assert(!empty());
+    return end()[-1];
+  }
+  const_reference back() const {
+    assert(!empty());
+    return end()[-1];
+  }
+};
+
+/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
+/// implementations that are designed to work with non-POD-like T's.
+template <typename T, bool isPodLike>
+class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
+protected:
+  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
+
+  static void destroy_range(T *S, T *E) {
+    while (S != E) {
+      --E;
+      E->~T();
+    }
+  }
+
+  /// Move the range [I, E) into the uninitialized memory starting with "Dest",
+  /// constructing elements as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
+    std::uninitialized_copy(std::make_move_iterator(I),
+                            std::make_move_iterator(E), Dest);
+  }
+
+  /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
+  /// constructing elements as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+    std::uninitialized_copy(I, E, Dest);
+  }
+
+  /// Grow the allocated memory (without initializing new elements), doubling
+  /// the size of the allocated memory. Guarantees space for at least one more
+  /// element, or MinSize more elements if specified.
+  void grow(size_t MinSize = 0);
+
+public:
+  void push_back(const T &Elt) {
+    if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+      this->grow();
+    ::new ((void*) this->end()) T(Elt);
+    this->setEnd(this->end()+1);
+  }
+
+  void push_back(T &&Elt) {
+    if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+      this->grow();
+    ::new ((void*) this->end()) T(::std::move(Elt));
+    this->setEnd(this->end()+1);
+  }
+
+  void pop_back() {
+    this->setEnd(this->end()-1);
+    this->end()->~T();
+  }
+};
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool isPodLike>
+void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
+  size_t CurCapacity = this->capacity();
+  size_t CurSize = this->size();
+  // Always grow, even from zero.
+  size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2));
+  if (NewCapacity < MinSize)
+    NewCapacity = MinSize;
+  T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T)));
+
+  // Move the elements over.
+  this->uninitialized_move(this->begin(), this->end(), NewElts);
+
+  // Destroy the original elements.
+  destroy_range(this->begin(), this->end());
+
+  // If this wasn't grown from the inline copy, deallocate the old space.
+  if (!this->isSmall())
+    free(this->begin());
+
+  this->setEnd(NewElts+CurSize);
+  this->BeginX = NewElts;
+  this->CapacityX = this->begin()+NewCapacity;
+}
+
+
+/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method
+/// implementations that are designed to work with POD-like T's.
+template <typename T>
+class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
+protected:
+  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
+
+  // No need to do a destroy loop for POD's.
+  static void destroy_range(T *, T *) {}
+
+  /// Move the range [I, E) onto the uninitialized memory
+  /// starting with "Dest", constructing elements into it as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
+    // Just do a copy.
+    uninitialized_copy(I, E, Dest);
+  }
+
+  /// Copy the range [I, E) onto the uninitialized memory
+  /// starting with "Dest", constructing elements into it as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+    // Arbitrary iterator types; just use the basic implementation.
+    std::uninitialized_copy(I, E, Dest);
+  }
+
+  /// Copy the range [I, E) onto the uninitialized memory
+  /// starting with "Dest", constructing elements into it as needed.
+  template <typename T1, typename T2>
+  static void uninitialized_copy(
+      T1 *I, T1 *E, T2 *Dest,
+      typename std::enable_if<std::is_same<typename std::remove_const<T1>::type,
+                                           T2>::value>::type * = nullptr) {
+    // Use memcpy for PODs iterated by pointers (which includes SmallVector
+    // iterators): std::uninitialized_copy optimizes to memmove, but we can
+    // use memcpy here. Note that I and E are iterators and thus might be
+    // invalid for memcpy if they are equal.
+    if (I != E)
+      memcpy(Dest, I, (E - I) * sizeof(T));
+  }
+
+  /// Double the size of the allocated memory, guaranteeing space for at
+  /// least one more element or MinSize if specified.
+  void grow(size_t MinSize = 0) {
+    this->grow_pod(MinSize*sizeof(T), sizeof(T));
+  }
+public:
+  void push_back(const T &Elt) {
+    if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+      this->grow();
+    memcpy(this->end(), &Elt, sizeof(T));
+    this->setEnd(this->end()+1);
+  }
+
+  void pop_back() {
+    this->setEnd(this->end()-1);
+  }
+};
+
+
+/// This class consists of common code factored out of the SmallVector class to
+/// reduce code duplication based on the SmallVector 'N' template parameter.
+template <typename T>
+class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
+  typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
+
+  SmallVectorImpl(const SmallVectorImpl&) = delete;
+public:
+  typedef typename SuperClass::iterator iterator;
+  typedef typename SuperClass::const_iterator const_iterator;
+  typedef typename SuperClass::size_type size_type;
+
+protected:
+  // Default ctor - Initialize to empty.
+  explicit SmallVectorImpl(unsigned N)
+    : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) {
+  }
+
+public:
+  ~SmallVectorImpl() {
+    // Destroy the constructed elements in the vector.
+    this->destroy_range(this->begin(), this->end());
+
+    // If this wasn't grown from the inline copy, deallocate the old space.
+    if (!this->isSmall())
+      free(this->begin());
+  }
+
+
+  void clear() {
+    this->destroy_range(this->begin(), this->end());
+    this->EndX = this->BeginX;
+  }
+
+  void resize(size_type N) {
+    if (N < this->size()) {
+      this->destroy_range(this->begin()+N, this->end());
+      this->setEnd(this->begin()+N);
+    } else if (N > this->size()) {
+      if (this->capacity() < N)
+        this->grow(N);
+      for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
+        new (&*I) T();
+      this->setEnd(this->begin()+N);
+    }
+  }
+
+  void resize(size_type N, const T &NV) {
+    if (N < this->size()) {
+      this->destroy_range(this->begin()+N, this->end());
+      this->setEnd(this->begin()+N);
+    } else if (N > this->size()) {
+      if (this->capacity() < N)
+        this->grow(N);
+      std::uninitialized_fill(this->end(), this->begin()+N, NV);
+      this->setEnd(this->begin()+N);
+    }
+  }
+
+  void reserve(size_type N) {
+    if (this->capacity() < N)
+      this->grow(N);
+  }
+
+  T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() {
+    T Result = ::std::move(this->back());
+    this->pop_back();
+    return Result;
+  }
+
+  void swap(SmallVectorImpl &RHS);
+
+  /// Add the specified range to the end of the SmallVector.
+  template<typename in_iter>
+  void append(in_iter in_start, in_iter in_end) {
+    size_type NumInputs = std::distance(in_start, in_end);
+    // Grow allocated space if needed.
+    if (NumInputs > size_type(this->capacity_ptr()-this->end()))
+      this->grow(this->size()+NumInputs);
+
+    // Copy the new elements over.
+    this->uninitialized_copy(in_start, in_end, this->end());
+    this->setEnd(this->end() + NumInputs);
+  }
+
+  /// Add the specified range to the end of the SmallVector.
+  void append(size_type NumInputs, const T &Elt) {
+    // Grow allocated space if needed.
+    if (NumInputs > size_type(this->capacity_ptr()-this->end()))
+      this->grow(this->size()+NumInputs);
+
+    // Copy the new elements over.
+    std::uninitialized_fill_n(this->end(), NumInputs, Elt);
+    this->setEnd(this->end() + NumInputs);
+  }
+
+  void append(std::initializer_list<T> IL) {
+    append(IL.begin(), IL.end());
+  }
+
+  void assign(size_type NumElts, const T &Elt) {
+    clear();
+    if (this->capacity() < NumElts)
+      this->grow(NumElts);
+    this->setEnd(this->begin()+NumElts);
+    std::uninitialized_fill(this->begin(), this->end(), Elt);
+  }
+
+  void assign(std::initializer_list<T> IL) {
+    clear();
+    append(IL);
+  }
+
+  iterator erase(const_iterator CI) {
+    // Just cast away constness because this is a non-const member function.
+    iterator I = const_cast<iterator>(CI);
+
+    assert(I >= this->begin() && "Iterator to erase is out of bounds.");
+    assert(I < this->end() && "Erasing at past-the-end iterator.");
+
+    iterator N = I;
+    // Shift all elts down one.
+    std::move(I+1, this->end(), I);
+    // Drop the last elt.
+    this->pop_back();
+    return(N);
+  }
+
+  iterator erase(const_iterator CS, const_iterator CE) {
+    // Just cast away constness because this is a non-const member function.
+    iterator S = const_cast<iterator>(CS);
+    iterator E = const_cast<iterator>(CE);
+
+    assert(S >= this->begin() && "Range to erase is out of bounds.");
+    assert(S <= E && "Trying to erase invalid range.");
+    assert(E <= this->end() && "Trying to erase past the end.");
+
+    iterator N = S;
+    // Shift all elts down.
+    iterator I = std::move(E, this->end(), S);
+    // Drop the last elts.
+    this->destroy_range(I, this->end());
+    this->setEnd(I);
+    return(N);
+  }
+
+  iterator insert(iterator I, T &&Elt) {
+    if (I == this->end()) {  // Important special case for empty vector.
+      this->push_back(::std::move(Elt));
+      return this->end()-1;
+    }
+
+    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+    assert(I <= this->end() && "Inserting past the end of the vector.");
+
+    if (this->EndX >= this->CapacityX) {
+      size_t EltNo = I-this->begin();
+      this->grow();
+      I = this->begin()+EltNo;
+    }
+
+    ::new ((void*) this->end()) T(::std::move(this->back()));
+    // Push everything else over.
+    std::move_backward(I, this->end()-1, this->end());
+    this->setEnd(this->end()+1);
+
+    // If we just moved the element we're inserting, be sure to update
+    // the reference.
+    T *EltPtr = &Elt;
+    if (I <= EltPtr && EltPtr < this->EndX)
+      ++EltPtr;
+
+    *I = ::std::move(*EltPtr);
+    return I;
+  }
+
+  iterator insert(iterator I, const T &Elt) {
+    if (I == this->end()) {  // Important special case for empty vector.
+      this->push_back(Elt);
+      return this->end()-1;
+    }
+
+    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+    assert(I <= this->end() && "Inserting past the end of the vector.");
+
+    if (this->EndX >= this->CapacityX) {
+      size_t EltNo = I-this->begin();
+      this->grow();
+      I = this->begin()+EltNo;
+    }
+    ::new ((void*) this->end()) T(std::move(this->back()));
+    // Push everything else over.
+    std::move_backward(I, this->end()-1, this->end());
+    this->setEnd(this->end()+1);
+
+    // If we just moved the element we're inserting, be sure to update
+    // the reference.
+    const T *EltPtr = &Elt;
+    if (I <= EltPtr && EltPtr < this->EndX)
+      ++EltPtr;
+
+    *I = *EltPtr;
+    return I;
+  }
+
+  iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
+    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+    size_t InsertElt = I - this->begin();
+
+    if (I == this->end()) {  // Important special case for empty vector.
+      append(NumToInsert, Elt);
+      return this->begin()+InsertElt;
+    }
+
+    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+    assert(I <= this->end() && "Inserting past the end of the vector.");
+
+    // Ensure there is enough space.
+    reserve(this->size() + NumToInsert);
+
+    // Uninvalidate the iterator.
+    I = this->begin()+InsertElt;
+
+    // If there are more elements between the insertion point and the end of the
+    // range than there are being inserted, we can use a simple approach to
+    // insertion.  Since we already reserved space, we know that this won't
+    // reallocate the vector.
+    if (size_t(this->end()-I) >= NumToInsert) {
+      T *OldEnd = this->end();
+      append(std::move_iterator<iterator>(this->end() - NumToInsert),
+             std::move_iterator<iterator>(this->end()));
+
+      // Copy the existing elements that get replaced.
+      std::move_backward(I, OldEnd-NumToInsert, OldEnd);
+
+      std::fill_n(I, NumToInsert, Elt);
+      return I;
+    }
+
+    // Otherwise, we're inserting more elements than exist already, and we're
+    // not inserting at the end.
+
+    // Move over the elements that we're about to overwrite.
+    T *OldEnd = this->end();
+    this->setEnd(this->end() + NumToInsert);
+    size_t NumOverwritten = OldEnd-I;
+    this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
+
+    // Replace the overwritten part.
+    std::fill_n(I, NumOverwritten, Elt);
+
+    // Insert the non-overwritten middle part.
+    std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
+    return I;
+  }
+
+  template<typename ItTy>
+  iterator insert(iterator I, ItTy From, ItTy To) {
+    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+    size_t InsertElt = I - this->begin();
+
+    if (I == this->end()) {  // Important special case for empty vector.
+      append(From, To);
+      return this->begin()+InsertElt;
+    }
+
+    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+    assert(I <= this->end() && "Inserting past the end of the vector.");
+
+    size_t NumToInsert = std::distance(From, To);
+
+    // Ensure there is enough space.
+    reserve(this->size() + NumToInsert);
+
+    // Uninvalidate the iterator.
+    I = this->begin()+InsertElt;
+
+    // If there are more elements between the insertion point and the end of the
+    // range than there are being inserted, we can use a simple approach to
+    // insertion.  Since we already reserved space, we know that this won't
+    // reallocate the vector.
+    if (size_t(this->end()-I) >= NumToInsert) {
+      T *OldEnd = this->end();
+      append(std::move_iterator<iterator>(this->end() - NumToInsert),
+             std::move_iterator<iterator>(this->end()));
+
+      // Copy the existing elements that get replaced.
+      std::move_backward(I, OldEnd-NumToInsert, OldEnd);
+
+      std::copy(From, To, I);
+      return I;
+    }
+
+    // Otherwise, we're inserting more elements than exist already, and we're
+    // not inserting at the end.
+
+    // Move over the elements that we're about to overwrite.
+    T *OldEnd = this->end();
+    this->setEnd(this->end() + NumToInsert);
+    size_t NumOverwritten = OldEnd-I;
+    this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
+
+    // Replace the overwritten part.
+    for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
+      *J = *From;
+      ++J; ++From;
+    }
+
+    // Insert the non-overwritten middle part.
+    this->uninitialized_copy(From, To, OldEnd);
+    return I;
+  }
+
+  void insert(iterator I, std::initializer_list<T> IL) {
+    insert(I, IL.begin(), IL.end());
+  }
+
+  template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
+    if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+      this->grow();
+    ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
+    this->setEnd(this->end() + 1);
+  }
+
+  SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
+
+  SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
+
+  bool operator==(const SmallVectorImpl &RHS) const {
+    if (this->size() != RHS.size()) return false;
+    return std::equal(this->begin(), this->end(), RHS.begin());
+  }
+  bool operator!=(const SmallVectorImpl &RHS) const {
+    return !(*this == RHS);
+  }
+
+  bool operator<(const SmallVectorImpl &RHS) const {
+    return std::lexicographical_compare(this->begin(), this->end(),
+                                        RHS.begin(), RHS.end());
+  }
+
+  /// Set the array size to \p N, which the current array must have enough
+  /// capacity for.
+  ///
+  /// This does not construct or destroy any elements in the vector.
+  ///
+  /// Clients can use this in conjunction with capacity() to write past the end
+  /// of the buffer when they know that more elements are available, and only
+  /// update the size later. This avoids the cost of value initializing elements
+  /// which will only be overwritten.
+  void set_size(size_type N) {
+    assert(N <= this->capacity());
+    this->setEnd(this->begin() + N);
+  }
+};
+
+
+template <typename T>
+void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
+  if (this == &RHS) return;
+
+  // We can only avoid copying elements if neither vector is small.
+  if (!this->isSmall() && !RHS.isSmall()) {
+    std::swap(this->BeginX, RHS.BeginX);
+    std::swap(this->EndX, RHS.EndX);
+    std::swap(this->CapacityX, RHS.CapacityX);
+    return;
+  }
+  if (RHS.size() > this->capacity())
+    this->grow(RHS.size());
+  if (this->size() > RHS.capacity())
+    RHS.grow(this->size());
+
+  // Swap the shared elements.
+  size_t NumShared = this->size();
+  if (NumShared > RHS.size()) NumShared = RHS.size();
+  for (size_type i = 0; i != NumShared; ++i)
+    std::swap((*this)[i], RHS[i]);
+
+  // Copy over the extra elts.
+  if (this->size() > RHS.size()) {
+    size_t EltDiff = this->size() - RHS.size();
+    this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
+    RHS.setEnd(RHS.end()+EltDiff);
+    this->destroy_range(this->begin()+NumShared, this->end());
+    this->setEnd(this->begin()+NumShared);
+  } else if (RHS.size() > this->size()) {
+    size_t EltDiff = RHS.size() - this->size();
+    this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
+    this->setEnd(this->end() + EltDiff);
+    this->destroy_range(RHS.begin()+NumShared, RHS.end());
+    RHS.setEnd(RHS.begin()+NumShared);
+  }
+}
+
+template <typename T>
+SmallVectorImpl<T> &SmallVectorImpl<T>::
+  operator=(const SmallVectorImpl<T> &RHS) {
+  // Avoid self-assignment.
+  if (this == &RHS) return *this;
+
+  // If we already have sufficient space, assign the common elements, then
+  // destroy any excess.
+  size_t RHSSize = RHS.size();
+  size_t CurSize = this->size();
+  if (CurSize >= RHSSize) {
+    // Assign common elements.
+    iterator NewEnd;
+    if (RHSSize)
+      NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
+    else
+      NewEnd = this->begin();
+
+    // Destroy excess elements.
+    this->destroy_range(NewEnd, this->end());
+
+    // Trim.
+    this->setEnd(NewEnd);
+    return *this;
+  }
+
+  // If we have to grow to have enough elements, destroy the current elements.
+  // This allows us to avoid copying them during the grow.
+  // FIXME: don't do this if they're efficiently moveable.
+  if (this->capacity() < RHSSize) {
+    // Destroy current elements.
+    this->destroy_range(this->begin(), this->end());
+    this->setEnd(this->begin());
+    CurSize = 0;
+    this->grow(RHSSize);
+  } else if (CurSize) {
+    // Otherwise, use assignment for the already-constructed elements.
+    std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
+  }
+
+  // Copy construct the new elements in place.
+  this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
+                           this->begin()+CurSize);
+
+  // Set end.
+  this->setEnd(this->begin()+RHSSize);
+  return *this;
+}
+
+template <typename T>
+SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
+  // Avoid self-assignment.
+  if (this == &RHS) return *this;
+
+  // If the RHS isn't small, clear this vector and then steal its buffer.
+  if (!RHS.isSmall()) {
+    this->destroy_range(this->begin(), this->end());
+    if (!this->isSmall()) free(this->begin());
+    this->BeginX = RHS.BeginX;
+    this->EndX = RHS.EndX;
+    this->CapacityX = RHS.CapacityX;
+    RHS.resetToSmall();
+    return *this;
+  }
+
+  // If we already have sufficient space, assign the common elements, then
+  // destroy any excess.
+  size_t RHSSize = RHS.size();
+  size_t CurSize = this->size();
+  if (CurSize >= RHSSize) {
+    // Assign common elements.
+    iterator NewEnd = this->begin();
+    if (RHSSize)
+      NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
+
+    // Destroy excess elements and trim the bounds.
+    this->destroy_range(NewEnd, this->end());
+    this->setEnd(NewEnd);
+
+    // Clear the RHS.
+    RHS.clear();
+
+    return *this;
+  }
+
+  // If we have to grow to have enough elements, destroy the current elements.
+  // This allows us to avoid copying them during the grow.
+  // FIXME: this may not actually make any sense if we can efficiently move
+  // elements.
+  if (this->capacity() < RHSSize) {
+    // Destroy current elements.
+    this->destroy_range(this->begin(), this->end());
+    this->setEnd(this->begin());
+    CurSize = 0;
+    this->grow(RHSSize);
+  } else if (CurSize) {
+    // Otherwise, use assignment for the already-constructed elements.
+    std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
+  }
+
+  // Move-construct the new elements in place.
+  this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
+                           this->begin()+CurSize);
+
+  // Set end.
+  this->setEnd(this->begin()+RHSSize);
+
+  RHS.clear();
+  return *this;
+}
+
+/// Storage for the SmallVector elements which aren't contained in
+/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1'
+/// element is in the base class. This is specialized for the N=1 and N=0 cases
+/// to avoid allocating unnecessary storage.
+template <typename T, unsigned N>
+struct SmallVectorStorage {
+  typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1];
+};
+template <typename T> struct SmallVectorStorage<T, 1> {};
+template <typename T> struct SmallVectorStorage<T, 0> {};
+
+/// This is a 'vector' (really, a variable-sized array), optimized
+/// for the case when the array is small.  It contains some number of elements
+/// in-place, which allows it to avoid heap allocation when the actual number of
+/// elements is below that threshold.  This allows normal "small" cases to be
+/// fast without losing generality for large inputs.
+///
+/// Note that this does not attempt to be exception safe.
+///
+template <typename T, unsigned N>
+class SmallVector : public SmallVectorImpl<T> {
+  /// Inline space for elements which aren't stored in the base class.
+  SmallVectorStorage<T, N> Storage;
+public:
+  SmallVector() : SmallVectorImpl<T>(N) {
+  }
+
+  explicit SmallVector(size_t Size, const T &Value = T())
+    : SmallVectorImpl<T>(N) {
+    this->assign(Size, Value);
+  }
+
+  template<typename ItTy>
+  SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
+    this->append(S, E);
+  }
+
+  template <typename RangeTy>
+  explicit SmallVector(const llvm::iterator_range<RangeTy> &R)
+      : SmallVectorImpl<T>(N) {
+    this->append(R.begin(), R.end());
+  }
+
+  SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
+    this->assign(IL);
+  }
+
+  SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
+    if (!RHS.empty())
+      SmallVectorImpl<T>::operator=(RHS);
+  }
+
+  const SmallVector &operator=(const SmallVector &RHS) {
+    SmallVectorImpl<T>::operator=(RHS);
+    return *this;
+  }
+
+  SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
+    if (!RHS.empty())
+      SmallVectorImpl<T>::operator=(::std::move(RHS));
+  }
+
+  const SmallVector &operator=(SmallVector &&RHS) {
+    SmallVectorImpl<T>::operator=(::std::move(RHS));
+    return *this;
+  }
+
+  SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
+    if (!RHS.empty())
+      SmallVectorImpl<T>::operator=(::std::move(RHS));
+  }
+
+  const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
+    SmallVectorImpl<T>::operator=(::std::move(RHS));
+    return *this;
+  }
+
+  const SmallVector &operator=(std::initializer_list<T> IL) {
+    this->assign(IL);
+    return *this;
+  }
+};
+
+template<typename T, unsigned N>
+static inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
+  return X.capacity_in_bytes();
+}
+
+} // End llvm namespace
+
+namespace std {
+  /// Implement std::swap in terms of SmallVector swap.
+  template<typename T>
+  inline void
+  swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
+    LHS.swap(RHS);
+  }
+
+  /// Implement std::swap in terms of SmallVector swap.
+  template<typename T, unsigned N>
+  inline void
+  swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
+    LHS.swap(RHS);
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Statistic.h b/third_party/llvm-subzero/include/llvm/ADT/Statistic.h
new file mode 100644
index 0000000..c541383
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/Statistic.h
@@ -0,0 +1,173 @@
+//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the 'Statistic' class, which is designed to be an easy way
+// to expose various metrics from passes.  These statistics are printed at the
+// end of a run (from llvm_shutdown), when the -stats command line option is
+// passed on the command line.
+//
+// This is useful for reporting information like the number of instructions
+// simplified, optimized or removed by various transformations, like this:
+//
+// static Statistic NumInstsKilled("gcse", "Number of instructions killed");
+//
+// Later, in the code: ++NumInstsKilled;
+//
+// NOTE: Statistics *must* be declared as global variables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STATISTIC_H
+#define LLVM_ADT_STATISTIC_H
+
+#include "llvm/Support/Atomic.h"
+#include "llvm/Support/Compiler.h"
+#include <atomic>
+#include <memory>
+
+namespace llvm {
+
+class raw_ostream;
+class raw_fd_ostream;
+
+class Statistic {
+public:
+  const char *DebugType;
+  const char *Name;
+  const char *Desc;
+  std::atomic<unsigned> Value;
+  bool Initialized;
+
+  unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
+  const char *getDebugType() const { return DebugType; }
+  const char *getName() const { return Name; }
+  const char *getDesc() const { return Desc; }
+
+  /// construct - This should only be called for non-global statistics.
+  void construct(const char *debugtype, const char *name, const char *desc) {
+    DebugType = debugtype;
+    Name = name;
+    Desc = desc;
+    Value = 0;
+    Initialized = false;
+  }
+
+  // Allow use of this class as the value itself.
+  operator unsigned() const { return getValue(); }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+   const Statistic &operator=(unsigned Val) {
+    Value.store(Val, std::memory_order_relaxed);
+    return init();
+  }
+
+  const Statistic &operator++() {
+    Value.fetch_add(1, std::memory_order_relaxed);
+    return init();
+  }
+
+  unsigned operator++(int) {
+    init();
+    return Value.fetch_add(1, std::memory_order_relaxed);
+  }
+
+  const Statistic &operator--() {
+    Value.fetch_sub(1, std::memory_order_relaxed);
+    return init();
+  }
+
+  unsigned operator--(int) {
+    init();
+    return Value.fetch_sub(1, std::memory_order_relaxed);
+  }
+
+  const Statistic &operator+=(unsigned V) {
+    if (V == 0)
+      return *this;
+    Value.fetch_add(V, std::memory_order_relaxed);
+    return init();
+  }
+
+  const Statistic &operator-=(unsigned V) {
+    if (V == 0)
+      return *this;
+    Value.fetch_sub(V, std::memory_order_relaxed);
+    return init();
+  }
+
+#else  // Statistics are disabled in release builds.
+
+  const Statistic &operator=(unsigned Val) {
+    return *this;
+  }
+
+  const Statistic &operator++() {
+    return *this;
+  }
+
+  unsigned operator++(int) {
+    return 0;
+  }
+
+  const Statistic &operator--() {
+    return *this;
+  }
+
+  unsigned operator--(int) {
+    return 0;
+  }
+
+  const Statistic &operator+=(const unsigned &V) {
+    return *this;
+  }
+
+  const Statistic &operator-=(const unsigned &V) {
+    return *this;
+  }
+
+#endif  // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+
+protected:
+  Statistic &init() {
+    bool tmp = Initialized;
+    sys::MemoryFence();
+    if (!tmp) RegisterStatistic();
+    TsanHappensAfter(this);
+    return *this;
+  }
+
+  void RegisterStatistic();
+};
+
+// STATISTIC - A macro to make definition of statistics really simple.  This
+// automatically passes the DEBUG_TYPE of the file into the statistic.
+#define STATISTIC(VARNAME, DESC)                                               \
+  static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, false}
+
+/// \brief Enable the collection and printing of statistics.
+void EnableStatistics();
+
+/// \brief Check if statistics are enabled.
+bool AreStatisticsEnabled();
+
+/// \brief Return a file stream to print our output on.
+std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
+
+/// \brief Print statistics to the file returned by CreateInfoOutputFile().
+void PrintStatistics();
+
+/// \brief Print statistics to the given output stream.
+void PrintStatistics(raw_ostream &OS);
+
+/// Print statistics in JSON format.
+void PrintStatisticsJSON(raw_ostream &OS);
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STATISTIC_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringExtras.h b/third_party/llvm-subzero/include/llvm/ADT/StringExtras.h
new file mode 100644
index 0000000..05513e1
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/StringExtras.h
@@ -0,0 +1,202 @@
+//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some functions that are useful when dealing with strings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGEXTRAS_H
+#define LLVM_ADT_STRINGEXTRAS_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include <iterator>
+
+namespace llvm {
+class raw_ostream;
+template<typename T> class SmallVectorImpl;
+
+/// hexdigit - Return the hexadecimal character for the
+/// given number \p X (which should be less than 16).
+static inline char hexdigit(unsigned X, bool LowerCase = false) {
+  const char HexChar = LowerCase ? 'a' : 'A';
+  return X < 10 ? '0' + X : HexChar + X - 10;
+}
+
+/// Construct a string ref from a boolean.
+static inline StringRef toStringRef(bool B) {
+  return StringRef(B ? "true" : "false");
+}
+
+/// Interpret the given character \p C as a hexadecimal digit and return its
+/// value.
+///
+/// If \p C is not a valid hex digit, -1U is returned.
+static inline unsigned hexDigitValue(char C) {
+  if (C >= '0' && C <= '9') return C-'0';
+  if (C >= 'a' && C <= 'f') return C-'a'+10U;
+  if (C >= 'A' && C <= 'F') return C-'A'+10U;
+  return -1U;
+}
+
+static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
+  char Buffer[17];
+  char *BufPtr = std::end(Buffer);
+
+  if (X == 0) *--BufPtr = '0';
+
+  while (X) {
+    unsigned char Mod = static_cast<unsigned char>(X) & 15;
+    *--BufPtr = hexdigit(Mod, LowerCase);
+    X >>= 4;
+  }
+
+  return std::string(BufPtr, std::end(Buffer));
+}
+
+/// Convert buffer \p Input to its hexadecimal representation.
+/// The returned string is double the size of \p Input.
+static inline std::string toHex(StringRef Input) {
+  static const char *const LUT = "0123456789ABCDEF";
+  size_t Length = Input.size();
+
+  std::string Output;
+  Output.reserve(2 * Length);
+  for (size_t i = 0; i < Length; ++i) {
+    const unsigned char c = Input[i];
+    Output.push_back(LUT[c >> 4]);
+    Output.push_back(LUT[c & 15]);
+  }
+  return Output;
+}
+
+static inline std::string utostr(uint64_t X, bool isNeg = false) {
+  char Buffer[21];
+  char *BufPtr = std::end(Buffer);
+
+  if (X == 0) *--BufPtr = '0';  // Handle special case...
+
+  while (X) {
+    *--BufPtr = '0' + char(X % 10);
+    X /= 10;
+  }
+
+  if (isNeg) *--BufPtr = '-';   // Add negative sign...
+  return std::string(BufPtr, std::end(Buffer));
+}
+
+
+static inline std::string itostr(int64_t X) {
+  if (X < 0)
+    return utostr(static_cast<uint64_t>(-X), true);
+  else
+    return utostr(static_cast<uint64_t>(X));
+}
+
+/// StrInStrNoCase - Portable version of strcasestr.  Locates the first
+/// occurrence of string 's1' in string 's2', ignoring case.  Returns
+/// the offset of s2 in s1 or npos if s2 cannot be found.
+StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2);
+
+/// getToken - This function extracts one token from source, ignoring any
+/// leading characters that appear in the Delimiters string, and ending the
+/// token at any of the characters that appear in the Delimiters string.  If
+/// there are no tokens in the source string, an empty string is returned.
+/// The function returns a pair containing the extracted token and the
+/// remaining tail string.
+std::pair<StringRef, StringRef> getToken(StringRef Source,
+                                         StringRef Delimiters = " \t\n\v\f\r");
+
+/// SplitString - Split up the specified string according to the specified
+/// delimiters, appending the result fragments to the output list.
+void SplitString(StringRef Source,
+                 SmallVectorImpl<StringRef> &OutFragments,
+                 StringRef Delimiters = " \t\n\v\f\r");
+
+/// HashString - Hash function for strings.
+///
+/// This is the Bernstein hash function.
+//
+// FIXME: Investigate whether a modified bernstein hash function performs
+// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
+//   X*33+c -> X*33^c
+static inline unsigned HashString(StringRef Str, unsigned Result = 0) {
+  for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i)
+    Result = Result * 33 + (unsigned char)Str[i];
+  return Result;
+}
+
+/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th).
+static inline StringRef getOrdinalSuffix(unsigned Val) {
+  // It is critically important that we do this perfectly for
+  // user-written sequences with over 100 elements.
+  switch (Val % 100) {
+  case 11:
+  case 12:
+  case 13:
+    return "th";
+  default:
+    switch (Val % 10) {
+      case 1: return "st";
+      case 2: return "nd";
+      case 3: return "rd";
+      default: return "th";
+    }
+  }
+}
+
+/// PrintEscapedString - Print each character of the specified string, escaping
+/// it if it is not printable or if it is an escape char.
+void PrintEscapedString(StringRef Name, raw_ostream &Out);
+
+template <typename IteratorT>
+inline std::string join_impl(IteratorT Begin, IteratorT End,
+                             StringRef Separator, std::input_iterator_tag) {
+  std::string S;
+  if (Begin == End)
+    return S;
+
+  S += (*Begin);
+  while (++Begin != End) {
+    S += Separator;
+    S += (*Begin);
+  }
+  return S;
+}
+
+template <typename IteratorT>
+inline std::string join_impl(IteratorT Begin, IteratorT End,
+                             StringRef Separator, std::forward_iterator_tag) {
+  std::string S;
+  if (Begin == End)
+    return S;
+
+  size_t Len = (std::distance(Begin, End) - 1) * Separator.size();
+  for (IteratorT I = Begin; I != End; ++I)
+    Len += (*Begin).size();
+  S.reserve(Len);
+  S += (*Begin);
+  while (++Begin != End) {
+    S += Separator;
+    S += (*Begin);
+  }
+  return S;
+}
+
+/// Joins the strings in the range [Begin, End), adding Separator between
+/// the elements.
+template <typename IteratorT>
+inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) {
+  typedef typename std::iterator_traits<IteratorT>::iterator_category tag;
+  return join_impl(Begin, End, Separator, tag());
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringMap.h b/third_party/llvm-subzero/include/llvm/ADT/StringMap.h
new file mode 100644
index 0000000..5c048b1
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/StringMap.h
@@ -0,0 +1,503 @@
+//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the StringMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGMAP_H
+#define LLVM_ADT_STRINGMAP_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cstring>
+#include <utility>
+
+namespace llvm {
+  template<typename ValueT>
+  class StringMapConstIterator;
+  template<typename ValueT>
+  class StringMapIterator;
+  template<typename ValueTy>
+  class StringMapEntry;
+
+/// StringMapEntryBase - Shared base class of StringMapEntry instances.
+class StringMapEntryBase {
+  unsigned StrLen;
+
+public:
+  explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
+
+  unsigned getKeyLength() const { return StrLen; }
+};
+
+/// StringMapImpl - This is the base class of StringMap that is shared among
+/// all of its instantiations.
+class StringMapImpl {
+protected:
+  // Array of NumBuckets pointers to entries, null pointers are holes.
+  // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
+  // by an array of the actual hash values as unsigned integers.
+  StringMapEntryBase **TheTable;
+  unsigned NumBuckets;
+  unsigned NumItems;
+  unsigned NumTombstones;
+  unsigned ItemSize;
+
+protected:
+  explicit StringMapImpl(unsigned itemSize)
+      : TheTable(nullptr),
+        // Initialize the map with zero buckets to allocation.
+        NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {}
+  StringMapImpl(StringMapImpl &&RHS)
+      : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
+        NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
+        ItemSize(RHS.ItemSize) {
+    RHS.TheTable = nullptr;
+    RHS.NumBuckets = 0;
+    RHS.NumItems = 0;
+    RHS.NumTombstones = 0;
+  }
+
+  StringMapImpl(unsigned InitSize, unsigned ItemSize);
+  unsigned RehashTable(unsigned BucketNo = 0);
+
+  /// LookupBucketFor - Look up the bucket that the specified string should end
+  /// up in.  If it already exists as a key in the map, the Item pointer for the
+  /// specified bucket will be non-null.  Otherwise, it will be null.  In either
+  /// case, the FullHashValue field of the bucket will be set to the hash value
+  /// of the string.
+  unsigned LookupBucketFor(StringRef Key);
+
+  /// FindKey - Look up the bucket that contains the specified key. If it exists
+  /// in the map, return the bucket number of the key.  Otherwise return -1.
+  /// This does not modify the map.
+  int FindKey(StringRef Key) const;
+
+  /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
+  /// delete it.  This aborts if the value isn't in the table.
+  void RemoveKey(StringMapEntryBase *V);
+
+  /// RemoveKey - Remove the StringMapEntry for the specified key from the
+  /// table, returning it.  If the key is not in the table, this returns null.
+  StringMapEntryBase *RemoveKey(StringRef Key);
+
+  /// Allocate the table with the specified number of buckets and otherwise
+  /// setup the map as empty.
+  void init(unsigned Size);
+
+public:
+  static StringMapEntryBase *getTombstoneVal() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
+    return reinterpret_cast<StringMapEntryBase *>(Val);
+  }
+
+  unsigned getNumBuckets() const { return NumBuckets; }
+  unsigned getNumItems() const { return NumItems; }
+
+  bool empty() const { return NumItems == 0; }
+  unsigned size() const { return NumItems; }
+
+  void swap(StringMapImpl &Other) {
+    std::swap(TheTable, Other.TheTable);
+    std::swap(NumBuckets, Other.NumBuckets);
+    std::swap(NumItems, Other.NumItems);
+    std::swap(NumTombstones, Other.NumTombstones);
+  }
+};
+
+/// StringMapEntry - This is used to represent one value that is inserted into
+/// a StringMap.  It contains the Value itself and the key: the string length
+/// and data.
+template<typename ValueTy>
+class StringMapEntry : public StringMapEntryBase {
+  StringMapEntry(StringMapEntry &E) = delete;
+
+public:
+  ValueTy second;
+
+  explicit StringMapEntry(unsigned strLen)
+    : StringMapEntryBase(strLen), second() {}
+  template <typename... InitTy>
+  StringMapEntry(unsigned strLen, InitTy &&... InitVals)
+      : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
+
+  StringRef getKey() const {
+    return StringRef(getKeyData(), getKeyLength());
+  }
+
+  const ValueTy &getValue() const { return second; }
+  ValueTy &getValue() { return second; }
+
+  void setValue(const ValueTy &V) { second = V; }
+
+  /// getKeyData - Return the start of the string data that is the key for this
+  /// value.  The string data is always stored immediately after the
+  /// StringMapEntry object.
+  const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
+
+  StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
+
+  /// Create a StringMapEntry for the specified key construct the value using
+  /// \p InitiVals.
+  template <typename AllocatorTy, typename... InitTy>
+  static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
+                                InitTy &&... InitVals) {
+    unsigned KeyLength = Key.size();
+
+    // Allocate a new item with space for the string at the end and a null
+    // terminator.
+    unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
+      KeyLength+1;
+    unsigned Alignment = alignOf<StringMapEntry>();
+
+    StringMapEntry *NewItem =
+      static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
+
+    // Construct the value.
+    new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
+
+    // Copy the string information.
+    char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
+    if (KeyLength > 0)
+      memcpy(StrBuffer, Key.data(), KeyLength);
+    StrBuffer[KeyLength] = 0;  // Null terminate for convenience of clients.
+    return NewItem;
+  }
+
+  /// Create - Create a StringMapEntry with normal malloc/free.
+  template <typename... InitType>
+  static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
+    MallocAllocator A;
+    return Create(Key, A, std::forward<InitType>(InitVal)...);
+  }
+
+  static StringMapEntry *Create(StringRef Key) {
+    return Create(Key, ValueTy());
+  }
+
+  /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
+  /// into a StringMapEntry, return the StringMapEntry itself.
+  static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
+    char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
+    return *reinterpret_cast<StringMapEntry*>(Ptr);
+  }
+
+  /// Destroy - Destroy this StringMapEntry, releasing memory back to the
+  /// specified allocator.
+  template<typename AllocatorTy>
+  void Destroy(AllocatorTy &Allocator) {
+    // Free memory referenced by the item.
+    unsigned AllocSize =
+        static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1;
+    this->~StringMapEntry();
+    Allocator.Deallocate(static_cast<void *>(this), AllocSize);
+  }
+
+  /// Destroy this object, releasing memory back to the malloc allocator.
+  void Destroy() {
+    MallocAllocator A;
+    Destroy(A);
+  }
+};
+
+/// StringMap - This is an unconventional map that is specialized for handling
+/// keys that are "strings", which are basically ranges of bytes. This does some
+/// funky memory allocation and hashing things to make it extremely efficient,
+/// storing the string data *after* the value in the map.
+template<typename ValueTy, typename AllocatorTy = MallocAllocator>
+class StringMap : public StringMapImpl {
+  AllocatorTy Allocator;
+
+public:
+  typedef StringMapEntry<ValueTy> MapEntryTy;
+
+  StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
+  explicit StringMap(unsigned InitialSize)
+    : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
+
+  explicit StringMap(AllocatorTy A)
+    : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
+
+  StringMap(unsigned InitialSize, AllocatorTy A)
+    : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
+      Allocator(A) {}
+
+  StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List)
+      : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
+    for (const auto &P : List) {
+      insert(P);
+    }
+  }
+
+  StringMap(StringMap &&RHS)
+      : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
+
+  StringMap &operator=(StringMap RHS) {
+    StringMapImpl::swap(RHS);
+    std::swap(Allocator, RHS.Allocator);
+    return *this;
+  }
+
+  StringMap(const StringMap &RHS) :
+    StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
+    Allocator(RHS.Allocator) {
+    if (RHS.empty())
+      return;
+
+    // Allocate TheTable of the same size as RHS's TheTable, and set the
+    // sentinel appropriately (and NumBuckets).
+    init(RHS.NumBuckets);
+    unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1),
+             *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1);
+
+    NumItems = RHS.NumItems;
+    NumTombstones = RHS.NumTombstones;
+    for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+      StringMapEntryBase *Bucket = RHS.TheTable[I];
+      if (!Bucket || Bucket == getTombstoneVal()) {
+        TheTable[I] = Bucket;
+        continue;
+      }
+
+      TheTable[I] = MapEntryTy::Create(
+          static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
+          static_cast<MapEntryTy *>(Bucket)->getValue());
+      HashTable[I] = RHSHashTable[I];
+    }
+
+    // Note that here we've copied everything from the RHS into this object,
+    // tombstones included. We could, instead, have re-probed for each key to
+    // instantiate this new object without any tombstone buckets. The
+    // assumption here is that items are rarely deleted from most StringMaps,
+    // and so tombstones are rare, so the cost of re-probing for all inputs is
+    // not worthwhile.
+  }
+
+  AllocatorTy &getAllocator() { return Allocator; }
+  const AllocatorTy &getAllocator() const { return Allocator; }
+
+  typedef const char* key_type;
+  typedef ValueTy mapped_type;
+  typedef StringMapEntry<ValueTy> value_type;
+  typedef size_t size_type;
+
+  typedef StringMapConstIterator<ValueTy> const_iterator;
+  typedef StringMapIterator<ValueTy> iterator;
+
+  iterator begin() {
+    return iterator(TheTable, NumBuckets == 0);
+  }
+  iterator end() {
+    return iterator(TheTable+NumBuckets, true);
+  }
+  const_iterator begin() const {
+    return const_iterator(TheTable, NumBuckets == 0);
+  }
+  const_iterator end() const {
+    return const_iterator(TheTable+NumBuckets, true);
+  }
+
+  iterator find(StringRef Key) {
+    int Bucket = FindKey(Key);
+    if (Bucket == -1) return end();
+    return iterator(TheTable+Bucket, true);
+  }
+
+  const_iterator find(StringRef Key) const {
+    int Bucket = FindKey(Key);
+    if (Bucket == -1) return end();
+    return const_iterator(TheTable+Bucket, true);
+  }
+
+  /// lookup - Return the entry for the specified key, or a default
+  /// constructed value if no such entry exists.
+  ValueTy lookup(StringRef Key) const {
+    const_iterator it = find(Key);
+    if (it != end())
+      return it->second;
+    return ValueTy();
+  }
+
+  /// Lookup the ValueTy for the \p Key, or create a default constructed value
+  /// if the key is not in the map.
+  ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; }
+
+  /// count - Return 1 if the element is in the map, 0 otherwise.
+  size_type count(StringRef Key) const {
+    return find(Key) == end() ? 0 : 1;
+  }
+
+  /// insert - Insert the specified key/value pair into the map.  If the key
+  /// already exists in the map, return false and ignore the request, otherwise
+  /// insert it and return true.
+  bool insert(MapEntryTy *KeyValue) {
+    unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
+    StringMapEntryBase *&Bucket = TheTable[BucketNo];
+    if (Bucket && Bucket != getTombstoneVal())
+      return false;  // Already exists in map.
+
+    if (Bucket == getTombstoneVal())
+      --NumTombstones;
+    Bucket = KeyValue;
+    ++NumItems;
+    assert(NumItems + NumTombstones <= NumBuckets);
+
+    RehashTable();
+    return true;
+  }
+
+  /// insert - Inserts the specified key/value pair into the map if the key
+  /// isn't already in the map. The bool component of the returned pair is true
+  /// if and only if the insertion takes place, and the iterator component of
+  /// the pair points to the element with key equivalent to the key of the pair.
+  std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
+    return try_emplace(KV.first, std::move(KV.second));
+  }
+
+  /// Emplace a new element for the specified key into the map if the key isn't
+  /// already in the map. The bool component of the returned pair is true
+  /// if and only if the insertion takes place, and the iterator component of
+  /// the pair points to the element with key equivalent to the key of the pair.
+  template <typename... ArgsTy>
+  std::pair<iterator, bool> try_emplace(StringRef Key, ArgsTy &&... Args) {
+    unsigned BucketNo = LookupBucketFor(Key);
+    StringMapEntryBase *&Bucket = TheTable[BucketNo];
+    if (Bucket && Bucket != getTombstoneVal())
+      return std::make_pair(iterator(TheTable + BucketNo, false),
+                            false); // Already exists in map.
+
+    if (Bucket == getTombstoneVal())
+      --NumTombstones;
+    Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
+    ++NumItems;
+    assert(NumItems + NumTombstones <= NumBuckets);
+
+    BucketNo = RehashTable(BucketNo);
+    return std::make_pair(iterator(TheTable + BucketNo, false), true);
+  }
+
+  // clear - Empties out the StringMap
+  void clear() {
+    if (empty()) return;
+
+    // Zap all values, resetting the keys back to non-present (not tombstone),
+    // which is safe because we're removing all elements.
+    for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+      StringMapEntryBase *&Bucket = TheTable[I];
+      if (Bucket && Bucket != getTombstoneVal()) {
+        static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
+      }
+      Bucket = nullptr;
+    }
+
+    NumItems = 0;
+    NumTombstones = 0;
+  }
+
+  /// remove - Remove the specified key/value pair from the map, but do not
+  /// erase it.  This aborts if the key is not in the map.
+  void remove(MapEntryTy *KeyValue) {
+    RemoveKey(KeyValue);
+  }
+
+  void erase(iterator I) {
+    MapEntryTy &V = *I;
+    remove(&V);
+    V.Destroy(Allocator);
+  }
+
+  bool erase(StringRef Key) {
+    iterator I = find(Key);
+    if (I == end()) return false;
+    erase(I);
+    return true;
+  }
+
+  ~StringMap() {
+    // Delete all the elements in the map, but don't reset the elements
+    // to default values.  This is a copy of clear(), but avoids unnecessary
+    // work not required in the destructor.
+    if (!empty()) {
+      for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+        StringMapEntryBase *Bucket = TheTable[I];
+        if (Bucket && Bucket != getTombstoneVal()) {
+          static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
+        }
+      }
+    }
+    free(TheTable);
+  }
+};
+
+template <typename ValueTy> class StringMapConstIterator {
+protected:
+  StringMapEntryBase **Ptr;
+
+public:
+  typedef StringMapEntry<ValueTy> value_type;
+
+  StringMapConstIterator() : Ptr(nullptr) { }
+
+  explicit StringMapConstIterator(StringMapEntryBase **Bucket,
+                                  bool NoAdvance = false)
+  : Ptr(Bucket) {
+    if (!NoAdvance) AdvancePastEmptyBuckets();
+  }
+
+  const value_type &operator*() const {
+    return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
+  }
+  const value_type *operator->() const {
+    return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
+  }
+
+  bool operator==(const StringMapConstIterator &RHS) const {
+    return Ptr == RHS.Ptr;
+  }
+  bool operator!=(const StringMapConstIterator &RHS) const {
+    return Ptr != RHS.Ptr;
+  }
+
+  inline StringMapConstIterator& operator++() {   // Preincrement
+    ++Ptr;
+    AdvancePastEmptyBuckets();
+    return *this;
+  }
+  StringMapConstIterator operator++(int) {        // Postincrement
+    StringMapConstIterator tmp = *this; ++*this; return tmp;
+  }
+
+private:
+  void AdvancePastEmptyBuckets() {
+    while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
+      ++Ptr;
+  }
+};
+
+template<typename ValueTy>
+class StringMapIterator : public StringMapConstIterator<ValueTy> {
+public:
+  StringMapIterator() {}
+  explicit StringMapIterator(StringMapEntryBase **Bucket,
+                             bool NoAdvance = false)
+    : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
+  }
+  StringMapEntry<ValueTy> &operator*() const {
+    return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
+  }
+  StringMapEntry<ValueTy> *operator->() const {
+    return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
+  }
+};
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringRef.h b/third_party/llvm-subzero/include/llvm/ADT/StringRef.h
new file mode 100644
index 0000000..37c214c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/StringRef.h
@@ -0,0 +1,693 @@
+//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGREF_H
+#define LLVM_ADT_STRINGREF_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <limits>
+#include <string>
+#include <utility>
+
+namespace llvm {
+  template <typename T>
+  class SmallVectorImpl;
+  class APInt;
+  class hash_code;
+  class StringRef;
+
+  /// Helper functions for StringRef::getAsInteger.
+  bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
+                            unsigned long long &Result);
+
+  bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result);
+
+  /// StringRef - Represent a constant reference to a string, i.e. a character
+  /// array and a length, which need not be null terminated.
+  ///
+  /// This class does not own the string data, it is expected to be used in
+  /// situations where the character data resides in some other buffer, whose
+  /// lifetime extends past that of the StringRef. For this reason, it is not in
+  /// general safe to store a StringRef.
+  class StringRef {
+  public:
+    typedef const char *iterator;
+    typedef const char *const_iterator;
+    static const size_t npos = ~size_t(0);
+    typedef size_t size_type;
+
+  private:
+    /// The start of the string, in an external buffer.
+    const char *Data;
+
+    /// The length of the string.
+    size_t Length;
+
+    // Workaround memcmp issue with null pointers (undefined behavior)
+    // by providing a specialized version
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
+      if (Length == 0) { return 0; }
+      return ::memcmp(Lhs,Rhs,Length);
+    }
+
+  public:
+    /// @name Constructors
+    /// @{
+
+    /// Construct an empty string ref.
+    /*implicit*/ StringRef() : Data(nullptr), Length(0) {}
+
+    /// Construct a string ref from a cstring.
+    /*implicit*/ StringRef(const char *Str)
+      : Data(Str) {
+        assert(Str && "StringRef cannot be built from a NULL argument");
+        Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior
+      }
+
+    /// Construct a string ref from a pointer and length.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    /*implicit*/ StringRef(const char *data, size_t length)
+      : Data(data), Length(length) {
+        assert((data || length == 0) &&
+        "StringRef cannot be built from a NULL argument with non-null length");
+      }
+
+    /// Construct a string ref from an std::string.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    /*implicit*/ StringRef(const std::string &Str)
+      : Data(Str.data()), Length(Str.length()) {}
+
+    /// @}
+    /// @name Iterators
+    /// @{
+
+    iterator begin() const { return Data; }
+
+    iterator end() const { return Data + Length; }
+
+    const unsigned char *bytes_begin() const {
+      return reinterpret_cast<const unsigned char *>(begin());
+    }
+    const unsigned char *bytes_end() const {
+      return reinterpret_cast<const unsigned char *>(end());
+    }
+    iterator_range<const unsigned char *> bytes() const {
+      return make_range(bytes_begin(), bytes_end());
+    }
+
+    /// @}
+    /// @name String Operations
+    /// @{
+
+    /// data - Get a pointer to the start of the string (which may not be null
+    /// terminated).
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    const char *data() const { return Data; }
+
+    /// empty - Check if the string is empty.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    bool empty() const { return Length == 0; }
+
+    /// size - Get the string size.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    size_t size() const { return Length; }
+
+    /// front - Get the first character in the string.
+    char front() const {
+      assert(!empty());
+      return Data[0];
+    }
+
+    /// back - Get the last character in the string.
+    char back() const {
+      assert(!empty());
+      return Data[Length-1];
+    }
+
+    // copy - Allocate copy in Allocator and return StringRef to it.
+    template <typename Allocator> StringRef copy(Allocator &A) const {
+      // Don't request a length 0 copy from the allocator.
+      if (empty())
+        return StringRef();
+      char *S = A.template Allocate<char>(Length);
+      std::copy(begin(), end(), S);
+      return StringRef(S, Length);
+    }
+
+    /// equals - Check for string equality, this is more efficient than
+    /// compare() when the relative ordering of inequal strings isn't needed.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    bool equals(StringRef RHS) const {
+      return (Length == RHS.Length &&
+              compareMemory(Data, RHS.Data, RHS.Length) == 0);
+    }
+
+    /// equals_lower - Check for string equality, ignoring case.
+    bool equals_lower(StringRef RHS) const {
+      return Length == RHS.Length && compare_lower(RHS) == 0;
+    }
+
+    /// compare - Compare two strings; the result is -1, 0, or 1 if this string
+    /// is lexicographically less than, equal to, or greater than the \p RHS.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    int compare(StringRef RHS) const {
+      // Check the prefix for a mismatch.
+      if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length)))
+        return Res < 0 ? -1 : 1;
+
+      // Otherwise the prefixes match, so we only need to check the lengths.
+      if (Length == RHS.Length)
+        return 0;
+      return Length < RHS.Length ? -1 : 1;
+    }
+
+    /// compare_lower - Compare two strings, ignoring case.
+    int compare_lower(StringRef RHS) const;
+
+    /// compare_numeric - Compare two strings, treating sequences of digits as
+    /// numbers.
+    int compare_numeric(StringRef RHS) const;
+
+    /// \brief Determine the edit distance between this string and another
+    /// string.
+    ///
+    /// \param Other the string to compare this string against.
+    ///
+    /// \param AllowReplacements whether to allow character
+    /// replacements (change one character into another) as a single
+    /// operation, rather than as two operations (an insertion and a
+    /// removal).
+    ///
+    /// \param MaxEditDistance If non-zero, the maximum edit distance that
+    /// this routine is allowed to compute. If the edit distance will exceed
+    /// that maximum, returns \c MaxEditDistance+1.
+    ///
+    /// \returns the minimum number of character insertions, removals,
+    /// or (if \p AllowReplacements is \c true) replacements needed to
+    /// transform one of the given strings into the other. If zero,
+    /// the strings are identical.
+    unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
+                           unsigned MaxEditDistance = 0) const;
+
+    /// str - Get the contents as an std::string.
+    std::string str() const {
+      if (!Data) return std::string();
+      return std::string(Data, Length);
+    }
+
+    /// @}
+    /// @name Operator Overloads
+    /// @{
+
+    char operator[](size_t Index) const {
+      assert(Index < Length && "Invalid index!");
+      return Data[Index];
+    }
+
+    /// @}
+    /// @name Type Conversions
+    /// @{
+
+    operator std::string() const {
+      return str();
+    }
+
+    /// @}
+    /// @name String Predicates
+    /// @{
+
+    /// Check if this string starts with the given \p Prefix.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    bool startswith(StringRef Prefix) const {
+      return Length >= Prefix.Length &&
+             compareMemory(Data, Prefix.Data, Prefix.Length) == 0;
+    }
+
+    /// Check if this string starts with the given \p Prefix, ignoring case.
+    bool startswith_lower(StringRef Prefix) const;
+
+    /// Check if this string ends with the given \p Suffix.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    bool endswith(StringRef Suffix) const {
+      return Length >= Suffix.Length &&
+        compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
+    }
+
+    /// Check if this string ends with the given \p Suffix, ignoring case.
+    bool endswith_lower(StringRef Suffix) const;
+
+    /// @}
+    /// @name String Searching
+    /// @{
+
+    /// Search for the first character \p C in the string.
+    ///
+    /// \returns The index of the first occurrence of \p C, or npos if not
+    /// found.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    size_t find(char C, size_t From = 0) const {
+      size_t FindBegin = std::min(From, Length);
+      if (FindBegin < Length) { // Avoid calling memchr with nullptr.
+        // Just forward to memchr, which is faster than a hand-rolled loop.
+        if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin))
+          return static_cast<const char *>(P) - Data;
+      }
+      return npos;
+    }
+
+    /// Search for the first string \p Str in the string.
+    ///
+    /// \returns The index of the first occurrence of \p Str, or npos if not
+    /// found.
+    size_t find(StringRef Str, size_t From = 0) const;
+
+    /// Search for the last character \p C in the string.
+    ///
+    /// \returns The index of the last occurrence of \p C, or npos if not
+    /// found.
+    size_t rfind(char C, size_t From = npos) const {
+      From = std::min(From, Length);
+      size_t i = From;
+      while (i != 0) {
+        --i;
+        if (Data[i] == C)
+          return i;
+      }
+      return npos;
+    }
+
+    /// Search for the last string \p Str in the string.
+    ///
+    /// \returns The index of the last occurrence of \p Str, or npos if not
+    /// found.
+    size_t rfind(StringRef Str) const;
+
+    /// Find the first character in the string that is \p C, or npos if not
+    /// found. Same as find.
+    size_t find_first_of(char C, size_t From = 0) const {
+      return find(C, From);
+    }
+
+    /// Find the first character in the string that is in \p Chars, or npos if
+    /// not found.
+    ///
+    /// Complexity: O(size() + Chars.size())
+    size_t find_first_of(StringRef Chars, size_t From = 0) const;
+
+    /// Find the first character in the string that is not \p C or npos if not
+    /// found.
+    size_t find_first_not_of(char C, size_t From = 0) const;
+
+    /// Find the first character in the string that is not in the string
+    /// \p Chars, or npos if not found.
+    ///
+    /// Complexity: O(size() + Chars.size())
+    size_t find_first_not_of(StringRef Chars, size_t From = 0) const;
+
+    /// Find the last character in the string that is \p C, or npos if not
+    /// found.
+    size_t find_last_of(char C, size_t From = npos) const {
+      return rfind(C, From);
+    }
+
+    /// Find the last character in the string that is in \p C, or npos if not
+    /// found.
+    ///
+    /// Complexity: O(size() + Chars.size())
+    size_t find_last_of(StringRef Chars, size_t From = npos) const;
+
+    /// Find the last character in the string that is not \p C, or npos if not
+    /// found.
+    size_t find_last_not_of(char C, size_t From = npos) const;
+
+    /// Find the last character in the string that is not in \p Chars, or
+    /// npos if not found.
+    ///
+    /// Complexity: O(size() + Chars.size())
+    size_t find_last_not_of(StringRef Chars, size_t From = npos) const;
+
+    /// Return true if the given string is a substring of *this, and false
+    /// otherwise.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    bool contains(StringRef Other) const { return find(Other) != npos; }
+
+    /// @}
+    /// @name Helpful Algorithms
+    /// @{
+
+    /// Return the number of occurrences of \p C in the string.
+    size_t count(char C) const {
+      size_t Count = 0;
+      for (size_t i = 0, e = Length; i != e; ++i)
+        if (Data[i] == C)
+          ++Count;
+      return Count;
+    }
+
+    /// Return the number of non-overlapped occurrences of \p Str in
+    /// the string.
+    size_t count(StringRef Str) const;
+
+    /// Parse the current string as an integer of the specified radix.  If
+    /// \p Radix is specified as zero, this does radix autosensing using
+    /// extended C rules: 0 is octal, 0x is hex, 0b is binary.
+    ///
+    /// If the string is invalid or if only a subset of the string is valid,
+    /// this returns true to signify the error.  The string is considered
+    /// erroneous if empty or if it overflows T.
+    template <typename T>
+    typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+    getAsInteger(unsigned Radix, T &Result) const {
+      long long LLVal;
+      if (getAsSignedInteger(*this, Radix, LLVal) ||
+            static_cast<T>(LLVal) != LLVal)
+        return true;
+      Result = LLVal;
+      return false;
+    }
+
+    template <typename T>
+    typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+    getAsInteger(unsigned Radix, T &Result) const {
+      unsigned long long ULLVal;
+      // The additional cast to unsigned long long is required to avoid the
+      // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type
+      // 'unsigned __int64' when instantiating getAsInteger with T = bool.
+      if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
+          static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
+        return true;
+      Result = ULLVal;
+      return false;
+    }
+
+    /// Parse the current string as an integer of the specified \p Radix, or of
+    /// an autosensed radix if the \p Radix given is 0.  The current value in
+    /// \p Result is discarded, and the storage is changed to be wide enough to
+    /// store the parsed integer.
+    ///
+    /// \returns true if the string does not solely consist of a valid
+    /// non-empty number in the appropriate base.
+    ///
+    /// APInt::fromString is superficially similar but assumes the
+    /// string is well-formed in the given radix.
+    bool getAsInteger(unsigned Radix, APInt &Result) const;
+
+    /// @}
+    /// @name String Operations
+    /// @{
+
+    // Convert the given ASCII string to lowercase.
+    std::string lower() const;
+
+    /// Convert the given ASCII string to uppercase.
+    std::string upper() const;
+
+    /// @}
+    /// @name Substring Operations
+    /// @{
+
+    /// Return a reference to the substring from [Start, Start + N).
+    ///
+    /// \param Start The index of the starting character in the substring; if
+    /// the index is npos or greater than the length of the string then the
+    /// empty substring will be returned.
+    ///
+    /// \param N The number of characters to included in the substring. If N
+    /// exceeds the number of characters remaining in the string, the string
+    /// suffix (starting with \p Start) will be returned.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef substr(size_t Start, size_t N = npos) const {
+      Start = std::min(Start, Length);
+      return StringRef(Data + Start, std::min(N, Length - Start));
+    }
+
+    /// Return a StringRef equal to 'this' but with only the first \p N
+    /// elements remaining.  If \p N is greater than the length of the
+    /// string, the entire string is returned.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef take_front(size_t N = 1) const {
+      if (N >= size())
+        return *this;
+      return drop_back(size() - N);
+    }
+
+    /// Return a StringRef equal to 'this' but with only the first \p N
+    /// elements remaining.  If \p N is greater than the length of the
+    /// string, the entire string is returned.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef take_back(size_t N = 1) const {
+      if (N >= size())
+        return *this;
+      return drop_front(size() - N);
+    }
+
+    /// Return a StringRef equal to 'this' but with the first \p N elements
+    /// dropped.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef drop_front(size_t N = 1) const {
+      assert(size() >= N && "Dropping more elements than exist");
+      return substr(N);
+    }
+
+    /// Return a StringRef equal to 'this' but with the last \p N elements
+    /// dropped.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef drop_back(size_t N = 1) const {
+      assert(size() >= N && "Dropping more elements than exist");
+      return substr(0, size()-N);
+    }
+
+    /// Returns true if this StringRef has the given prefix and removes that
+    /// prefix.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    bool consume_front(StringRef Prefix) {
+      if (!startswith(Prefix))
+        return false;
+
+      *this = drop_front(Prefix.size());
+      return true;
+    }
+
+    /// Returns true if this StringRef has the given suffix and removes that
+    /// suffix.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    bool consume_back(StringRef Suffix) {
+      if (!endswith(Suffix))
+        return false;
+
+      *this = drop_back(Suffix.size());
+      return true;
+    }
+
+    /// Return a reference to the substring from [Start, End).
+    ///
+    /// \param Start The index of the starting character in the substring; if
+    /// the index is npos or greater than the length of the string then the
+    /// empty substring will be returned.
+    ///
+    /// \param End The index following the last character to include in the
+    /// substring. If this is npos or exceeds the number of characters
+    /// remaining in the string, the string suffix (starting with \p Start)
+    /// will be returned. If this is less than \p Start, an empty string will
+    /// be returned.
+    LLVM_ATTRIBUTE_ALWAYS_INLINE
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef slice(size_t Start, size_t End) const {
+      Start = std::min(Start, Length);
+      End = std::min(std::max(Start, End), Length);
+      return StringRef(Data + Start, End - Start);
+    }
+
+    /// Split into two substrings around the first occurrence of a separator
+    /// character.
+    ///
+    /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+    /// such that (*this == LHS + Separator + RHS) is true and RHS is
+    /// maximal. If \p Separator is not in the string, then the result is a
+    /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+    ///
+    /// \param Separator The character to split on.
+    /// \returns The split substrings.
+    std::pair<StringRef, StringRef> split(char Separator) const {
+      size_t Idx = find(Separator);
+      if (Idx == npos)
+        return std::make_pair(*this, StringRef());
+      return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
+    }
+
+    /// Split into two substrings around the first occurrence of a separator
+    /// string.
+    ///
+    /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+    /// such that (*this == LHS + Separator + RHS) is true and RHS is
+    /// maximal. If \p Separator is not in the string, then the result is a
+    /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+    ///
+    /// \param Separator - The string to split on.
+    /// \return - The split substrings.
+    std::pair<StringRef, StringRef> split(StringRef Separator) const {
+      size_t Idx = find(Separator);
+      if (Idx == npos)
+        return std::make_pair(*this, StringRef());
+      return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
+    }
+
+    /// Split into substrings around the occurrences of a separator string.
+    ///
+    /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
+    /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1
+    /// elements are added to A.
+    /// If \p KeepEmpty is false, empty strings are not added to \p A. They
+    /// still count when considering \p MaxSplit
+    /// An useful invariant is that
+    /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
+    ///
+    /// \param A - Where to put the substrings.
+    /// \param Separator - The string to split on.
+    /// \param MaxSplit - The maximum number of times the string is split.
+    /// \param KeepEmpty - True if empty substring should be added.
+    void split(SmallVectorImpl<StringRef> &A,
+               StringRef Separator, int MaxSplit = -1,
+               bool KeepEmpty = true) const;
+
+    /// Split into substrings around the occurrences of a separator character.
+    ///
+    /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
+    /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1
+    /// elements are added to A.
+    /// If \p KeepEmpty is false, empty strings are not added to \p A. They
+    /// still count when considering \p MaxSplit
+    /// An useful invariant is that
+    /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
+    ///
+    /// \param A - Where to put the substrings.
+    /// \param Separator - The string to split on.
+    /// \param MaxSplit - The maximum number of times the string is split.
+    /// \param KeepEmpty - True if empty substring should be added.
+    void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1,
+               bool KeepEmpty = true) const;
+
+    /// Split into two substrings around the last occurrence of a separator
+    /// character.
+    ///
+    /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+    /// such that (*this == LHS + Separator + RHS) is true and RHS is
+    /// minimal. If \p Separator is not in the string, then the result is a
+    /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+    ///
+    /// \param Separator - The character to split on.
+    /// \return - The split substrings.
+    std::pair<StringRef, StringRef> rsplit(char Separator) const {
+      size_t Idx = rfind(Separator);
+      if (Idx == npos)
+        return std::make_pair(*this, StringRef());
+      return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
+    }
+
+    /// Return string with consecutive \p Char characters starting from the
+    /// the left removed.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef ltrim(char Char) const {
+      return drop_front(std::min(Length, find_first_not_of(Char)));
+    }
+
+    /// Return string with consecutive characters in \p Chars starting from
+    /// the left removed.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const {
+      return drop_front(std::min(Length, find_first_not_of(Chars)));
+    }
+
+    /// Return string with consecutive \p Char characters starting from the
+    /// right removed.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef rtrim(char Char) const {
+      return drop_back(Length - std::min(Length, find_last_not_of(Char) + 1));
+    }
+
+    /// Return string with consecutive characters in \p Chars starting from
+    /// the right removed.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const {
+      return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1));
+    }
+
+    /// Return string with consecutive \p Char characters starting from the
+    /// left and right removed.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef trim(char Char) const {
+      return ltrim(Char).rtrim(Char);
+    }
+
+    /// Return string with consecutive characters in \p Chars starting from
+    /// the left and right removed.
+    LLVM_ATTRIBUTE_UNUSED_RESULT
+    StringRef trim(StringRef Chars = " \t\n\v\f\r") const {
+      return ltrim(Chars).rtrim(Chars);
+    }
+
+    /// @}
+  };
+
+  /// @name StringRef Comparison Operators
+  /// @{
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  inline bool operator==(StringRef LHS, StringRef RHS) {
+    return LHS.equals(RHS);
+  }
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  inline bool operator!=(StringRef LHS, StringRef RHS) {
+    return !(LHS == RHS);
+  }
+
+  inline bool operator<(StringRef LHS, StringRef RHS) {
+    return LHS.compare(RHS) == -1;
+  }
+
+  inline bool operator<=(StringRef LHS, StringRef RHS) {
+    return LHS.compare(RHS) != 1;
+  }
+
+  inline bool operator>(StringRef LHS, StringRef RHS) {
+    return LHS.compare(RHS) == 1;
+  }
+
+  inline bool operator>=(StringRef LHS, StringRef RHS) {
+    return LHS.compare(RHS) != -1;
+  }
+
+  inline std::string &operator+=(std::string &buffer, StringRef string) {
+    return buffer.append(string.data(), string.size());
+  }
+
+  /// @}
+
+  /// \brief Compute a hash_code for a StringRef.
+  hash_code hash_value(StringRef S);
+
+  // StringRefs can be treated like a POD type.
+  template <typename T> struct isPodLike;
+  template <> struct isPodLike<StringRef> { static const bool value = true; };
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringSwitch.h b/third_party/llvm-subzero/include/llvm/ADT/StringSwitch.h
new file mode 100644
index 0000000..bd200fc
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/StringSwitch.h
@@ -0,0 +1,181 @@
+//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements the StringSwitch template, which mimics a switch()
+//  statement whose cases are string literals.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_ADT_STRINGSWITCH_H
+#define LLVM_ADT_STRINGSWITCH_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstring>
+
+namespace llvm {
+
+/// \brief A switch()-like statement whose cases are string literals.
+///
+/// The StringSwitch class is a simple form of a switch() statement that
+/// determines whether the given string matches one of the given string
+/// literals. The template type parameter \p T is the type of the value that
+/// will be returned from the string-switch expression. For example,
+/// the following code switches on the name of a color in \c argv[i]:
+///
+/// \code
+/// Color color = StringSwitch<Color>(argv[i])
+///   .Case("red", Red)
+///   .Case("orange", Orange)
+///   .Case("yellow", Yellow)
+///   .Case("green", Green)
+///   .Case("blue", Blue)
+///   .Case("indigo", Indigo)
+///   .Cases("violet", "purple", Violet)
+///   .Default(UnknownColor);
+/// \endcode
+template<typename T, typename R = T>
+class StringSwitch {
+  /// \brief The string we are matching.
+  StringRef Str;
+
+  /// \brief The pointer to the result of this switch statement, once known,
+  /// null before that.
+  const T *Result;
+
+public:
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  explicit StringSwitch(StringRef S)
+  : Str(S), Result(nullptr) { }
+
+  // StringSwitch is not copyable.
+  StringSwitch(const StringSwitch &) = delete;
+  void operator=(const StringSwitch &) = delete;
+
+  StringSwitch(StringSwitch &&other) {
+    *this = std::move(other);
+  }
+  StringSwitch &operator=(StringSwitch &&other) {
+    Str = other.Str;
+    Result = other.Result;
+    return *this;
+  }
+
+  ~StringSwitch() = default;
+
+  template<unsigned N>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& Case(const char (&S)[N], const T& Value) {
+    if (!Result && N-1 == Str.size() &&
+        (std::memcmp(S, Str.data(), N-1) == 0)) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  template<unsigned N>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
+    if (!Result && Str.size() >= N-1 &&
+        std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  template<unsigned N>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
+    if (!Result && Str.size() >= N-1 &&
+        std::memcmp(S, Str.data(), N-1) == 0) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  template<unsigned N0, unsigned N1>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
+                      const T& Value) {
+    if (!Result && (
+        (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) ||
+        (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0))) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  template<unsigned N0, unsigned N1, unsigned N2>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
+                      const char (&S2)[N2], const T& Value) {
+    if (!Result && (
+        (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) ||
+        (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0) ||
+        (N2-1 == Str.size() && std::memcmp(S2, Str.data(), N2-1) == 0))) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
+                      const char (&S2)[N2], const char (&S3)[N3],
+                      const T& Value) {
+    if (!Result && (
+        (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) ||
+        (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0) ||
+        (N2-1 == Str.size() && std::memcmp(S2, Str.data(), N2-1) == 0) ||
+        (N3-1 == Str.size() && std::memcmp(S3, Str.data(), N3-1) == 0))) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
+                      const char (&S2)[N2], const char (&S3)[N3],
+                      const char (&S4)[N4], const T& Value) {
+    if (!Result && (
+        (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) ||
+        (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0) ||
+        (N2-1 == Str.size() && std::memcmp(S2, Str.data(), N2-1) == 0) ||
+        (N3-1 == Str.size() && std::memcmp(S3, Str.data(), N3-1) == 0) ||
+        (N4-1 == Str.size() && std::memcmp(S4, Str.data(), N4-1) == 0))) {
+      Result = &Value;
+    }
+
+    return *this;
+  }
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  R Default(const T& Value) const {
+    if (Result)
+      return *Result;
+
+    return Value;
+  }
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE
+  operator R() const {
+    assert(Result && "Fell off the end of a string-switch");
+    return *Result;
+  }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGSWITCH_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Triple.h b/third_party/llvm-subzero/include/llvm/ADT/Triple.h
new file mode 100644
index 0000000..b98f840
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/Triple.h
@@ -0,0 +1,727 @@
+//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_TRIPLE_H
+#define LLVM_ADT_TRIPLE_H
+
+#include "llvm/ADT/Twine.h"
+
+// Some system headers or GCC predefined macros conflict with identifiers in
+// this file.  Undefine them here.
+#undef NetBSD
+#undef mips
+#undef sparc
+
+namespace llvm {
+
+/// Triple - Helper class for working with autoconf configuration names. For
+/// historical reasons, we also call these 'triples' (they used to contain
+/// exactly three fields).
+///
+/// Configuration names are strings in the canonical form:
+///   ARCHITECTURE-VENDOR-OPERATING_SYSTEM
+/// or
+///   ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT
+///
+/// This class is used for clients which want to support arbitrary
+/// configuration names, but also want to implement certain special
+/// behavior for particular configurations. This class isolates the mapping
+/// from the components of the configuration name to well known IDs.
+///
+/// At its core the Triple class is designed to be a wrapper for a triple
+/// string; the constructor does not change or normalize the triple string.
+/// Clients that need to handle the non-canonical triples that users often
+/// specify should use the normalize method.
+///
+/// See autoconf/config.guess for a glimpse into what configuration names
+/// look like in practice.
+class Triple {
+public:
+  enum ArchType {
+    UnknownArch,
+
+    arm,            // ARM (little endian): arm, armv.*, xscale
+    armeb,          // ARM (big endian): armeb
+    aarch64,        // AArch64 (little endian): aarch64
+    aarch64_be,     // AArch64 (big endian): aarch64_be
+    avr,            // AVR: Atmel AVR microcontroller
+    bpfel,          // eBPF or extended BPF or 64-bit BPF (little endian)
+    bpfeb,          // eBPF or extended BPF or 64-bit BPF (big endian)
+    hexagon,        // Hexagon: hexagon
+    mips,           // MIPS: mips, mipsallegrex
+    mipsel,         // MIPSEL: mipsel, mipsallegrexel
+    mips64,         // MIPS64: mips64
+    mips64el,       // MIPS64EL: mips64el
+    msp430,         // MSP430: msp430
+    ppc,            // PPC: powerpc
+    ppc64,          // PPC64: powerpc64, ppu
+    ppc64le,        // PPC64LE: powerpc64le
+    r600,           // R600: AMD GPUs HD2XXX - HD6XXX
+    amdgcn,         // AMDGCN: AMD GCN GPUs
+    sparc,          // Sparc: sparc
+    sparcv9,        // Sparcv9: Sparcv9
+    sparcel,        // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
+    systemz,        // SystemZ: s390x
+    tce,            // TCE (http://tce.cs.tut.fi/): tce
+    thumb,          // Thumb (little endian): thumb, thumbv.*
+    thumbeb,        // Thumb (big endian): thumbeb
+    x86,            // X86: i[3-9]86
+    x86_64,         // X86-64: amd64, x86_64
+    xcore,          // XCore: xcore
+    nvptx,          // NVPTX: 32-bit
+    nvptx64,        // NVPTX: 64-bit
+    le32,           // le32: generic little-endian 32-bit CPU (PNaCl)
+    le64,           // le64: generic little-endian 64-bit CPU (PNaCl)
+    amdil,          // AMDIL
+    amdil64,        // AMDIL with 64-bit pointers
+    hsail,          // AMD HSAIL
+    hsail64,        // AMD HSAIL with 64-bit pointers
+    spir,           // SPIR: standard portable IR for OpenCL 32-bit version
+    spir64,         // SPIR: standard portable IR for OpenCL 64-bit version
+    kalimba,        // Kalimba: generic kalimba
+    shave,          // SHAVE: Movidius vector VLIW processors
+    lanai,          // Lanai: Lanai 32-bit
+    wasm32,         // WebAssembly with 32-bit pointers
+    wasm64,         // WebAssembly with 64-bit pointers
+    renderscript32, // 32-bit RenderScript
+    renderscript64, // 64-bit RenderScript
+    LastArchType = renderscript64
+  };
+  enum SubArchType {
+    NoSubArch,
+
+    ARMSubArch_v8_2a,
+    ARMSubArch_v8_1a,
+    ARMSubArch_v8,
+    ARMSubArch_v8m_baseline,
+    ARMSubArch_v8m_mainline,
+    ARMSubArch_v7,
+    ARMSubArch_v7em,
+    ARMSubArch_v7m,
+    ARMSubArch_v7s,
+    ARMSubArch_v7k,
+    ARMSubArch_v6,
+    ARMSubArch_v6m,
+    ARMSubArch_v6k,
+    ARMSubArch_v6t2,
+    ARMSubArch_v5,
+    ARMSubArch_v5te,
+    ARMSubArch_v4t,
+
+    KalimbaSubArch_v3,
+    KalimbaSubArch_v4,
+    KalimbaSubArch_v5
+  };
+  enum VendorType {
+    UnknownVendor,
+
+    Apple,
+    PC,
+    SCEI,
+    BGP,
+    BGQ,
+    Freescale,
+    IBM,
+    ImaginationTechnologies,
+    MipsTechnologies,
+    NVIDIA,
+    CSR,
+    Myriad,
+    AMD,
+    Mesa,
+    LastVendorType = Mesa
+  };
+  enum OSType {
+    UnknownOS,
+
+    CloudABI,
+    Darwin,
+    DragonFly,
+    FreeBSD,
+    IOS,
+    KFreeBSD,
+    Linux,
+    Lv2,        // PS3
+    MacOSX,
+    NetBSD,
+    OpenBSD,
+    Solaris,
+    Win32,
+    Haiku,
+    Minix,
+    RTEMS,
+    NaCl,       // Native Client
+    CNK,        // BG/P Compute-Node Kernel
+    Bitrig,
+    AIX,
+    CUDA,       // NVIDIA CUDA
+    NVCL,       // NVIDIA OpenCL
+    AMDHSA,     // AMD HSA Runtime
+    PS4,
+    ELFIAMCU,
+    TvOS,       // Apple tvOS
+    WatchOS,    // Apple watchOS
+    Mesa3D,
+    LastOSType = Mesa3D
+  };
+  enum EnvironmentType {
+    UnknownEnvironment,
+
+    GNU,
+    GNUABI64,
+    GNUEABI,
+    GNUEABIHF,
+    GNUX32,
+    CODE16,
+    EABI,
+    EABIHF,
+    Android,
+    Musl,
+    MuslEABI,
+    MuslEABIHF,
+
+    MSVC,
+    Itanium,
+    Cygnus,
+    AMDOpenCL,
+    CoreCLR,
+    LastEnvironmentType = CoreCLR
+  };
+  enum ObjectFormatType {
+    UnknownObjectFormat,
+
+    COFF,
+    ELF,
+    MachO,
+  };
+
+private:
+  std::string Data;
+
+  /// The parsed arch type.
+  ArchType Arch;
+
+  /// The parsed subarchitecture type.
+  SubArchType SubArch;
+
+  /// The parsed vendor type.
+  VendorType Vendor;
+
+  /// The parsed OS type.
+  OSType OS;
+
+  /// The parsed Environment type.
+  EnvironmentType Environment;
+
+  /// The object format type.
+  ObjectFormatType ObjectFormat;
+
+public:
+  /// @name Constructors
+  /// @{
+
+  /// Default constructor is the same as an empty string and leaves all
+  /// triple fields unknown.
+  Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {}
+
+  explicit Triple(const Twine &Str);
+  Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr);
+  Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
+         const Twine &EnvironmentStr);
+
+  bool operator==(const Triple &Other) const {
+    return Arch == Other.Arch && SubArch == Other.SubArch &&
+           Vendor == Other.Vendor && OS == Other.OS &&
+           Environment == Other.Environment &&
+           ObjectFormat == Other.ObjectFormat;
+  }
+
+  /// @}
+  /// @name Normalization
+  /// @{
+
+  /// normalize - Turn an arbitrary machine specification into the canonical
+  /// triple form (or something sensible that the Triple class understands if
+  /// nothing better can reasonably be done).  In particular, it handles the
+  /// common case in which otherwise valid components are in the wrong order.
+  static std::string normalize(StringRef Str);
+
+  /// Return the normalized form of this triple's string.
+  std::string normalize() const { return normalize(Data); }
+
+  /// @}
+  /// @name Typed Component Access
+  /// @{
+
+  /// getArch - Get the parsed architecture type of this triple.
+  ArchType getArch() const { return Arch; }
+
+  /// getSubArch - get the parsed subarchitecture type for this triple.
+  SubArchType getSubArch() const { return SubArch; }
+
+  /// getVendor - Get the parsed vendor type of this triple.
+  VendorType getVendor() const { return Vendor; }
+
+  /// getOS - Get the parsed operating system type of this triple.
+  OSType getOS() const { return OS; }
+
+  /// hasEnvironment - Does this triple have the optional environment
+  /// (fourth) component?
+  bool hasEnvironment() const {
+    return getEnvironmentName() != "";
+  }
+
+  /// getEnvironment - Get the parsed environment type of this triple.
+  EnvironmentType getEnvironment() const { return Environment; }
+
+  /// Parse the version number from the OS name component of the
+  /// triple, if present.
+  ///
+  /// For example, "fooos1.2.3" would return (1, 2, 3).
+  ///
+  /// If an entry is not defined, it will be returned as 0.
+  void getEnvironmentVersion(unsigned &Major, unsigned &Minor,
+                             unsigned &Micro) const;
+
+  /// getFormat - Get the object format for this triple.
+  ObjectFormatType getObjectFormat() const { return ObjectFormat; }
+
+  /// getOSVersion - Parse the version number from the OS name component of the
+  /// triple, if present.
+  ///
+  /// For example, "fooos1.2.3" would return (1, 2, 3).
+  ///
+  /// If an entry is not defined, it will be returned as 0.
+  void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const;
+
+  /// getOSMajorVersion - Return just the major version number, this is
+  /// specialized because it is a common query.
+  unsigned getOSMajorVersion() const {
+    unsigned Maj, Min, Micro;
+    getOSVersion(Maj, Min, Micro);
+    return Maj;
+  }
+
+  /// getMacOSXVersion - Parse the version number as with getOSVersion and then
+  /// translate generic "darwin" versions to the corresponding OS X versions.
+  /// This may also be called with IOS triples but the OS X version number is
+  /// just set to a constant 10.4.0 in that case.  Returns true if successful.
+  bool getMacOSXVersion(unsigned &Major, unsigned &Minor,
+                        unsigned &Micro) const;
+
+  /// getiOSVersion - Parse the version number as with getOSVersion.  This should
+  /// only be called with IOS or generic triples.
+  void getiOSVersion(unsigned &Major, unsigned &Minor,
+                     unsigned &Micro) const;
+
+  /// getWatchOSVersion - Parse the version number as with getOSVersion.  This
+  /// should only be called with WatchOS or generic triples.
+  void getWatchOSVersion(unsigned &Major, unsigned &Minor,
+                         unsigned &Micro) const;
+
+  /// @}
+  /// @name Direct Component Access
+  /// @{
+
+  const std::string &str() const { return Data; }
+
+  const std::string &getTriple() const { return Data; }
+
+  /// getArchName - Get the architecture (first) component of the
+  /// triple.
+  StringRef getArchName() const;
+
+  /// getVendorName - Get the vendor (second) component of the triple.
+  StringRef getVendorName() const;
+
+  /// getOSName - Get the operating system (third) component of the
+  /// triple.
+  StringRef getOSName() const;
+
+  /// getEnvironmentName - Get the optional environment (fourth)
+  /// component of the triple, or "" if empty.
+  StringRef getEnvironmentName() const;
+
+  /// getOSAndEnvironmentName - Get the operating system and optional
+  /// environment components as a single string (separated by a '-'
+  /// if the environment component is present).
+  StringRef getOSAndEnvironmentName() const;
+
+  /// @}
+  /// @name Convenience Predicates
+  /// @{
+
+  /// Test whether the architecture is 64-bit
+  ///
+  /// Note that this tests for 64-bit pointer width, and nothing else. Note
+  /// that we intentionally expose only three predicates, 64-bit, 32-bit, and
+  /// 16-bit. The inner details of pointer width for particular architectures
+  /// is not summed up in the triple, and so only a coarse grained predicate
+  /// system is provided.
+  bool isArch64Bit() const;
+
+  /// Test whether the architecture is 32-bit
+  ///
+  /// Note that this tests for 32-bit pointer width, and nothing else.
+  bool isArch32Bit() const;
+
+  /// Test whether the architecture is 16-bit
+  ///
+  /// Note that this tests for 16-bit pointer width, and nothing else.
+  bool isArch16Bit() const;
+
+  /// isOSVersionLT - Helper function for doing comparisons against version
+  /// numbers included in the target triple.
+  bool isOSVersionLT(unsigned Major, unsigned Minor = 0,
+                     unsigned Micro = 0) const {
+    unsigned LHS[3];
+    getOSVersion(LHS[0], LHS[1], LHS[2]);
+
+    if (LHS[0] != Major)
+      return LHS[0] < Major;
+    if (LHS[1] != Minor)
+      return LHS[1] < Minor;
+    if (LHS[2] != Micro)
+      return LHS[1] < Micro;
+
+    return false;
+  }
+
+  bool isOSVersionLT(const Triple &Other) const {
+    unsigned RHS[3];
+    Other.getOSVersion(RHS[0], RHS[1], RHS[2]);
+    return isOSVersionLT(RHS[0], RHS[1], RHS[2]);
+  }
+
+  /// isMacOSXVersionLT - Comparison function for checking OS X version
+  /// compatibility, which handles supporting skewed version numbering schemes
+  /// used by the "darwin" triples.
+  bool isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
+                         unsigned Micro = 0) const {
+    assert(isMacOSX() && "Not an OS X triple!");
+
+    // If this is OS X, expect a sane version number.
+    if (getOS() == Triple::MacOSX)
+      return isOSVersionLT(Major, Minor, Micro);
+
+    // Otherwise, compare to the "Darwin" number.
+    assert(Major == 10 && "Unexpected major version");
+    return isOSVersionLT(Minor + 4, Micro, 0);
+  }
+
+  /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both
+  /// "darwin" and "osx" as OS X triples.
+  bool isMacOSX() const {
+    return getOS() == Triple::Darwin || getOS() == Triple::MacOSX;
+  }
+
+  /// Is this an iOS triple.
+  /// Note: This identifies tvOS as a variant of iOS. If that ever
+  /// changes, i.e., if the two operating systems diverge or their version
+  /// numbers get out of sync, that will need to be changed.
+  /// watchOS has completely different version numbers so it is not included.
+  bool isiOS() const {
+    return getOS() == Triple::IOS || isTvOS();
+  }
+
+  /// Is this an Apple tvOS triple.
+  bool isTvOS() const {
+    return getOS() == Triple::TvOS;
+  }
+
+  /// Is this an Apple watchOS triple.
+  bool isWatchOS() const {
+    return getOS() == Triple::WatchOS;
+  }
+
+  bool isWatchABI() const {
+    return getSubArch() == Triple::ARMSubArch_v7k;
+  }
+
+  /// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS).
+  bool isOSDarwin() const {
+    return isMacOSX() || isiOS() || isWatchOS();
+  }
+
+  bool isOSNetBSD() const {
+    return getOS() == Triple::NetBSD;
+  }
+
+  bool isOSOpenBSD() const {
+    return getOS() == Triple::OpenBSD;
+  }
+
+  bool isOSFreeBSD() const {
+    return getOS() == Triple::FreeBSD;
+  }
+
+  bool isOSDragonFly() const { return getOS() == Triple::DragonFly; }
+
+  bool isOSSolaris() const {
+    return getOS() == Triple::Solaris;
+  }
+
+  bool isOSBitrig() const {
+    return getOS() == Triple::Bitrig;
+  }
+
+  bool isOSIAMCU() const {
+    return getOS() == Triple::ELFIAMCU;
+  }
+
+  bool isGNUEnvironment() const {
+    EnvironmentType Env = getEnvironment();
+    return Env == Triple::GNU || Env == Triple::GNUABI64 ||
+           Env == Triple::GNUEABI || Env == Triple::GNUEABIHF ||
+           Env == Triple::GNUX32;
+  }
+
+  /// Checks if the environment could be MSVC.
+  bool isWindowsMSVCEnvironment() const {
+    return getOS() == Triple::Win32 &&
+           (getEnvironment() == Triple::UnknownEnvironment ||
+            getEnvironment() == Triple::MSVC);
+  }
+
+  /// Checks if the environment is MSVC.
+  bool isKnownWindowsMSVCEnvironment() const {
+    return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC;
+  }
+
+  bool isWindowsCoreCLREnvironment() const {
+    return getOS() == Triple::Win32 && getEnvironment() == Triple::CoreCLR;
+  }
+
+  bool isWindowsItaniumEnvironment() const {
+    return getOS() == Triple::Win32 && getEnvironment() == Triple::Itanium;
+  }
+
+  bool isWindowsCygwinEnvironment() const {
+    return getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus;
+  }
+
+  bool isWindowsGNUEnvironment() const {
+    return getOS() == Triple::Win32 && getEnvironment() == Triple::GNU;
+  }
+
+  /// Tests for either Cygwin or MinGW OS
+  bool isOSCygMing() const {
+    return isWindowsCygwinEnvironment() || isWindowsGNUEnvironment();
+  }
+
+  /// Is this a "Windows" OS targeting a "MSVCRT.dll" environment.
+  bool isOSMSVCRT() const {
+    return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() ||
+           isWindowsItaniumEnvironment();
+  }
+
+  /// Tests whether the OS is Windows.
+  bool isOSWindows() const {
+    return getOS() == Triple::Win32;
+  }
+
+  /// Tests whether the OS is NaCl (Native Client)
+  bool isOSNaCl() const {
+    return getOS() == Triple::NaCl;
+  }
+
+  /// Tests whether the OS is Linux.
+  bool isOSLinux() const {
+    return getOS() == Triple::Linux;
+  }
+
+  /// Tests whether the OS is kFreeBSD.
+  bool isOSKFreeBSD() const {
+    return getOS() == Triple::KFreeBSD;
+  }
+
+  /// Tests whether the OS uses glibc.
+  bool isOSGlibc() const {
+    return getOS() == Triple::Linux || getOS() == Triple::KFreeBSD;
+  }
+
+  /// Tests whether the OS uses the ELF binary format.
+  bool isOSBinFormatELF() const {
+    return getObjectFormat() == Triple::ELF;
+  }
+
+  /// Tests whether the OS uses the COFF binary format.
+  bool isOSBinFormatCOFF() const {
+    return getObjectFormat() == Triple::COFF;
+  }
+
+  /// Tests whether the environment is MachO.
+  bool isOSBinFormatMachO() const {
+    return getObjectFormat() == Triple::MachO;
+  }
+
+  /// Tests whether the target is the PS4 CPU
+  bool isPS4CPU() const {
+    return getArch() == Triple::x86_64 &&
+           getVendor() == Triple::SCEI &&
+           getOS() == Triple::PS4;
+  }
+
+  /// Tests whether the target is the PS4 platform
+  bool isPS4() const {
+    return getVendor() == Triple::SCEI &&
+           getOS() == Triple::PS4;
+  }
+
+  /// Tests whether the target is Android
+  bool isAndroid() const { return getEnvironment() == Triple::Android; }
+
+  /// Tests whether the environment is musl-libc
+  bool isMusl() const {
+    return getEnvironment() == Triple::Musl ||
+           getEnvironment() == Triple::MuslEABI ||
+           getEnvironment() == Triple::MuslEABIHF;
+  }
+
+  /// Tests whether the target is NVPTX (32- or 64-bit).
+  bool isNVPTX() const {
+    return getArch() == Triple::nvptx || getArch() == Triple::nvptx64;
+  }
+
+  /// Tests wether the target supports comdat
+  bool supportsCOMDAT() const { return !isOSBinFormatMachO(); }
+
+  /// @}
+  /// @name Mutators
+  /// @{
+
+  /// setArch - Set the architecture (first) component of the triple
+  /// to a known type.
+  void setArch(ArchType Kind);
+
+  /// setVendor - Set the vendor (second) component of the triple to a
+  /// known type.
+  void setVendor(VendorType Kind);
+
+  /// setOS - Set the operating system (third) component of the triple
+  /// to a known type.
+  void setOS(OSType Kind);
+
+  /// setEnvironment - Set the environment (fourth) component of the triple
+  /// to a known type.
+  void setEnvironment(EnvironmentType Kind);
+
+  /// setObjectFormat - Set the object file format
+  void setObjectFormat(ObjectFormatType Kind);
+
+  /// setTriple - Set all components to the new triple \p Str.
+  void setTriple(const Twine &Str);
+
+  /// setArchName - Set the architecture (first) component of the
+  /// triple by name.
+  void setArchName(StringRef Str);
+
+  /// setVendorName - Set the vendor (second) component of the triple
+  /// by name.
+  void setVendorName(StringRef Str);
+
+  /// setOSName - Set the operating system (third) component of the
+  /// triple by name.
+  void setOSName(StringRef Str);
+
+  /// setEnvironmentName - Set the optional environment (fourth)
+  /// component of the triple by name.
+  void setEnvironmentName(StringRef Str);
+
+  /// setOSAndEnvironmentName - Set the operating system and optional
+  /// environment components with a single string.
+  void setOSAndEnvironmentName(StringRef Str);
+
+  /// @}
+  /// @name Helpers to build variants of a particular triple.
+  /// @{
+
+  /// Form a triple with a 32-bit variant of the current architecture.
+  ///
+  /// This can be used to move across "families" of architectures where useful.
+  ///
+  /// \returns A new triple with a 32-bit architecture or an unknown
+  ///          architecture if no such variant can be found.
+  llvm::Triple get32BitArchVariant() const;
+
+  /// Form a triple with a 64-bit variant of the current architecture.
+  ///
+  /// This can be used to move across "families" of architectures where useful.
+  ///
+  /// \returns A new triple with a 64-bit architecture or an unknown
+  ///          architecture if no such variant can be found.
+  llvm::Triple get64BitArchVariant() const;
+
+  /// Form a triple with a big endian variant of the current architecture.
+  ///
+  /// This can be used to move across "families" of architectures where useful.
+  ///
+  /// \returns A new triple with a big endian architecture or an unknown
+  ///          architecture if no such variant can be found.
+  llvm::Triple getBigEndianArchVariant() const;
+
+  /// Form a triple with a little endian variant of the current architecture.
+  ///
+  /// This can be used to move across "families" of architectures where useful.
+  ///
+  /// \returns A new triple with a little endian architecture or an unknown
+  ///          architecture if no such variant can be found.
+  llvm::Triple getLittleEndianArchVariant() const;
+
+  /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
+  ///
+  /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty
+  /// string then the triple's arch name is used.
+  StringRef getARMCPUForArch(StringRef Arch = StringRef()) const;
+
+  /// Tests whether the target triple is little endian.
+  ///
+  /// \returns true if the triple is little endian, false otherwise.
+  bool isLittleEndian() const;
+
+  /// @}
+  /// @name Static helpers for IDs.
+  /// @{
+
+  /// getArchTypeName - Get the canonical name for the \p Kind architecture.
+  static const char *getArchTypeName(ArchType Kind);
+
+  /// getArchTypePrefix - Get the "prefix" canonical name for the \p Kind
+  /// architecture. This is the prefix used by the architecture specific
+  /// builtins, and is suitable for passing to \see
+  /// Intrinsic::getIntrinsicForGCCBuiltin().
+  ///
+  /// \return - The architecture prefix, or 0 if none is defined.
+  static const char *getArchTypePrefix(ArchType Kind);
+
+  /// getVendorTypeName - Get the canonical name for the \p Kind vendor.
+  static const char *getVendorTypeName(VendorType Kind);
+
+  /// getOSTypeName - Get the canonical name for the \p Kind operating system.
+  static const char *getOSTypeName(OSType Kind);
+
+  /// getEnvironmentTypeName - Get the canonical name for the \p Kind
+  /// environment.
+  static const char *getEnvironmentTypeName(EnvironmentType Kind);
+
+  /// @}
+  /// @name Static helpers for converting alternate architecture names.
+  /// @{
+
+  /// getArchTypeForLLVMName - The canonical type for the given LLVM
+  /// architecture name (e.g., "x86").
+  static ArchType getArchTypeForLLVMName(StringRef Str);
+
+  /// @}
+};
+
+} // End llvm namespace
+
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Twine.h b/third_party/llvm-subzero/include/llvm/ADT/Twine.h
new file mode 100644
index 0000000..81b1a6d
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/Twine.h
@@ -0,0 +1,540 @@
+//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_TWINE_H
+#define LLVM_ADT_TWINE_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <string>
+
+namespace llvm {
+  class raw_ostream;
+
+  /// Twine - A lightweight data structure for efficiently representing the
+  /// concatenation of temporary values as strings.
+  ///
+  /// A Twine is a kind of rope, it represents a concatenated string using a
+  /// binary-tree, where the string is the preorder of the nodes. Since the
+  /// Twine can be efficiently rendered into a buffer when its result is used,
+  /// it avoids the cost of generating temporary values for intermediate string
+  /// results -- particularly in cases when the Twine result is never
+  /// required. By explicitly tracking the type of leaf nodes, we can also avoid
+  /// the creation of temporary strings for conversions operations (such as
+  /// appending an integer to a string).
+  ///
+  /// A Twine is not intended for use directly and should not be stored, its
+  /// implementation relies on the ability to store pointers to temporary stack
+  /// objects which may be deallocated at the end of a statement. Twines should
+  /// only be used accepted as const references in arguments, when an API wishes
+  /// to accept possibly-concatenated strings.
+  ///
+  /// Twines support a special 'null' value, which always concatenates to form
+  /// itself, and renders as an empty string. This can be returned from APIs to
+  /// effectively nullify any concatenations performed on the result.
+  ///
+  /// \b Implementation
+  ///
+  /// Given the nature of a Twine, it is not possible for the Twine's
+  /// concatenation method to construct interior nodes; the result must be
+  /// represented inside the returned value. For this reason a Twine object
+  /// actually holds two values, the left- and right-hand sides of a
+  /// concatenation. We also have nullary Twine objects, which are effectively
+  /// sentinel values that represent empty strings.
+  ///
+  /// Thus, a Twine can effectively have zero, one, or two children. The \see
+  /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for
+  /// testing the number of children.
+  ///
+  /// We maintain a number of invariants on Twine objects (FIXME: Why):
+  ///  - Nullary twines are always represented with their Kind on the left-hand
+  ///    side, and the Empty kind on the right-hand side.
+  ///  - Unary twines are always represented with the value on the left-hand
+  ///    side, and the Empty kind on the right-hand side.
+  ///  - If a Twine has another Twine as a child, that child should always be
+  ///    binary (otherwise it could have been folded into the parent).
+  ///
+  /// These invariants are check by \see isValid().
+  ///
+  /// \b Efficiency Considerations
+  ///
+  /// The Twine is designed to yield efficient and small code for common
+  /// situations. For this reason, the concat() method is inlined so that
+  /// concatenations of leaf nodes can be optimized into stores directly into a
+  /// single stack allocated object.
+  ///
+  /// In practice, not all compilers can be trusted to optimize concat() fully,
+  /// so we provide two additional methods (and accompanying operator+
+  /// overloads) to guarantee that particularly important cases (cstring plus
+  /// StringRef) codegen as desired.
+  class Twine {
+    /// NodeKind - Represent the type of an argument.
+    enum NodeKind : unsigned char {
+      /// An empty string; the result of concatenating anything with it is also
+      /// empty.
+      NullKind,
+
+      /// The empty string.
+      EmptyKind,
+
+      /// A pointer to a Twine instance.
+      TwineKind,
+
+      /// A pointer to a C string instance.
+      CStringKind,
+
+      /// A pointer to an std::string instance.
+      StdStringKind,
+
+      /// A pointer to a StringRef instance.
+      StringRefKind,
+
+      /// A pointer to a SmallString instance.
+      SmallStringKind,
+
+      /// A char value, to render as a character.
+      CharKind,
+
+      /// An unsigned int value, to render as an unsigned decimal integer.
+      DecUIKind,
+
+      /// An int value, to render as a signed decimal integer.
+      DecIKind,
+
+      /// A pointer to an unsigned long value, to render as an unsigned decimal
+      /// integer.
+      DecULKind,
+
+      /// A pointer to a long value, to render as a signed decimal integer.
+      DecLKind,
+
+      /// A pointer to an unsigned long long value, to render as an unsigned
+      /// decimal integer.
+      DecULLKind,
+
+      /// A pointer to a long long value, to render as a signed decimal integer.
+      DecLLKind,
+
+      /// A pointer to a uint64_t value, to render as an unsigned hexadecimal
+      /// integer.
+      UHexKind
+    };
+
+    union Child
+    {
+      const Twine *twine;
+      const char *cString;
+      const std::string *stdString;
+      const StringRef *stringRef;
+      const SmallVectorImpl<char> *smallString;
+      char character;
+      unsigned int decUI;
+      int decI;
+      const unsigned long *decUL;
+      const long *decL;
+      const unsigned long long *decULL;
+      const long long *decLL;
+      const uint64_t *uHex;
+    };
+
+  private:
+    /// LHS - The prefix in the concatenation, which may be uninitialized for
+    /// Null or Empty kinds.
+    Child LHS;
+    /// RHS - The suffix in the concatenation, which may be uninitialized for
+    /// Null or Empty kinds.
+    Child RHS;
+    /// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
+    NodeKind LHSKind;
+    /// RHSKind - The NodeKind of the right hand side, \see getRHSKind().
+    NodeKind RHSKind;
+
+  private:
+    /// Construct a nullary twine; the kind must be NullKind or EmptyKind.
+    explicit Twine(NodeKind Kind)
+      : LHSKind(Kind), RHSKind(EmptyKind) {
+      assert(isNullary() && "Invalid kind!");
+    }
+
+    /// Construct a binary twine.
+    explicit Twine(const Twine &LHS, const Twine &RHS)
+        : LHSKind(TwineKind), RHSKind(TwineKind) {
+      this->LHS.twine = &LHS;
+      this->RHS.twine = &RHS;
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Construct a twine from explicit values.
+    explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind)
+        : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) {
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Since the intended use of twines is as temporary objects, assignments
+    /// when concatenating might cause undefined behavior or stack corruptions
+    Twine &operator=(const Twine &Other) = delete;
+
+    /// Check for the null twine.
+    bool isNull() const {
+      return getLHSKind() == NullKind;
+    }
+
+    /// Check for the empty twine.
+    bool isEmpty() const {
+      return getLHSKind() == EmptyKind;
+    }
+
+    /// Check if this is a nullary twine (null or empty).
+    bool isNullary() const {
+      return isNull() || isEmpty();
+    }
+
+    /// Check if this is a unary twine.
+    bool isUnary() const {
+      return getRHSKind() == EmptyKind && !isNullary();
+    }
+
+    /// Check if this is a binary twine.
+    bool isBinary() const {
+      return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
+    }
+
+    /// Check if this is a valid twine (satisfying the invariants on
+    /// order and number of arguments).
+    bool isValid() const {
+      // Nullary twines always have Empty on the RHS.
+      if (isNullary() && getRHSKind() != EmptyKind)
+        return false;
+
+      // Null should never appear on the RHS.
+      if (getRHSKind() == NullKind)
+        return false;
+
+      // The RHS cannot be non-empty if the LHS is empty.
+      if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind)
+        return false;
+
+      // A twine child should always be binary.
+      if (getLHSKind() == TwineKind &&
+          !LHS.twine->isBinary())
+        return false;
+      if (getRHSKind() == TwineKind &&
+          !RHS.twine->isBinary())
+        return false;
+
+      return true;
+    }
+
+    /// Get the NodeKind of the left-hand side.
+    NodeKind getLHSKind() const { return LHSKind; }
+
+    /// Get the NodeKind of the right-hand side.
+    NodeKind getRHSKind() const { return RHSKind; }
+
+    /// Print one child from a twine.
+    void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
+
+    /// Print the representation of one child from a twine.
+    void printOneChildRepr(raw_ostream &OS, Child Ptr,
+                           NodeKind Kind) const;
+
+  public:
+    /// @name Constructors
+    /// @{
+
+    /// Construct from an empty string.
+    /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) {
+      assert(isValid() && "Invalid twine!");
+    }
+
+    Twine(const Twine &) = default;
+
+    /// Construct from a C string.
+    ///
+    /// We take care here to optimize "" into the empty twine -- this will be
+    /// optimized out for string constants. This allows Twine arguments have
+    /// default "" values, without introducing unnecessary string constants.
+    /*implicit*/ Twine(const char *Str)
+      : RHSKind(EmptyKind) {
+      if (Str[0] != '\0') {
+        LHS.cString = Str;
+        LHSKind = CStringKind;
+      } else
+        LHSKind = EmptyKind;
+
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Construct from an std::string.
+    /*implicit*/ Twine(const std::string &Str)
+      : LHSKind(StdStringKind), RHSKind(EmptyKind) {
+      LHS.stdString = &Str;
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Construct from a StringRef.
+    /*implicit*/ Twine(const StringRef &Str)
+      : LHSKind(StringRefKind), RHSKind(EmptyKind) {
+      LHS.stringRef = &Str;
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Construct from a SmallString.
+    /*implicit*/ Twine(const SmallVectorImpl<char> &Str)
+      : LHSKind(SmallStringKind), RHSKind(EmptyKind) {
+      LHS.smallString = &Str;
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Construct from a char.
+    explicit Twine(char Val)
+      : LHSKind(CharKind), RHSKind(EmptyKind) {
+      LHS.character = Val;
+    }
+
+    /// Construct from a signed char.
+    explicit Twine(signed char Val)
+      : LHSKind(CharKind), RHSKind(EmptyKind) {
+      LHS.character = static_cast<char>(Val);
+    }
+
+    /// Construct from an unsigned char.
+    explicit Twine(unsigned char Val)
+      : LHSKind(CharKind), RHSKind(EmptyKind) {
+      LHS.character = static_cast<char>(Val);
+    }
+
+    /// Construct a twine to print \p Val as an unsigned decimal integer.
+    explicit Twine(unsigned Val)
+      : LHSKind(DecUIKind), RHSKind(EmptyKind) {
+      LHS.decUI = Val;
+    }
+
+    /// Construct a twine to print \p Val as a signed decimal integer.
+    explicit Twine(int Val)
+      : LHSKind(DecIKind), RHSKind(EmptyKind) {
+      LHS.decI = Val;
+    }
+
+    /// Construct a twine to print \p Val as an unsigned decimal integer.
+    explicit Twine(const unsigned long &Val)
+      : LHSKind(DecULKind), RHSKind(EmptyKind) {
+      LHS.decUL = &Val;
+    }
+
+    /// Construct a twine to print \p Val as a signed decimal integer.
+    explicit Twine(const long &Val)
+      : LHSKind(DecLKind), RHSKind(EmptyKind) {
+      LHS.decL = &Val;
+    }
+
+    /// Construct a twine to print \p Val as an unsigned decimal integer.
+    explicit Twine(const unsigned long long &Val)
+      : LHSKind(DecULLKind), RHSKind(EmptyKind) {
+      LHS.decULL = &Val;
+    }
+
+    /// Construct a twine to print \p Val as a signed decimal integer.
+    explicit Twine(const long long &Val)
+      : LHSKind(DecLLKind), RHSKind(EmptyKind) {
+      LHS.decLL = &Val;
+    }
+
+    // FIXME: Unfortunately, to make sure this is as efficient as possible we
+    // need extra binary constructors from particular types. We can't rely on
+    // the compiler to be smart enough to fold operator+()/concat() down to the
+    // right thing. Yet.
+
+    /// Construct as the concatenation of a C string and a StringRef.
+    /*implicit*/ Twine(const char *LHS, const StringRef &RHS)
+        : LHSKind(CStringKind), RHSKind(StringRefKind) {
+      this->LHS.cString = LHS;
+      this->RHS.stringRef = &RHS;
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Construct as the concatenation of a StringRef and a C string.
+    /*implicit*/ Twine(const StringRef &LHS, const char *RHS)
+        : LHSKind(StringRefKind), RHSKind(CStringKind) {
+      this->LHS.stringRef = &LHS;
+      this->RHS.cString = RHS;
+      assert(isValid() && "Invalid twine!");
+    }
+
+    /// Create a 'null' string, which is an empty string that always
+    /// concatenates to form another empty string.
+    static Twine createNull() {
+      return Twine(NullKind);
+    }
+
+    /// @}
+    /// @name Numeric Conversions
+    /// @{
+
+    // Construct a twine to print \p Val as an unsigned hexadecimal integer.
+    static Twine utohexstr(const uint64_t &Val) {
+      Child LHS, RHS;
+      LHS.uHex = &Val;
+      RHS.twine = nullptr;
+      return Twine(LHS, UHexKind, RHS, EmptyKind);
+    }
+
+    /// @}
+    /// @name Predicate Operations
+    /// @{
+
+    /// Check if this twine is trivially empty; a false return value does not
+    /// necessarily mean the twine is empty.
+    bool isTriviallyEmpty() const {
+      return isNullary();
+    }
+
+    /// Return true if this twine can be dynamically accessed as a single
+    /// StringRef value with getSingleStringRef().
+    bool isSingleStringRef() const {
+      if (getRHSKind() != EmptyKind) return false;
+
+      switch (getLHSKind()) {
+      case EmptyKind:
+      case CStringKind:
+      case StdStringKind:
+      case StringRefKind:
+      case SmallStringKind:
+        return true;
+      default:
+        return false;
+      }
+    }
+
+    /// @}
+    /// @name String Operations
+    /// @{
+
+    Twine concat(const Twine &Suffix) const;
+
+    /// @}
+    /// @name Output & Conversion.
+    /// @{
+
+    /// Return the twine contents as a std::string.
+    std::string str() const;
+
+    /// Append the concatenated string into the given SmallString or SmallVector.
+    void toVector(SmallVectorImpl<char> &Out) const;
+
+    /// This returns the twine as a single StringRef.  This method is only valid
+    /// if isSingleStringRef() is true.
+    StringRef getSingleStringRef() const {
+      assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
+      switch (getLHSKind()) {
+      default: llvm_unreachable("Out of sync with isSingleStringRef");
+      case EmptyKind:      return StringRef();
+      case CStringKind:    return StringRef(LHS.cString);
+      case StdStringKind:  return StringRef(*LHS.stdString);
+      case StringRefKind:  return *LHS.stringRef;
+      case SmallStringKind:
+        return StringRef(LHS.smallString->data(), LHS.smallString->size());
+      }
+    }
+
+    /// This returns the twine as a single StringRef if it can be
+    /// represented as such. Otherwise the twine is written into the given
+    /// SmallVector and a StringRef to the SmallVector's data is returned.
+    StringRef toStringRef(SmallVectorImpl<char> &Out) const {
+      if (isSingleStringRef())
+        return getSingleStringRef();
+      toVector(Out);
+      return StringRef(Out.data(), Out.size());
+    }
+
+    /// This returns the twine as a single null terminated StringRef if it
+    /// can be represented as such. Otherwise the twine is written into the
+    /// given SmallVector and a StringRef to the SmallVector's data is returned.
+    ///
+    /// The returned StringRef's size does not include the null terminator.
+    StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;
+
+    /// Write the concatenated string represented by this twine to the
+    /// stream \p OS.
+    void print(raw_ostream &OS) const;
+
+    /// Dump the concatenated string represented by this twine to stderr.
+    void dump() const;
+
+    /// Write the representation of this twine to the stream \p OS.
+    void printRepr(raw_ostream &OS) const;
+
+    /// Dump the representation of this twine to stderr.
+    void dumpRepr() const;
+
+    /// @}
+  };
+
+  /// @name Twine Inline Implementations
+  /// @{
+
+  inline Twine Twine::concat(const Twine &Suffix) const {
+    // Concatenation with null is null.
+    if (isNull() || Suffix.isNull())
+      return Twine(NullKind);
+
+    // Concatenation with empty yields the other side.
+    if (isEmpty())
+      return Suffix;
+    if (Suffix.isEmpty())
+      return *this;
+
+    // Otherwise we need to create a new node, taking care to fold in unary
+    // twines.
+    Child NewLHS, NewRHS;
+    NewLHS.twine = this;
+    NewRHS.twine = &Suffix;
+    NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
+    if (isUnary()) {
+      NewLHS = LHS;
+      NewLHSKind = getLHSKind();
+    }
+    if (Suffix.isUnary()) {
+      NewRHS = Suffix.LHS;
+      NewRHSKind = Suffix.getLHSKind();
+    }
+
+    return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind);
+  }
+
+  inline Twine operator+(const Twine &LHS, const Twine &RHS) {
+    return LHS.concat(RHS);
+  }
+
+  /// Additional overload to guarantee simplified codegen; this is equivalent to
+  /// concat().
+
+  inline Twine operator+(const char *LHS, const StringRef &RHS) {
+    return Twine(LHS, RHS);
+  }
+
+  /// Additional overload to guarantee simplified codegen; this is equivalent to
+  /// concat().
+
+  inline Twine operator+(const StringRef &LHS, const char *RHS) {
+    return Twine(LHS, RHS);
+  }
+
+  inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) {
+    RHS.print(OS);
+    return OS;
+  }
+
+  /// @}
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/edit_distance.h b/third_party/llvm-subzero/include/llvm/ADT/edit_distance.h
new file mode 100644
index 0000000..06a01b1
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/edit_distance.h
@@ -0,0 +1,103 @@
+//===-- llvm/ADT/edit_distance.h - Array edit distance function --- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a Levenshtein distance function that works for any two
+// sequences, with each element of each sequence being analogous to a character
+// in a string.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_EDIT_DISTANCE_H
+#define LLVM_ADT_EDIT_DISTANCE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include <algorithm>
+#include <memory>
+
+namespace llvm {
+
+/// \brief Determine the edit distance between two sequences.
+///
+/// \param FromArray the first sequence to compare.
+///
+/// \param ToArray the second sequence to compare.
+///
+/// \param AllowReplacements whether to allow element replacements (change one
+/// element into another) as a single operation, rather than as two operations
+/// (an insertion and a removal).
+///
+/// \param MaxEditDistance If non-zero, the maximum edit distance that this
+/// routine is allowed to compute. If the edit distance will exceed that
+/// maximum, returns \c MaxEditDistance+1.
+///
+/// \returns the minimum number of element insertions, removals, or (if
+/// \p AllowReplacements is \c true) replacements needed to transform one of
+/// the given sequences into the other. If zero, the sequences are identical.
+template<typename T>
+unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
+                             bool AllowReplacements = true,
+                             unsigned MaxEditDistance = 0) {
+  // The algorithm implemented below is the "classic"
+  // dynamic-programming algorithm for computing the Levenshtein
+  // distance, which is described here:
+  //
+  //   http://en.wikipedia.org/wiki/Levenshtein_distance
+  //
+  // Although the algorithm is typically described using an m x n
+  // array, only one row plus one element are used at a time, so this
+  // implementation just keeps one vector for the row.  To update one entry,
+  // only the entries to the left, top, and top-left are needed.  The left
+  // entry is in Row[x-1], the top entry is what's in Row[x] from the last
+  // iteration, and the top-left entry is stored in Previous.
+  typename ArrayRef<T>::size_type m = FromArray.size();
+  typename ArrayRef<T>::size_type n = ToArray.size();
+
+  const unsigned SmallBufferSize = 64;
+  unsigned SmallBuffer[SmallBufferSize];
+  std::unique_ptr<unsigned[]> Allocated;
+  unsigned *Row = SmallBuffer;
+  if (n + 1 > SmallBufferSize) {
+    Row = new unsigned[n + 1];
+    Allocated.reset(Row);
+  }
+
+  for (unsigned i = 1; i <= n; ++i)
+    Row[i] = i;
+
+  for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
+    Row[0] = y;
+    unsigned BestThisRow = Row[0];
+
+    unsigned Previous = y - 1;
+    for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
+      int OldRow = Row[x];
+      if (AllowReplacements) {
+        Row[x] = std::min(
+            Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
+            std::min(Row[x-1], Row[x])+1);
+      }
+      else {
+        if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous;
+        else Row[x] = std::min(Row[x-1], Row[x]) + 1;
+      }
+      Previous = OldRow;
+      BestThisRow = std::min(BestThisRow, Row[x]);
+    }
+
+    if (MaxEditDistance && BestThisRow > MaxEditDistance)
+      return MaxEditDistance + 1;
+  }
+
+  unsigned Result = Row[n];
+  return Result;
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist.h b/third_party/llvm-subzero/include/llvm/ADT/ilist.h
new file mode 100644
index 0000000..ce5af68
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/ilist.h
@@ -0,0 +1,457 @@
+//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes to implement an intrusive doubly linked list class
+// (i.e. each node of the list must contain a next and previous field for the
+// list.
+//
+// The ilist class itself should be a plug in replacement for list.  This list
+// replacement does not provide a constant time size() method, so be careful to
+// use empty() when you really want to know if it's empty.
+//
+// The ilist class is implemented as a circular list.  The list itself contains
+// a sentinel node, whose Next points at begin() and whose Prev points at
+// rbegin().  The sentinel node itself serves as end() and rend().
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_H
+#define LLVM_ADT_ILIST_H
+
+#include "llvm/ADT/simple_ilist.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+
+namespace llvm {
+
+/// Use new/delete by default for iplist and ilist.
+///
+/// Specialize this to get different behaviour for allocation-related API.  (If
+/// you really want new/delete, consider just using std::list.)
+///
+/// \see ilist_noalloc_traits
+template <typename NodeTy> struct ilist_alloc_traits {
+  static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); }
+  static void deleteNode(NodeTy *V) { delete V; }
+};
+
+/// Custom traits to disable node creation and do nothing on deletion.
+///
+/// Specialize ilist_alloc_traits to inherit from this to disable the
+/// non-intrusive parts of iplist and/or ilist.  It has no createNode function,
+/// and deleteNode does nothing.
+///
+/// \code
+/// template <>
+/// struct ilist_alloc_traits<MyType> : ilist_noalloc_traits<MyType> {};
+/// \endcode
+template <typename NodeTy> struct ilist_noalloc_traits {
+  static void deleteNode(NodeTy *V) {}
+};
+
+/// Callbacks do nothing by default in iplist and ilist.
+///
+/// Specialize this for to use callbacks for when nodes change their list
+/// membership.
+template <typename NodeTy> struct ilist_callback_traits {
+  void addNodeToList(NodeTy *) {}
+  void removeNodeFromList(NodeTy *) {}
+
+  /// Callback before transferring nodes to this list.
+  ///
+  /// \pre \c this!=&OldList
+  template <class Iterator>
+  void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/,
+                             Iterator /*last*/) {
+    (void)OldList;
+  }
+};
+
+/// A fragment for template traits for intrusive list that provides default
+/// node related operations.
+///
+/// TODO: Remove this layer of indirection.  It's not necessary.
+template <typename NodeTy>
+struct ilist_node_traits : ilist_alloc_traits<NodeTy>,
+                           ilist_callback_traits<NodeTy> {};
+
+/// Default template traits for intrusive list.
+///
+/// By inheriting from this, you can easily use default implementations for all
+/// common operations.
+///
+/// TODO: Remove this customization point.  Specializing ilist_traits is
+/// already fully general.
+template <typename NodeTy>
+struct ilist_default_traits : public ilist_node_traits<NodeTy> {};
+
+/// Template traits for intrusive list.
+///
+/// Customize callbacks and allocation semantics.
+template <typename NodeTy>
+struct ilist_traits : public ilist_default_traits<NodeTy> {};
+
+/// Const traits should never be instantiated.
+template <typename Ty> struct ilist_traits<const Ty> {};
+
+namespace ilist_detail {
+
+template <class T> T &make();
+
+/// Type trait to check for a traits class that has a getNext member (as a
+/// canary for any of the ilist_nextprev_traits API).
+template <class TraitsT, class NodeT> struct HasGetNext {
+  typedef char Yes[1];
+  typedef char No[2];
+  template <size_t N> struct SFINAE {};
+
+  template <class U>
+  static Yes &test(U *I, decltype(I->getNext(&make<NodeT>())) * = 0);
+  template <class> static No &test(...);
+
+public:
+  static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes);
+};
+
+/// Type trait to check for a traits class that has a createSentinel member (as
+/// a canary for any of the ilist_sentinel_traits API).
+template <class TraitsT> struct HasCreateSentinel {
+  typedef char Yes[1];
+  typedef char No[2];
+
+  template <class U>
+  static Yes &test(U *I, decltype(I->createSentinel()) * = 0);
+  template <class> static No &test(...);
+
+public:
+  static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes);
+};
+
+template <class TraitsT, class NodeT> struct HasObsoleteCustomization {
+  static const bool value =
+      HasGetNext<TraitsT, NodeT>::value || HasCreateSentinel<TraitsT>::value;
+};
+
+} // end namespace ilist_detail
+
+//===----------------------------------------------------------------------===//
+//
+/// A wrapper around an intrusive list with callbacks and non-intrusive
+/// ownership.
+///
+/// This wraps a purely intrusive list (like simple_ilist) with a configurable
+/// traits class.  The traits can implement callbacks and customize the
+/// ownership semantics.
+///
+/// This is a subset of ilist functionality that can safely be used on nodes of
+/// polymorphic types, i.e. a heterogeneous list with a common base class that
+/// holds the next/prev pointers.  The only state of the list itself is an
+/// ilist_sentinel, which holds pointers to the first and last nodes in the
+/// list.
+template <class IntrusiveListT, class TraitsT>
+class iplist_impl : public TraitsT, IntrusiveListT {
+  typedef IntrusiveListT base_list_type;
+
+public:
+  typedef typename base_list_type::pointer pointer;
+  typedef typename base_list_type::const_pointer const_pointer;
+  typedef typename base_list_type::reference reference;
+  typedef typename base_list_type::const_reference const_reference;
+  typedef typename base_list_type::value_type value_type;
+  typedef typename base_list_type::size_type size_type;
+  typedef typename base_list_type::difference_type difference_type;
+  typedef typename base_list_type::iterator iterator;
+  typedef typename base_list_type::const_iterator const_iterator;
+  typedef typename base_list_type::reverse_iterator reverse_iterator;
+  typedef
+      typename base_list_type::const_reverse_iterator const_reverse_iterator;
+
+private:
+  // TODO: Drop this assertion and the transitive type traits anytime after
+  // v4.0 is branched (i.e,. keep them for one release to help out-of-tree code
+  // update).
+  static_assert(
+      !ilist_detail::HasObsoleteCustomization<TraitsT, value_type>::value,
+      "ilist customization points have changed!");
+
+  static bool op_less(const_reference L, const_reference R) { return L < R; }
+  static bool op_equal(const_reference L, const_reference R) { return L == R; }
+
+  // Copying intrusively linked nodes doesn't make sense.
+  iplist_impl(const iplist_impl &) = delete;
+  void operator=(const iplist_impl &) = delete;
+
+public:
+  iplist_impl() = default;
+  ~iplist_impl() { clear(); }
+
+  // Miscellaneous inspection routines.
+  size_type max_size() const { return size_type(-1); }
+
+  using base_list_type::begin;
+  using base_list_type::end;
+  using base_list_type::rbegin;
+  using base_list_type::rend;
+  using base_list_type::empty;
+  using base_list_type::front;
+  using base_list_type::back;
+
+  void swap(iplist_impl &RHS) {
+    assert(0 && "Swap does not use list traits callback correctly yet!");
+    base_list_type::swap(RHS);
+  }
+
+  iterator insert(iterator where, pointer New) {
+    this->addNodeToList(New); // Notify traits that we added a node...
+    return base_list_type::insert(where, *New);
+  }
+
+  iterator insert(iterator where, const_reference New) {
+    return this->insert(where, new value_type(New));
+  }
+
+  iterator insertAfter(iterator where, pointer New) {
+    if (empty())
+      return insert(begin(), New);
+    else
+      return insert(++where, New);
+  }
+
+  pointer remove(iterator &IT) {
+    pointer Node = &*IT++;
+    this->removeNodeFromList(Node); // Notify traits that we removed a node...
+    base_list_type::remove(*Node);
+    return Node;
+  }
+
+  pointer remove(const iterator &IT) {
+    iterator MutIt = IT;
+    return remove(MutIt);
+  }
+
+  pointer remove(pointer IT) { return remove(iterator(IT)); }
+  pointer remove(reference IT) { return remove(iterator(IT)); }
+
+  // erase - remove a node from the controlled sequence... and delete it.
+  iterator erase(iterator where) {
+    this->deleteNode(remove(where));
+    return where;
+  }
+
+  iterator erase(pointer IT) { return erase(iterator(IT)); }
+  iterator erase(reference IT) { return erase(iterator(IT)); }
+
+  /// Remove all nodes from the list like clear(), but do not call
+  /// removeNodeFromList() or deleteNode().
+  ///
+  /// This should only be used immediately before freeing nodes in bulk to
+  /// avoid traversing the list and bringing all the nodes into cache.
+  void clearAndLeakNodesUnsafely() { base_list_type::clear(); }
+
+private:
+  // transfer - The heart of the splice function.  Move linked list nodes from
+  // [first, last) into position.
+  //
+  void transfer(iterator position, iplist_impl &L2, iterator first, iterator last) {
+    if (position == last)
+      return;
+
+    if (this != &L2) // Notify traits we moved the nodes...
+      this->transferNodesFromList(L2, first, last);
+
+    base_list_type::splice(position, L2, first, last);
+  }
+
+public:
+
+  //===----------------------------------------------------------------------===
+  // Functionality derived from other functions defined above...
+  //
+
+  using base_list_type::size;
+
+  iterator erase(iterator first, iterator last) {
+    while (first != last)
+      first = erase(first);
+    return last;
+  }
+
+  void clear() { erase(begin(), end()); }
+
+  // Front and back inserters...
+  void push_front(pointer val) { insert(begin(), val); }
+  void push_back(pointer val) { insert(end(), val); }
+  void pop_front() {
+    assert(!empty() && "pop_front() on empty list!");
+    erase(begin());
+  }
+  void pop_back() {
+    assert(!empty() && "pop_back() on empty list!");
+    iterator t = end(); erase(--t);
+  }
+
+  // Special forms of insert...
+  template<class InIt> void insert(iterator where, InIt first, InIt last) {
+    for (; first != last; ++first) insert(where, *first);
+  }
+
+  // Splice members - defined in terms of transfer...
+  void splice(iterator where, iplist_impl &L2) {
+    if (!L2.empty())
+      transfer(where, L2, L2.begin(), L2.end());
+  }
+  void splice(iterator where, iplist_impl &L2, iterator first) {
+    iterator last = first; ++last;
+    if (where == first || where == last) return; // No change
+    transfer(where, L2, first, last);
+  }
+  void splice(iterator where, iplist_impl &L2, iterator first, iterator last) {
+    if (first != last) transfer(where, L2, first, last);
+  }
+  void splice(iterator where, iplist_impl &L2, reference N) {
+    splice(where, L2, iterator(N));
+  }
+  void splice(iterator where, iplist_impl &L2, pointer N) {
+    splice(where, L2, iterator(N));
+  }
+
+  template <class Compare>
+  void merge(iplist_impl &Right, Compare comp) {
+    if (this == &Right)
+      return;
+    this->transferNodesFromList(Right, Right.begin(), Right.end());
+    base_list_type::merge(Right, comp);
+  }
+  void merge(iplist_impl &Right) { return merge(Right, op_less); }
+
+  using base_list_type::sort;
+
+  /// \brief Get the previous node, or \c nullptr for the list head.
+  pointer getPrevNode(reference N) const {
+    auto I = N.getIterator();
+    if (I == begin())
+      return nullptr;
+    return &*std::prev(I);
+  }
+  /// \brief Get the previous node, or \c nullptr for the list head.
+  const_pointer getPrevNode(const_reference N) const {
+    return getPrevNode(const_cast<reference >(N));
+  }
+
+  /// \brief Get the next node, or \c nullptr for the list tail.
+  pointer getNextNode(reference N) const {
+    auto Next = std::next(N.getIterator());
+    if (Next == end())
+      return nullptr;
+    return &*Next;
+  }
+  /// \brief Get the next node, or \c nullptr for the list tail.
+  const_pointer getNextNode(const_reference N) const {
+    return getNextNode(const_cast<reference >(N));
+  }
+};
+
+/// An intrusive list with ownership and callbacks specified/controlled by
+/// ilist_traits, only with API safe for polymorphic types.
+template <class T>
+class iplist : public iplist_impl<simple_ilist<T>, ilist_traits<T>> {};
+
+/// An intrusive list with ownership and callbacks specified/controlled by
+/// ilist_traits, with API that is unsafe for polymorphic types.
+template <class T> class ilist : public iplist<T> {
+  typedef iplist<T> base_list_type;
+
+public:
+  typedef typename base_list_type::size_type size_type;
+  typedef typename base_list_type::iterator iterator;
+  typedef typename base_list_type::value_type value_type;
+  typedef typename base_list_type::const_reference const_reference;
+
+  ilist() {}
+  ilist(const ilist &right) : base_list_type() {
+    insert(this->begin(), right.begin(), right.end());
+  }
+  explicit ilist(size_type count) {
+    insert(this->begin(), count, value_type());
+  }
+  ilist(size_type count, const_reference val) {
+    insert(this->begin(), count, val);
+  }
+  template<class InIt> ilist(InIt first, InIt last) {
+    insert(this->begin(), first, last);
+  }
+
+  // bring hidden functions into scope
+  using base_list_type::insert;
+  using base_list_type::push_front;
+  using base_list_type::push_back;
+
+  // Main implementation here - Insert for a node passed by value...
+  iterator insert(iterator where, const_reference val) {
+    return insert(where, this->createNode(val));
+  }
+
+
+  // Front and back inserters...
+  void push_front(const_reference val) { insert(this->begin(), val); }
+  void push_back(const_reference val) { insert(this->end(), val); }
+
+  void insert(iterator where, size_type count, const_reference val) {
+    for (; count != 0; --count) insert(where, val);
+  }
+
+  // Assign special forms...
+  void assign(size_type count, const_reference val) {
+    iterator I = this->begin();
+    for (; I != this->end() && count != 0; ++I, --count)
+      *I = val;
+    if (count != 0)
+      insert(this->end(), val, val);
+    else
+      erase(I, this->end());
+  }
+  template<class InIt> void assign(InIt first1, InIt last1) {
+    iterator first2 = this->begin(), last2 = this->end();
+    for ( ; first1 != last1 && first2 != last2; ++first1, ++first2)
+      *first1 = *first2;
+    if (first2 == last2)
+      erase(first1, last1);
+    else
+      insert(last1, first2, last2);
+  }
+
+
+  // Resize members...
+  void resize(size_type newsize, value_type val) {
+    iterator i = this->begin();
+    size_type len = 0;
+    for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ;
+
+    if (len == newsize)
+      erase(i, this->end());
+    else                                          // i == end()
+      insert(this->end(), newsize - len, val);
+  }
+  void resize(size_type newsize) { resize(newsize, value_type()); }
+};
+
+} // End llvm namespace
+
+namespace std {
+  // Ensure that swap uses the fast list swap...
+  template<class Ty>
+  void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) {
+    Left.swap(Right);
+  }
+}  // End 'std' extensions...
+
+#endif // LLVM_ADT_ILIST_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_base.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_base.h
new file mode 100644
index 0000000..a41696d
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_base.h
@@ -0,0 +1,93 @@
+//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_BASE_H
+#define LLVM_ADT_ILIST_BASE_H
+
+#include "llvm/ADT/ilist_node_base.h"
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+namespace llvm {
+
+/// Implementations of list algorithms using ilist_node_base.
+class ilist_base {
+public:
+  static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) {
+    ilist_node_base &Prev = *Next.getPrev();
+    N.setNext(&Next);
+    N.setPrev(&Prev);
+    Prev.setNext(&N);
+    Next.setPrev(&N);
+  }
+
+  static void removeImpl(ilist_node_base &N) {
+    ilist_node_base *Prev = N.getPrev();
+    ilist_node_base *Next = N.getNext();
+    Next->setPrev(Prev);
+    Prev->setNext(Next);
+
+    // Not strictly necessary, but helps catch a class of bugs.
+    N.setPrev(nullptr);
+    N.setNext(nullptr);
+  }
+
+  static void removeRangeImpl(ilist_node_base &First, ilist_node_base &Last) {
+    ilist_node_base *Prev = First.getPrev();
+    ilist_node_base *Final = Last.getPrev();
+    Last.setPrev(Prev);
+    Prev->setNext(&Last);
+
+    // Not strictly necessary, but helps catch a class of bugs.
+    First.setPrev(nullptr);
+    Final->setNext(nullptr);
+  }
+
+  static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First,
+                                 ilist_node_base &Last) {
+    if (&Next == &Last || &First == &Last)
+      return;
+
+    // Position cannot be contained in the range to be transferred.
+    assert(&Next != &First &&
+           // Check for the most common mistake.
+           "Insertion point can't be one of the transferred nodes");
+
+    ilist_node_base &Final = *Last.getPrev();
+
+    // Detach from old list/position.
+    First.getPrev()->setNext(&Last);
+    Last.setPrev(First.getPrev());
+
+    // Splice [First, Final] into its new list/position.
+    ilist_node_base &Prev = *Next.getPrev();
+    Final.setNext(&Next);
+    First.setPrev(&Prev);
+    Prev.setNext(&First);
+    Next.setPrev(&Final);
+  }
+
+  template <class T> static void insertBefore(T &Next, T &N) {
+    insertBeforeImpl(Next, N);
+  }
+
+  template <class T> static void remove(T &N) { removeImpl(N); }
+  template <class T> static void removeRange(T &First, T &Last) {
+    removeRangeImpl(First, Last);
+  }
+
+  template <class T> static void transferBefore(T &Next, T &First, T &Last) {
+    transferBeforeImpl(Next, First, Last);
+  }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_BASE_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_iterator.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_iterator.h
new file mode 100644
index 0000000..d106d0c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_iterator.h
@@ -0,0 +1,170 @@
+//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator -------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_ITERATOR_H
+#define LLVM_ADT_ILIST_ITERATOR_H
+
+#include "llvm/ADT/ilist_node.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+
+namespace llvm {
+
+namespace ilist_detail {
+
+template <class NodeTy> struct ConstCorrectNodeType {
+  typedef ilist_node<NodeTy> type;
+};
+template <class NodeTy> struct ConstCorrectNodeType<const NodeTy> {
+  typedef const ilist_node<NodeTy> type;
+};
+
+template <bool IsReverse = false> struct IteratorHelper {
+  template <class T> static void increment(T *&I) {
+    I = ilist_node_access::getNext(*I);
+  }
+  template <class T> static void decrement(T *&I) {
+    I = ilist_node_access::getPrev(*I);
+  }
+};
+template <> struct IteratorHelper<true> {
+  template <class T> static void increment(T *&I) {
+    IteratorHelper<false>::decrement(I);
+  }
+  template <class T> static void decrement(T *&I) {
+    IteratorHelper<false>::increment(I);
+  }
+};
+
+} // end namespace ilist_detail
+
+/// Iterator for intrusive lists  based on ilist_node.
+template <typename NodeTy, bool IsReverse> class ilist_iterator {
+public:
+  typedef NodeTy value_type;
+  typedef value_type *pointer;
+  typedef value_type &reference;
+  typedef ptrdiff_t difference_type;
+  typedef std::bidirectional_iterator_tag iterator_category;
+
+  typedef typename std::add_const<value_type>::type *const_pointer;
+  typedef typename std::add_const<value_type>::type &const_reference;
+
+  typedef typename ilist_detail::ConstCorrectNodeType<NodeTy>::type node_type;
+  typedef node_type *node_pointer;
+  typedef node_type &node_reference;
+
+private:
+  node_pointer NodePtr;
+
+public:
+  /// Create from an ilist_node.
+  explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
+
+  explicit ilist_iterator(pointer NP)
+      : NodePtr(ilist_node_access::getNodePtr(NP)) {}
+  explicit ilist_iterator(reference NR)
+      : NodePtr(ilist_node_access::getNodePtr(&NR)) {}
+  ilist_iterator() : NodePtr(nullptr) {}
+
+  // This is templated so that we can allow constructing a const iterator from
+  // a nonconst iterator...
+  template <class node_ty>
+  ilist_iterator(
+      const ilist_iterator<node_ty, IsReverse> &RHS,
+      typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value,
+                              void *>::type = nullptr)
+      : NodePtr(RHS.getNodePtr()) {}
+
+  // This is templated so that we can allow assigning to a const iterator from
+  // a nonconst iterator...
+  template <class node_ty>
+  const ilist_iterator &
+  operator=(const ilist_iterator<node_ty, IsReverse> &RHS) {
+    NodePtr = RHS.getNodePtr();
+    return *this;
+  }
+
+  /// Convert from an iterator to its reverse.
+  ///
+  /// TODO: Roll this into the implicit constructor once we're sure that no one
+  /// is relying on the std::reverse_iterator off-by-one semantics.
+  ilist_iterator<NodeTy, !IsReverse> getReverse() const {
+    if (NodePtr)
+      return ilist_iterator<NodeTy, !IsReverse>(*NodePtr);
+    return ilist_iterator<NodeTy, !IsReverse>();
+  }
+
+  void reset(pointer NP) { NodePtr = NP; }
+
+  // Accessors...
+  reference operator*() const {
+    assert(!NodePtr->isKnownSentinel());
+    return *ilist_node_access::getValuePtr(NodePtr);
+  }
+  pointer operator->() const { return &operator*(); }
+
+  // Comparison operators
+  friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
+    return LHS.NodePtr == RHS.NodePtr;
+  }
+  friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
+    return LHS.NodePtr != RHS.NodePtr;
+  }
+
+  // Increment and decrement operators...
+  ilist_iterator &operator--() {
+    ilist_detail::IteratorHelper<IsReverse>::decrement(NodePtr);
+    return *this;
+  }
+  ilist_iterator &operator++() {
+    ilist_detail::IteratorHelper<IsReverse>::increment(NodePtr);
+    return *this;
+  }
+  ilist_iterator operator--(int) {
+    ilist_iterator tmp = *this;
+    --*this;
+    return tmp;
+  }
+  ilist_iterator operator++(int) {
+    ilist_iterator tmp = *this;
+    ++*this;
+    return tmp;
+  }
+
+  /// Get the underlying ilist_node.
+  node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
+};
+
+template <typename From> struct simplify_type;
+
+/// Allow ilist_iterators to convert into pointers to a node automatically when
+/// used by the dyn_cast, cast, isa mechanisms...
+///
+/// FIXME: remove this, since there is no implicit conversion to NodeTy.
+template <typename NodeTy> struct simplify_type<ilist_iterator<NodeTy>> {
+  typedef NodeTy *SimpleType;
+
+  static SimpleType getSimplifiedValue(ilist_iterator<NodeTy> &Node) {
+    return &*Node;
+  }
+};
+template <typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy>> {
+  typedef /*const*/ NodeTy *SimpleType;
+
+  static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) {
+    return &*Node;
+  }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_ITERATOR_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_node.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_node.h
new file mode 100644
index 0000000..a5e2f5e
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_node.h
@@ -0,0 +1,169 @@
+//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ilist_node class template, which is a convenient
+// base class for creating classes that can be used with ilists.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_NODE_H
+#define LLVM_ADT_ILIST_NODE_H
+
+#include "llvm/ADT/ilist_node_base.h"
+
+namespace llvm {
+
+template<typename NodeTy>
+struct ilist_traits;
+
+struct ilist_node_access;
+template <typename NodeTy, bool IsReverse = false> class ilist_iterator;
+template <typename NodeTy> class ilist_sentinel;
+
+/// Templated wrapper class.
+template <typename NodeTy> class ilist_node : ilist_node_base {
+  friend class ilist_base;
+  friend struct ilist_node_access;
+  friend struct ilist_traits<NodeTy>;
+  friend class ilist_iterator<NodeTy, false>;
+  friend class ilist_iterator<NodeTy, true>;
+  friend class ilist_sentinel<NodeTy>;
+
+protected:
+  ilist_node() = default;
+
+private:
+  ilist_node *getPrev() {
+    return static_cast<ilist_node *>(ilist_node_base::getPrev());
+  }
+  ilist_node *getNext() {
+    return static_cast<ilist_node *>(ilist_node_base::getNext());
+  }
+
+  const ilist_node *getPrev() const {
+    return static_cast<ilist_node *>(ilist_node_base::getPrev());
+  }
+  const ilist_node *getNext() const {
+    return static_cast<ilist_node *>(ilist_node_base::getNext());
+  }
+
+  void setPrev(ilist_node *N) { ilist_node_base::setPrev(N); }
+  void setNext(ilist_node *N) { ilist_node_base::setNext(N); }
+
+public:
+  ilist_iterator<NodeTy> getIterator() { return ilist_iterator<NodeTy>(*this); }
+  ilist_iterator<const NodeTy> getIterator() const {
+    return ilist_iterator<const NodeTy>(*this);
+  }
+
+  using ilist_node_base::isKnownSentinel;
+};
+
+/// An access class for ilist_node private API.
+///
+/// This gives access to the private parts of ilist nodes.  Nodes for an ilist
+/// should friend this class if they inherit privately from ilist_node.
+///
+/// Using this class outside of the ilist implementation is unsupported.
+struct ilist_node_access {
+  template <typename T> static ilist_node<T> *getNodePtr(T *N) { return N; }
+  template <typename T> static const ilist_node<T> *getNodePtr(const T *N) {
+    return N;
+  }
+  template <typename T> static T *getValuePtr(ilist_node<T> *N) {
+    return static_cast<T *>(N);
+  }
+  template <typename T> static const T *getValuePtr(const ilist_node<T> *N) {
+    return static_cast<const T *>(N);
+  }
+
+  template <typename T> static ilist_node<T> *getPrev(ilist_node<T> &N) {
+    return N.getPrev();
+  }
+  template <typename T> static ilist_node<T> *getNext(ilist_node<T> &N) {
+    return N.getNext();
+  }
+  template <typename T>
+  static const ilist_node<T> *getPrev(const ilist_node<T> &N) {
+    return N.getPrev();
+  }
+  template <typename T>
+  static const ilist_node<T> *getNext(const ilist_node<T> &N) {
+    return N.getNext();
+  }
+};
+
+template <typename NodeTy> class ilist_sentinel : public ilist_node<NodeTy> {
+public:
+  ilist_sentinel() {
+    ilist_node_base::initializeSentinel();
+    reset();
+  }
+
+  void reset() {
+    this->setPrev(this);
+    this->setNext(this);
+  }
+
+  bool empty() const { return this == this->getPrev(); }
+};
+
+/// An ilist node that can access its parent list.
+///
+/// Requires \c NodeTy to have \a getParent() to find the parent node, and the
+/// \c ParentTy to have \a getSublistAccess() to get a reference to the list.
+template <typename NodeTy, typename ParentTy>
+class ilist_node_with_parent : public ilist_node<NodeTy> {
+protected:
+  ilist_node_with_parent() = default;
+
+private:
+  /// Forward to NodeTy::getParent().
+  ///
+  /// Note: do not use the name "getParent()".  We want a compile error
+  /// (instead of recursion) when the subclass fails to implement \a
+  /// getParent().
+  const ParentTy *getNodeParent() const {
+    return static_cast<const NodeTy *>(this)->getParent();
+  }
+
+public:
+  /// @name Adjacent Node Accessors
+  /// @{
+  /// \brief Get the previous node, or \c nullptr for the list head.
+  NodeTy *getPrevNode() {
+    // Should be separated to a reused function, but then we couldn't use auto
+    // (and would need the type of the list).
+    const auto &List =
+        getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));
+    return List.getPrevNode(*static_cast<NodeTy *>(this));
+  }
+  /// \brief Get the previous node, or \c nullptr for the list head.
+  const NodeTy *getPrevNode() const {
+    return const_cast<ilist_node_with_parent *>(this)->getPrevNode();
+  }
+
+  /// \brief Get the next node, or \c nullptr for the list tail.
+  NodeTy *getNextNode() {
+    // Should be separated to a reused function, but then we couldn't use auto
+    // (and would need the type of the list).
+    const auto &List =
+        getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));
+    return List.getNextNode(*static_cast<NodeTy *>(this));
+  }
+  /// \brief Get the next node, or \c nullptr for the list tail.
+  const NodeTy *getNextNode() const {
+    return const_cast<ilist_node_with_parent *>(this)->getNextNode();
+  }
+  /// @}
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_node_base.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_node_base.h
new file mode 100644
index 0000000..6a46876
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_node_base.h
@@ -0,0 +1,47 @@
+//===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_NODE_BASE_H
+#define LLVM_ADT_ILIST_NODE_BASE_H
+
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace llvm {
+
+/// Base class for ilist nodes.
+class ilist_node_base {
+#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
+  PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;
+#else
+  ilist_node_base *Prev = nullptr;
+#endif
+  ilist_node_base *Next = nullptr;
+
+public:
+#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
+  void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); }
+  ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }
+
+  bool isKnownSentinel() const { return PrevAndSentinel.getInt(); }
+  void initializeSentinel() { PrevAndSentinel.setInt(true); }
+#else
+  void setPrev(ilist_node_base *Prev) { this->Prev = Prev; }
+  ilist_node_base *getPrev() const { return Prev; }
+
+  bool isKnownSentinel() const { return false; }
+  void initializeSentinel() {}
+#endif
+
+  void setNext(ilist_node_base *Next) { this->Next = Next; }
+  ilist_node_base *getNext() const { return Next; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_NODE_BASE_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/iterator.h b/third_party/llvm-subzero/include/llvm/ADT/iterator.h
new file mode 100644
index 0000000..30b8ac1
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/iterator.h
@@ -0,0 +1,278 @@
+//===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ITERATOR_H
+#define LLVM_ADT_ITERATOR_H
+
+#include <cstddef>
+#include <iterator>
+
+namespace llvm {
+
+/// \brief CRTP base class which implements the entire standard iterator facade
+/// in terms of a minimal subset of the interface.
+///
+/// Use this when it is reasonable to implement most of the iterator
+/// functionality in terms of a core subset. If you need special behavior or
+/// there are performance implications for this, you may want to override the
+/// relevant members instead.
+///
+/// Note, one abstraction that this does *not* provide is implementing
+/// subtraction in terms of addition by negating the difference. Negation isn't
+/// always information preserving, and I can see very reasonable iterator
+/// designs where this doesn't work well. It doesn't really force much added
+/// boilerplate anyways.
+///
+/// Another abstraction that this doesn't provide is implementing increment in
+/// terms of addition of one. These aren't equivalent for all iterator
+/// categories, and respecting that adds a lot of complexity for little gain.
+template <typename DerivedT, typename IteratorCategoryT, typename T,
+          typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *,
+          typename ReferenceT = T &>
+class iterator_facade_base
+    : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
+                           ReferenceT> {
+protected:
+  enum {
+    IsRandomAccess =
+        std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value,
+    IsBidirectional =
+        std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value,
+  };
+
+  /// A proxy object for computing a reference via indirecting a copy of an
+  /// iterator. This is used in APIs which need to produce a reference via
+  /// indirection but for which the iterator object might be a temporary. The
+  /// proxy preserves the iterator internally and exposes the indirected
+  /// reference via a conversion operator.
+  class ReferenceProxy {
+    friend iterator_facade_base;
+
+    DerivedT I;
+
+    ReferenceProxy(DerivedT I) : I(std::move(I)) {}
+
+  public:
+    operator ReferenceT() const { return *I; }
+  };
+
+public:
+  DerivedT operator+(DifferenceTypeT n) const {
+    static_assert(
+        IsRandomAccess,
+        "The '+' operator is only defined for random access iterators.");
+    DerivedT tmp = *static_cast<const DerivedT *>(this);
+    tmp += n;
+    return tmp;
+  }
+  friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) {
+    static_assert(
+        IsRandomAccess,
+        "The '+' operator is only defined for random access iterators.");
+    return i + n;
+  }
+  DerivedT operator-(DifferenceTypeT n) const {
+    static_assert(
+        IsRandomAccess,
+        "The '-' operator is only defined for random access iterators.");
+    DerivedT tmp = *static_cast<const DerivedT *>(this);
+    tmp -= n;
+    return tmp;
+  }
+
+  DerivedT &operator++() {
+    return static_cast<DerivedT *>(this)->operator+=(1);
+  }
+  DerivedT operator++(int) {
+    DerivedT tmp = *static_cast<DerivedT *>(this);
+    ++*static_cast<DerivedT *>(this);
+    return tmp;
+  }
+  DerivedT &operator--() {
+    static_assert(
+        IsBidirectional,
+        "The decrement operator is only defined for bidirectional iterators.");
+    return static_cast<DerivedT *>(this)->operator-=(1);
+  }
+  DerivedT operator--(int) {
+    static_assert(
+        IsBidirectional,
+        "The decrement operator is only defined for bidirectional iterators.");
+    DerivedT tmp = *static_cast<DerivedT *>(this);
+    --*static_cast<DerivedT *>(this);
+    return tmp;
+  }
+
+  bool operator!=(const DerivedT &RHS) const {
+    return !static_cast<const DerivedT *>(this)->operator==(RHS);
+  }
+
+  bool operator>(const DerivedT &RHS) const {
+    static_assert(
+        IsRandomAccess,
+        "Relational operators are only defined for random access iterators.");
+    return !static_cast<const DerivedT *>(this)->operator<(RHS) &&
+           !static_cast<const DerivedT *>(this)->operator==(RHS);
+  }
+  bool operator<=(const DerivedT &RHS) const {
+    static_assert(
+        IsRandomAccess,
+        "Relational operators are only defined for random access iterators.");
+    return !static_cast<const DerivedT *>(this)->operator>(RHS);
+  }
+  bool operator>=(const DerivedT &RHS) const {
+    static_assert(
+        IsRandomAccess,
+        "Relational operators are only defined for random access iterators.");
+    return !static_cast<const DerivedT *>(this)->operator<(RHS);
+  }
+
+  PointerT operator->() const {
+    return &static_cast<const DerivedT *>(this)->operator*();
+  }
+  ReferenceProxy operator[](DifferenceTypeT n) const {
+    static_assert(IsRandomAccess,
+                  "Subscripting is only defined for random access iterators.");
+    return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
+  }
+};
+
+/// \brief CRTP base class for adapting an iterator to a different type.
+///
+/// This class can be used through CRTP to adapt one iterator into another.
+/// Typically this is done through providing in the derived class a custom \c
+/// operator* implementation. Other methods can be overridden as well.
+template <
+    typename DerivedT, typename WrappedIteratorT,
+    typename IteratorCategoryT =
+        typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+    typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
+    typename DifferenceTypeT =
+        typename std::iterator_traits<WrappedIteratorT>::difference_type,
+    typename PointerT = typename std::conditional<
+        std::is_same<T, typename std::iterator_traits<
+                            WrappedIteratorT>::value_type>::value,
+        typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type,
+    typename ReferenceT = typename std::conditional<
+        std::is_same<T, typename std::iterator_traits<
+                            WrappedIteratorT>::value_type>::value,
+        typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type,
+    // Don't provide these, they are mostly to act as aliases below.
+    typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>>
+class iterator_adaptor_base
+    : public iterator_facade_base<DerivedT, IteratorCategoryT, T,
+                                  DifferenceTypeT, PointerT, ReferenceT> {
+  typedef typename iterator_adaptor_base::iterator_facade_base BaseT;
+
+protected:
+  WrappedIteratorT I;
+
+  iterator_adaptor_base() = default;
+
+  explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {}
+
+  const WrappedIteratorT &wrapped() const { return I; }
+
+public:
+  typedef DifferenceTypeT difference_type;
+
+  DerivedT &operator+=(difference_type n) {
+    static_assert(
+        BaseT::IsRandomAccess,
+        "The '+=' operator is only defined for random access iterators.");
+    I += n;
+    return *static_cast<DerivedT *>(this);
+  }
+  DerivedT &operator-=(difference_type n) {
+    static_assert(
+        BaseT::IsRandomAccess,
+        "The '-=' operator is only defined for random access iterators.");
+    I -= n;
+    return *static_cast<DerivedT *>(this);
+  }
+  using BaseT::operator-;
+  difference_type operator-(const DerivedT &RHS) const {
+    static_assert(
+        BaseT::IsRandomAccess,
+        "The '-' operator is only defined for random access iterators.");
+    return I - RHS.I;
+  }
+
+  // We have to explicitly provide ++ and -- rather than letting the facade
+  // forward to += because WrappedIteratorT might not support +=.
+  using BaseT::operator++;
+  DerivedT &operator++() {
+    ++I;
+    return *static_cast<DerivedT *>(this);
+  }
+  using BaseT::operator--;
+  DerivedT &operator--() {
+    static_assert(
+        BaseT::IsBidirectional,
+        "The decrement operator is only defined for bidirectional iterators.");
+    --I;
+    return *static_cast<DerivedT *>(this);
+  }
+
+  bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
+  bool operator<(const DerivedT &RHS) const {
+    static_assert(
+        BaseT::IsRandomAccess,
+        "Relational operators are only defined for random access iterators.");
+    return I < RHS.I;
+  }
+
+  ReferenceT operator*() const { return *I; }
+};
+
+/// \brief An iterator type that allows iterating over the pointees via some
+/// other iterator.
+///
+/// The typical usage of this is to expose a type that iterates over Ts, but
+/// which is implemented with some iterator over T*s:
+///
+/// \code
+///   typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator;
+/// \endcode
+template <typename WrappedIteratorT,
+          typename T = typename std::remove_reference<
+              decltype(**std::declval<WrappedIteratorT>())>::type>
+struct pointee_iterator
+    : iterator_adaptor_base<
+          pointee_iterator<WrappedIteratorT>, WrappedIteratorT,
+          typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+          T> {
+  pointee_iterator() = default;
+  template <typename U>
+  pointee_iterator(U &&u)
+      : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
+
+  T &operator*() const { return **this->I; }
+};
+
+template <typename WrappedIteratorT,
+          typename T = decltype(&*std::declval<WrappedIteratorT>())>
+class pointer_iterator
+    : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT>,
+                                   WrappedIteratorT, T> {
+  mutable T Ptr;
+
+public:
+  pointer_iterator() {}
+
+  explicit pointer_iterator(WrappedIteratorT u)
+      : pointer_iterator::iterator_adaptor_base(std::move(u)) {}
+
+  T &operator*() { return Ptr = &*this->I; }
+  const T &operator*() const { return Ptr = &*this->I; }
+};
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/iterator_range.h b/third_party/llvm-subzero/include/llvm/ADT/iterator_range.h
new file mode 100644
index 0000000..3dd679b
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/iterator_range.h
@@ -0,0 +1,68 @@
+//===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This provides a very simple, boring adaptor for a begin and end iterator
+/// into a range type. This should be used to build range views that work well
+/// with range based for loops and range based constructors.
+///
+/// Note that code here follows more standards-based coding conventions as it
+/// is mirroring proposed interfaces for standardization.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ITERATOR_RANGE_H
+#define LLVM_ADT_ITERATOR_RANGE_H
+
+#include <utility>
+#include <iterator>
+
+namespace llvm {
+
+/// \brief A range adaptor for a pair of iterators.
+///
+/// This just wraps two iterators into a range-compatible interface. Nothing
+/// fancy at all.
+template <typename IteratorT>
+class iterator_range {
+  IteratorT begin_iterator, end_iterator;
+
+public:
+  //TODO: Add SFINAE to test that the Container's iterators match the range's
+  //      iterators.
+  template <typename Container>
+  iterator_range(Container &&c)
+  //TODO: Consider ADL/non-member begin/end calls.
+      : begin_iterator(c.begin()), end_iterator(c.end()) {}
+  iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
+      : begin_iterator(std::move(begin_iterator)),
+        end_iterator(std::move(end_iterator)) {}
+
+  IteratorT begin() const { return begin_iterator; }
+  IteratorT end() const { return end_iterator; }
+};
+
+/// \brief Convenience function for iterating over sub-ranges.
+///
+/// This provides a bit of syntactic sugar to make using sub-ranges
+/// in for loops a bit easier. Analogous to std::make_pair().
+template <class T> iterator_range<T> make_range(T x, T y) {
+  return iterator_range<T>(std::move(x), std::move(y));
+}
+
+template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
+  return iterator_range<T>(std::move(p.first), std::move(p.second));
+}
+
+template<typename T>
+iterator_range<decltype(begin(std::declval<T>()))> drop_begin(T &&t, int n) {
+  return make_range(std::next(begin(t), n), end(t));
+}
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/simple_ilist.h b/third_party/llvm-subzero/include/llvm/ADT/simple_ilist.h
new file mode 100644
index 0000000..f9983d8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/ADT/simple_ilist.h
@@ -0,0 +1,269 @@
+//===- llvm/ADT/simple_ilist.h - Simple Intrusive List ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SIMPLE_ILIST_H
+#define LLVM_ADT_SIMPLE_ILIST_H
+
+#include "llvm/ADT/ilist_base.h"
+#include "llvm/ADT/ilist_iterator.h"
+#include "llvm/ADT/ilist_node.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+
+namespace llvm {
+
+/// A simple intrusive list implementation.
+///
+/// This is a simple intrusive list for a \c T that inherits from \c
+/// ilist_node<T>.  The list never takes ownership of anything inserted in it.
+///
+/// Unlike \a iplist<T> and \a ilist<T>, \a simple_ilist<T> never allocates or
+/// deletes values, and has no callback traits.
+///
+/// The API for adding nodes include \a push_front(), \a push_back(), and \a
+/// insert().  These all take values by reference (not by pointer), except for
+/// the range version of \a insert().
+///
+/// There are three sets of API for discarding nodes from the list: \a
+/// remove(), which takes a reference to the node to remove, \a erase(), which
+/// takes an iterator or iterator range and returns the next one, and \a
+/// clear(), which empties out the container.  All three are constant time
+/// operations.  None of these deletes any nodes; in particular, if there is a
+/// single node in the list, then these have identical semantics:
+/// \li \c L.remove(L.front());
+/// \li \c L.erase(L.begin());
+/// \li \c L.clear();
+///
+/// As a convenience for callers, there are parallel APIs that take a \c
+/// Disposer (such as \c std::default_delete<T>): \a removeAndDispose(), \a
+/// eraseAndDispose(), and \a clearAndDispose().  These have different names
+/// because the extra semantic is otherwise non-obvious.  They are equivalent
+/// to calling \a std::for_each() on the range to be discarded.
+template <typename T> class simple_ilist : ilist_base, ilist_node_access {
+  ilist_sentinel<T> Sentinel;
+
+public:
+  typedef T value_type;
+  typedef T *pointer;
+  typedef T &reference;
+  typedef const T *const_pointer;
+  typedef const T &const_reference;
+  typedef ilist_iterator<T> iterator;
+  typedef ilist_iterator<const T> const_iterator;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef ilist_iterator<const T, true> const_reverse_iterator;
+  typedef ilist_iterator<T, true> reverse_iterator;
+
+  simple_ilist() = default;
+  ~simple_ilist() = default;
+
+  // No copy constructors.
+  simple_ilist(const simple_ilist &) = delete;
+  simple_ilist &operator=(const simple_ilist &) = delete;
+
+  // Move constructors.
+  simple_ilist(simple_ilist &&X) { splice(end(), X); }
+  simple_ilist &operator=(simple_ilist &&X) {
+    clear();
+    splice(end(), X);
+    return *this;
+  }
+
+  iterator begin() { return ++iterator(Sentinel); }
+  const_iterator begin() const { return ++const_iterator(Sentinel); }
+  iterator end() { return iterator(Sentinel); }
+  const_iterator end() const { return const_iterator(Sentinel); }
+  reverse_iterator rbegin() { return ++reverse_iterator(Sentinel); }
+  const_reverse_iterator rbegin() const {
+    return ++const_reverse_iterator(Sentinel);
+  }
+  reverse_iterator rend() { return reverse_iterator(Sentinel); }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(Sentinel);
+  }
+
+  /// Check if the list is empty in constant time.
+  bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return Sentinel.empty(); }
+
+  /// Calculate the size of the list in linear time.
+  size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const {
+    return std::distance(begin(), end());
+  }
+
+  reference front() { return *begin(); }
+  const_reference front() const { return *begin(); }
+  reference back() { return *rbegin(); }
+  const_reference back() const { return *rbegin(); }
+
+  /// Insert a node at the front; never copies.
+  void push_front(reference Node) { insert(begin(), Node); }
+
+  /// Insert a node at the back; never copies.
+  void push_back(reference Node) { insert(end(), Node); }
+
+  /// Remove the node at the front; never deletes.
+  void pop_front() { erase(begin()); }
+
+  /// Remove the node at the back; never deletes.
+  void pop_back() { erase(--end()); }
+
+  /// Swap with another list in place using std::swap.
+  void swap(simple_ilist &X) { std::swap(*this, X); }
+
+  /// Insert a node by reference; never copies.
+  iterator insert(iterator I, reference Node) {
+    ilist_base::insertBefore(*I.getNodePtr(), *this->getNodePtr(&Node));
+    return iterator(&Node);
+  }
+
+  /// Insert a range of nodes; never copies.
+  template <class Iterator>
+  void insert(iterator I, Iterator First, Iterator Last) {
+    for (; First != Last; ++First)
+      insert(I, *First);
+  }
+
+  /// Remove a node by reference; never deletes.
+  ///
+  /// \see \a erase() for removing by iterator.
+  /// \see \a removeAndDispose() if the node should be deleted.
+  void remove(reference N) { ilist_base::remove(*this->getNodePtr(&N)); }
+
+  /// Remove a node by reference and dispose of it.
+  template <class Disposer>
+  void removeAndDispose(reference N, Disposer dispose) {
+    remove(N);
+    dispose(&N);
+  }
+
+  /// Remove a node by iterator; never deletes.
+  ///
+  /// \see \a remove() for removing by reference.
+  /// \see \a eraseAndDispose() it the node should be deleted.
+  iterator erase(iterator I) {
+    assert(I != end() && "Cannot remove end of list!");
+    remove(*I++);
+    return I;
+  }
+
+  /// Remove a range of nodes; never deletes.
+  ///
+  /// \see \a eraseAndDispose() if the nodes should be deleted.
+  iterator erase(iterator First, iterator Last) {
+    ilist_base::removeRange(*First.getNodePtr(), *Last.getNodePtr());
+    return Last;
+  }
+
+  /// Remove a node by iterator and dispose of it.
+  template <class Disposer>
+  iterator eraseAndDispose(iterator I, Disposer dispose) {
+    auto Next = std::next(I);
+    erase(I);
+    dispose(&*I);
+    return Next;
+  }
+
+  /// Remove a range of nodes and dispose of them.
+  template <class Disposer>
+  iterator eraseAndDispose(iterator First, iterator Last, Disposer dispose) {
+    while (First != Last)
+      First = eraseAndDispose(First, dispose);
+    return Last;
+  }
+
+  /// Clear the list; never deletes.
+  ///
+  /// \see \a clearAndDispose() if the nodes should be deleted.
+  void clear() { Sentinel.reset(); }
+
+  /// Clear the list and dispose of the nodes.
+  template <class Disposer> void clearAndDispose(Disposer dispose) {
+    eraseAndDispose(begin(), end(), dispose);
+  }
+
+  /// Splice in another list.
+  void splice(iterator I, simple_ilist &L2) {
+    splice(I, L2, L2.begin(), L2.end());
+  }
+
+  /// Splice in a node from another list.
+  void splice(iterator I, simple_ilist &L2, iterator Node) {
+    splice(I, L2, Node, std::next(Node));
+  }
+
+  /// Splice in a range of nodes from another list.
+  void splice(iterator I, simple_ilist &, iterator First, iterator Last) {
+    ilist_base::transferBefore(*I.getNodePtr(), *First.getNodePtr(),
+                               *Last.getNodePtr());
+  }
+
+  /// Merge in another list.
+  ///
+  /// \pre \c this and \p RHS are sorted.
+  ///@{
+  void merge(simple_ilist &RHS) { merge(RHS, std::less<T>()); }
+  template <class Compare> void merge(simple_ilist &RHS, Compare comp);
+  ///@}
+
+  /// Sort the list.
+  ///@{
+  void sort() { sort(std::less<T>()); }
+  template <class Compare> void sort(Compare comp);
+  ///@}
+};
+
+template <class T>
+template <class Compare>
+void simple_ilist<T>::merge(simple_ilist<T> &RHS, Compare comp) {
+  if (this == &RHS || RHS.empty())
+    return;
+  iterator LI = begin(), LE = end();
+  iterator RI = RHS.begin(), RE = RHS.end();
+  while (LI != LE) {
+    if (comp(*RI, *LI)) {
+      // Transfer a run of at least size 1 from RHS to LHS.
+      iterator RunStart = RI++;
+      RI = std::find_if(RI, RE, [&](reference RV) { return !comp(RV, *LI); });
+      splice(LI, RHS, RunStart, RI);
+      if (RI == RE)
+        return;
+    }
+    ++LI;
+  }
+  // Transfer the remaining RHS nodes once LHS is finished.
+  splice(LE, RHS, RI, RE);
+}
+
+template <class T>
+template <class Compare>
+void simple_ilist<T>::sort(Compare comp) {
+  // Vacuously sorted.
+  if (empty() || std::next(begin()) == end())
+    return;
+
+  // Split the list in the middle.
+  iterator Center = begin(), End = begin();
+  while (End != end() && ++End != end()) {
+    ++Center;
+    ++End;
+  }
+  simple_ilist<T> RHS;
+  RHS.splice(RHS.end(), *this, Center, end());
+
+  // Sort the sublists and merge back together.
+  sort(comp);
+  RHS.sort(comp);
+  merge(RHS, comp);
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_SIMPLE_ILIST_H
diff --git a/third_party/llvm-subzero/include/llvm/Config/config.h b/third_party/llvm-subzero/include/llvm/Config/config.h
new file mode 100644
index 0000000..2d77390
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Config/config.h
@@ -0,0 +1,584 @@
+/* include/llvm/Config/config.h.cmake corresponding to config.h.in. */

+

+#ifndef CONFIG_H

+#define CONFIG_H

+

+/* Exported configuration */

+#include "llvm/Config/llvm-config.h"

+

+/* Bug report URL. */

+#define BUG_REPORT_URL "http://llvm.org/bugs/"

+

+/* Define if you want backtraces on crash */

+#define ENABLE_BACKTRACES

+

+/* Define to enable crash overrides */

+#define ENABLE_CRASH_OVERRIDES

+

+/* Define to disable C++ atexit */

+#define DISABLE_LLVM_DYLIB_ATEXIT

+

+/* Define if position independent code is enabled */

+#define ENABLE_PIC

+

+/* Define if timestamp information (e.g., __DATE__) is allowed */

+#define ENABLE_TIMESTAMPS 1

+

+/* Define to 1 if you have the `arc4random' function. */

+/* #undef HAVE_DECL_ARC4RANDOM */

+

+/* Define to 1 if you have the `backtrace' function. */

+/* #undef HAVE_BACKTRACE */

+

+/* Define to 1 if you have the `bcopy' function. */

+#undef HAVE_BCOPY

+

+/* Define to 1 if you have the `closedir' function. */

+/* #undef HAVE_CLOSEDIR */

+

+/* Define to 1 if you have the <cxxabi.h> header file. */

+/* #undef HAVE_CXXABI_H */

+

+/* Define to 1 if you have the <CrashReporterClient.h> header file. */

+#undef HAVE_CRASHREPORTERCLIENT_H

+

+/* can use __crashreporter_info__ */

+#undef HAVE_CRASHREPORTER_INFO

+

+/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you

+don't. */

+#define HAVE_DECL_STRERROR_S 1

+

+/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */

+/* #undef HAVE_DIA_SDK */

+

+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.

+*/

+/* #undef HAVE_DIRENT_H */

+

+/* Define if you have the GNU dld library. */

+#undef HAVE_DLD

+

+/* Define to 1 if you have the `dlerror' function. */

+/* #undef HAVE_DLERROR */

+

+/* Define to 1 if you have the <dlfcn.h> header file. */

+/* #undef HAVE_DLFCN_H */

+

+/* Define if dlopen() is available on this platform. */

+/* #undef HAVE_DLOPEN */

+

+/* Define if you have the _dyld_func_lookup function. */

+#undef HAVE_DYLD

+

+/* Define to 1 if you have the <errno.h> header file. */

+#define HAVE_ERRNO_H 1

+

+/* Define to 1 if you have the <execinfo.h> header file. */

+/* #undef HAVE_EXECINFO_H */

+

+/* Define to 1 if you have the <fcntl.h> header file. */

+#define HAVE_FCNTL_H 1

+

+/* Define to 1 if you have the <fenv.h> header file. */

+#define HAVE_FENV_H 1

+

+/* Define if libffi is available on this platform. */

+/* #undef HAVE_FFI_CALL */

+

+/* Define to 1 if you have the <ffi/ffi.h> header file. */

+/* #undef HAVE_FFI_FFI_H */

+

+/* Define to 1 if you have the <ffi.h> header file. */

+/* #undef HAVE_FFI_H */

+

+/* Define to 1 if you have the `futimes' function. */

+/* #undef HAVE_FUTIMES */

+

+/* Define to 1 if you have the `futimens' function */

+/* #undef HAVE_FUTIMENS */

+

+/* Define to 1 if you have the `getcwd' function. */

+/* #undef HAVE_GETCWD */

+

+/* Define to 1 if you have the `getpagesize' function. */

+/* #undef HAVE_GETPAGESIZE */

+

+/* Define to 1 if you have the `getrlimit' function. */

+/* #undef HAVE_GETRLIMIT */

+

+/* Define to 1 if you have the `getrusage' function. */

+/* #undef HAVE_GETRUSAGE */

+

+/* Define to 1 if you have the `gettimeofday' function. */

+/* #undef HAVE_GETTIMEOFDAY */

+

+/* Define to 1 if the system has the type `int64_t'. */

+#define HAVE_INT64_T 1

+

+/* Define to 1 if you have the <inttypes.h> header file. */

+#define HAVE_INTTYPES_H 1

+

+/* Define to 1 if you have the `isatty' function. */

+/* #undef HAVE_ISATTY */

+

+/* Define if you have the libdl library or equivalent. */

+/* #undef HAVE_LIBDL */

+

+/* Define to 1 if you have the `m' library (-lm). */

+#undef HAVE_LIBM

+

+/* Define to 1 if you have the `ole32' library (-lole32). */

+#undef HAVE_LIBOLE32

+

+/* Define to 1 if you have the `psapi' library (-lpsapi). */

+/* #undef HAVE_LIBPSAPI */

+

+/* Define to 1 if you have the `pthread' library (-lpthread). */

+/* #undef HAVE_LIBPTHREAD */

+

+/* Define to 1 if you have the `shell32' library (-lshell32). */

+/* #undef HAVE_LIBSHELL32 */

+

+/* Define to 1 if you have the 'z' library (-lz). */

+/* #undef HAVE_LIBZ */

+

+/* Define to 1 if you have the 'edit' library (-ledit). */

+/* #undef HAVE_LIBEDIT */

+

+/* Define to 1 if you have the <limits.h> header file. */

+#define HAVE_LIMITS_H 1

+

+/* Define to 1 if you have the <link.h> header file. */

+/* #undef HAVE_LINK_H */

+

+/* Define if you can use -rdynamic. */

+#define HAVE_LINK_EXPORT_DYNAMIC 1

+

+/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add

+the current directory to the dynamic linker search path. */

+#undef HAVE_LINK_R

+

+/* Define to 1 if you have the `longjmp' function. */

+/* #undef HAVE_LONGJMP */

+

+/* Define to 1 if you have the <mach/mach.h> header file. */

+/* #undef HAVE_MACH_MACH_H */

+

+/* Define to 1 if you have the <mach-o/dyld.h> header file. */

+/* #undef HAVE_MACH_O_DYLD_H */

+

+/* Define if mallinfo() is available on this platform. */

+/* #undef HAVE_MALLINFO */

+

+/* Define to 1 if you have the <malloc.h> header file. */

+#define HAVE_MALLOC_H 1

+

+/* Define to 1 if you have the <malloc/malloc.h> header file. */

+/* #undef HAVE_MALLOC_MALLOC_H */

+

+/* Define to 1 if you have the `malloc_zone_statistics' function. */

+/* #undef HAVE_MALLOC_ZONE_STATISTICS */

+

+/* Define to 1 if you have the `mallctl` function. */

+/* #undef HAVE_MALLCTL */

+

+/* Define to 1 if you have the `mkdtemp' function. */

+/* #undef HAVE_MKDTEMP */

+

+/* Define to 1 if you have the `mkstemp' function. */

+/* #undef HAVE_MKSTEMP */

+

+/* Define to 1 if you have the `mktemp' function. */

+/* #undef HAVE_MKTEMP */

+

+/* Define to 1 if you have a working `mmap' system call. */

+#undef HAVE_MMAP

+

+/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if

+it uses MAP_ANON */

+#undef HAVE_MMAP_ANONYMOUS

+

+/* Define if mmap() can map files into memory */

+#undef HAVE_MMAP_FILE

+

+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */

+/* #undef HAVE_NDIR_H */

+

+/* Define to 1 if you have the `opendir' function. */

+/* #undef HAVE_OPENDIR */

+

+/* Define to 1 if you have the `posix_spawn' function. */

+/* #undef HAVE_POSIX_SPAWN */

+

+/* Define to 1 if you have the `pread' function. */

+/* #undef HAVE_PREAD */

+

+/* Define if libtool can extract symbol lists from object files. */

+#undef HAVE_PRELOADED_SYMBOLS

+

+/* Define to have the %a format string */

+#undef HAVE_PRINTF_A

+

+/* Have pthread_getspecific */

+/* #undef HAVE_PTHREAD_GETSPECIFIC */

+

+/* Define to 1 if you have the <pthread.h> header file. */

+/* #undef HAVE_PTHREAD_H */

+

+/* Have pthread_mutex_lock */

+/* #undef HAVE_PTHREAD_MUTEX_LOCK */

+

+/* Have pthread_rwlock_init */

+/* #undef HAVE_PTHREAD_RWLOCK_INIT */

+

+/* Define to 1 if srand48/lrand48/drand48 exist in <stdlib.h> */

+/* #undef HAVE_RAND48 */

+

+/* Define to 1 if you have the `readdir' function. */

+/* #undef HAVE_READDIR */

+

+/* Define to 1 if you have the `realpath' function. */

+/* #undef HAVE_REALPATH */

+

+/* Define to 1 if you have the `sbrk' function. */

+/* #undef HAVE_SBRK */

+

+/* Define to 1 if you have the `setenv' function. */

+/* #undef HAVE_SETENV */

+

+/* Define to 1 if you have the `setjmp' function. */

+/* #undef HAVE_SETJMP */

+

+/* Define to 1 if you have the `setrlimit' function. */

+/* #undef HAVE_SETRLIMIT */

+

+/* Define if you have the shl_load function. */

+#undef HAVE_SHL_LOAD

+

+/* Define to 1 if you have the `siglongjmp' function. */

+/* #undef HAVE_SIGLONGJMP */

+

+/* Define to 1 if you have the <signal.h> header file. */

+#define HAVE_SIGNAL_H 1

+

+/* Define to 1 if you have the `sigsetjmp' function. */

+/* #undef HAVE_SIGSETJMP */

+

+/* Define to 1 if you have the <stdint.h> header file. */

+#define HAVE_STDINT_H 1

+

+/* Set to 1 if the std::isinf function is found in <cmath> */

+#undef HAVE_STD_ISINF_IN_CMATH

+

+/* Set to 1 if the std::isnan function is found in <cmath> */

+#undef HAVE_STD_ISNAN_IN_CMATH

+

+/* Define to 1 if you have the `strdup' function. */

+/* #undef HAVE_STRDUP */

+

+/* Define to 1 if you have the `strerror' function. */

+#define HAVE_STRERROR 1

+

+/* Define to 1 if you have the `strerror_r' function. */

+/* #undef HAVE_STRERROR_R */

+

+/* Define to 1 if you have the `strtoll' function. */

+#define HAVE_STRTOLL 1

+

+/* Define to 1 if you have the `strtoq' function. */

+/* #undef HAVE_STRTOQ */

+

+/* Define to 1 if you have the `sysconf' function. */

+#undef HAVE_SYSCONF

+

+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.

+*/

+/* #undef HAVE_SYS_DIR_H */

+

+/* Define to 1 if you have the <sys/ioctl.h> header file. */

+/* #undef HAVE_SYS_IOCTL_H */

+

+/* Define to 1 if you have the <sys/mman.h> header file. */

+/* #undef HAVE_SYS_MMAN_H */

+

+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.

+*/

+/* #undef HAVE_SYS_NDIR_H */

+

+/* Define to 1 if you have the <sys/param.h> header file. */

+/* #undef HAVE_SYS_PARAM_H */

+

+/* Define to 1 if you have the <sys/resource.h> header file. */

+/* #undef HAVE_SYS_RESOURCE_H */

+

+/* Define to 1 if you have the <sys/stat.h> header file. */

+#define HAVE_SYS_STAT_H 1

+

+/* Define to 1 if you have the <sys/time.h> header file. */

+/* #undef HAVE_SYS_TIME_H */

+

+/* Define to 1 if you have the <sys/types.h> header file. */

+/* #undef HAVE_SYS_TYPES_H */

+

+/* Define to 1 if you have the <sys/uio.h> header file. */

+/* #undef HAVE_SYS_UIO_H */

+

+/* Define if the setupterm() function is supported this platform. */

+/* #undef HAVE_TERMINFO */

+

+/* Define to 1 if you have the <termios.h> header file. */

+/* #undef HAVE_TERMIOS_H */

+

+/* Define to 1 if the system has the type `uint64_t'. */

+#define HAVE_UINT64_T 1

+

+/* Define to 1 if you have the <unistd.h> header file. */

+/* #undef HAVE_UNISTD_H */

+

+/* Define to 1 if you have the <utime.h> header file. */

+/* #undef HAVE_UTIME_H */

+

+/* Define to 1 if the system has the type `u_int64_t'. */

+/* #undef HAVE_U_INT64_T */

+

+/* Define to 1 if you have the <valgrind/valgrind.h> header file. */

+/* #undef HAVE_VALGRIND_VALGRIND_H */

+

+/* Define to 1 if you have the `writev' function. */

+/* #undef HAVE_WRITEV */

+

+/* Define to 1 if you have the <zlib.h> header file. */

+/* #undef HAVE_ZLIB_H */

+

+/* Have host's _alloca */

+/* #undef HAVE__ALLOCA */

+

+/* Have host's __alloca */

+/* #undef HAVE___ALLOCA */

+

+/* Have host's __ashldi3 */

+/* #undef HAVE___ASHLDI3 */

+

+/* Have host's __ashrdi3 */

+/* #undef HAVE___ASHRDI3 */

+

+/* Have host's __chkstk */

+/* #undef HAVE___CHKSTK */

+

+/* Have host's __chkstk_ms */

+/* #undef HAVE___CHKSTK_MS */

+

+/* Have host's __cmpdi2 */

+/* #undef HAVE___CMPDI2 */

+

+/* Have host's __divdi3 */

+/* #undef HAVE___DIVDI3 */

+

+/* Define to 1 if you have the `__dso_handle' function. */

+#undef HAVE___DSO_HANDLE

+

+/* Have host's __fixdfdi */

+/* #undef HAVE___FIXDFDI */

+

+/* Have host's __fixsfdi */

+/* #undef HAVE___FIXSFDI */

+

+/* Have host's __floatdidf */

+/* #undef HAVE___FLOATDIDF */

+

+/* Have host's __lshrdi3 */

+/* #undef HAVE___LSHRDI3 */

+

+/* Have host's __main */

+/* #undef HAVE___MAIN */

+

+/* Have host's __moddi3 */

+/* #undef HAVE___MODDI3 */

+

+/* Have host's __udivdi3 */

+/* #undef HAVE___UDIVDI3 */

+

+/* Have host's __umoddi3 */

+/* #undef HAVE___UMODDI3 */

+

+/* Have host's ___chkstk */

+/* #undef HAVE____CHKSTK */

+

+/* Have host's ___chkstk_ms */

+/* #undef HAVE____CHKSTK_MS */

+

+/* Linker version detected at compile time. */

+#undef HOST_LINK_VERSION

+

+/* Installation directory for binary executables */

+/* #undef LLVM_BINDIR */

+

+/* Time at which LLVM was configured */

+/* #undef LLVM_CONFIGTIME */

+

+/* Installation directory for data files */

+/* #undef LLVM_DATADIR */

+

+/* Target triple LLVM will generate code for by default

+* Doesn't use `cmakedefine` because it is allowed to be empty.

+*/

+#define LLVM_DEFAULT_TARGET_TRIPLE "i686-pc-win32"

+

+/* Installation directory for documentation */

+/* #undef LLVM_DOCSDIR */

+

+/* Define if LLVM is built with asserts and checks that change the layout of

+client-visible data structures.  */

+#define LLVM_ENABLE_ABI_BREAKING_CHECKS

+

+/* Define if threads enabled */

+#define LLVM_ENABLE_THREADS 1

+

+/* Define if zlib compression is available */

+#define LLVM_ENABLE_ZLIB 0

+

+/* Installation directory for config files */

+/* #undef LLVM_ETCDIR */

+

+/* Has gcc/MSVC atomic intrinsics */

+#define LLVM_HAS_ATOMICS 1

+

+/* Host triple LLVM will be executed on */

+#define LLVM_HOST_TRIPLE "i686-pc-win32"

+

+/* Installation directory for include files */

+/* #undef LLVM_INCLUDEDIR */

+

+/* Installation directory for .info files */

+/* #undef LLVM_INFODIR */

+

+/* Installation directory for man pages */

+/* #undef LLVM_MANDIR */

+

+/* LLVM architecture name for the native architecture, if available */

+#define LLVM_NATIVE_ARCH X86

+

+/* LLVM name for the native AsmParser init function, if available */

+#define LLVM_NATIVE_ASMPARSER LLVMInitializeX86AsmParser

+

+/* LLVM name for the native AsmPrinter init function, if available */

+#define LLVM_NATIVE_ASMPRINTER LLVMInitializeX86AsmPrinter

+

+/* LLVM name for the native Disassembler init function, if available */

+#define LLVM_NATIVE_DISASSEMBLER LLVMInitializeX86Disassembler

+

+/* LLVM name for the native Target init function, if available */

+#define LLVM_NATIVE_TARGET LLVMInitializeX86Target

+

+/* LLVM name for the native TargetInfo init function, if available */

+#define LLVM_NATIVE_TARGETINFO LLVMInitializeX86TargetInfo

+

+/* LLVM name for the native target MC init function, if available */

+#define LLVM_NATIVE_TARGETMC LLVMInitializeX86TargetMC

+

+/* Define if this is Unixish platform */

+/* #undef LLVM_ON_UNIX */

+

+/* Define if this is Win32ish platform */

+#define LLVM_ON_WIN32 1

+

+/* Installation prefix directory */

+#define LLVM_PREFIX "C:/Program Files (x86)/LLVM"

+

+/* Define if we have the Intel JIT API runtime support library */

+/* #undef LLVM_USE_INTEL_JITEVENTS */

+

+/* Define if we have the oprofile JIT-support library */

+/* #undef LLVM_USE_OPROFILE */

+

+/* Major version of the LLVM API */

+#define LLVM_VERSION_MAJOR 3

+

+/* Minor version of the LLVM API */

+#define LLVM_VERSION_MINOR 8

+

+/* Patch version of the LLVM API */

+#define LLVM_VERSION_PATCH 1

+

+/* LLVM version string */

+#define LLVM_VERSION_STRING "3.8.1"

+

+/* Define if we link Polly to the tools */

+/* #undef LINK_POLLY_INTO_TOOLS */

+

+/* Define if the OS needs help to load dependent libraries for dlopen(). */

+/* #undef LTDL_DLOPEN_DEPLIBS */

+

+/* Define to the sub-directory in which libtool stores uninstalled libraries.

+*/

+#undef LTDL_OBJDIR

+

+/* Define to the extension used for shared libraries, say, ".so". */

+#define LTDL_SHLIB_EXT ".dll"

+

+/* Define to the system default library search path. */

+/* #undef LTDL_SYSSEARCHPATH */

+

+/* Define if /dev/zero should be used when mapping RWX memory, or undefine if

+its not necessary */

+#undef NEED_DEV_ZERO_FOR_MMAP

+

+/* Define if dlsym() requires a leading underscore in symbol names. */

+#undef NEED_USCORE

+

+/* Define to the address where bug reports for this package should be sent. */

+#define PACKAGE_BUGREPORT "http://llvm.org/bugs/"

+

+/* Define to the full name of this package. */

+#define PACKAGE_NAME "LLVM"

+

+/* Define to the full name and version of this package. */

+#define PACKAGE_STRING "LLVM 3.8.1"

+

+/* Define to the one symbol short name of this package. */

+#undef PACKAGE_TARNAME

+

+/* Define to the version of this package. */

+#define PACKAGE_VERSION "3.8.1"

+

+/* Define as the return type of signal handlers (`int' or `void'). */

+#define RETSIGTYPE void

+

+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */

+#undef STAT_MACROS_BROKEN

+

+/* Define to 1 if you have the ANSI C header files. */

+#undef STDC_HEADERS

+

+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */

+#undef TIME_WITH_SYS_TIME

+

+/* Define to 1 if your <sys/time.h> declares `struct tm'. */

+#undef TM_IN_SYS_TIME

+

+/* Type of 1st arg on ELM Callback */

+#define WIN32_ELMCB_PCSTR PCSTR

+

+/* Define to `int' if <sys/types.h> does not define. */

+#undef pid_t

+

+/* Define to `unsigned int' if <sys/types.h> does not define. */

+#undef size_t

+

+/* Define to a function replacing strtoll */

+/* #undef strtoll */

+

+/* Define to a function implementing strtoull */

+/* #undef strtoull */

+

+/* Define to a function implementing stricmp */

+#define stricmp _stricmp

+

+/* Define to a function implementing strdup */

+#define strdup _strdup

+

+/* Define to 1 if you have the `_chsize_s' function. */

+#define HAVE__CHSIZE_S 1

+

+#endif

diff --git a/third_party/llvm-subzero/include/llvm/Config/llvm-config.h b/third_party/llvm-subzero/include/llvm/Config/llvm-config.h
new file mode 100644
index 0000000..9a2ee7c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Config/llvm-config.h
@@ -0,0 +1,106 @@
+/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/
+/*                                                                            */
+/*                     The LLVM Compiler Infrastructure                       */
+/*                                                                            */
+/* This file is distributed under the University of Illinois Open Source      */
+/* License. See LICENSE.TXT for details.                                      */
+/*                                                                            */
+/*===----------------------------------------------------------------------===*/
+
+/* This file enumerates all of the llvm variables from configure so that
+   they can be in exported headers and won't override package specific
+   directives.  This is a C file so we can include it in the llvm-c headers.  */
+
+/* To avoid multiple inclusions of these variables when we include the exported
+   headers and config.h, conditionally include these.  */
+/* TODO: This is a bit of a hack.  */
+#ifndef CONFIG_H
+
+/* Installation directory for binary executables */
+/* #undef LLVM_BINDIR */
+
+/* Time at which LLVM was configured */
+/* #undef LLVM_CONFIGTIME */
+
+/* Installation directory for data files */
+/* #undef LLVM_DATADIR */
+
+/* Installation directory for documentation */
+/* #undef LLVM_DOCSDIR */
+
+/* Installation directory for config files */
+/* #undef LLVM_ETCDIR */
+
+/* Has gcc/MSVC atomic intrinsics */
+#define LLVM_HAS_ATOMICS 1
+
+/* Host triple we were built on */
+#define LLVM_HOSTTRIPLE "i686-pc-win32"
+
+/* Installation directory for include files */
+/* #undef LLVM_INCLUDEDIR */
+
+/* Installation directory for .info files */
+/* #undef LLVM_INFODIR */
+
+/* Installation directory for libraries */
+/* #undef LLVM_LIBDIR */
+
+/* Installation directory for man pages */
+/* #undef LLVM_MANDIR */
+
+/* LLVM architecture name for the native architecture, if available */
+#define LLVM_NATIVE_ARCH X86
+
+/* LLVM name for the native AsmParser init function, if available */
+/* #undef LLVM_NATIVE_ASMPARSER */
+
+/* LLVM name for the native AsmPrinter init function, if available */
+#define LLVM_NATIVE_ASMPRINTER LLVMInitializeX86AsmPrinter
+
+/* LLVM name for the native Target init function, if available */
+#define LLVM_NATIVE_TARGET LLVMInitializeX86Target
+
+/* LLVM name for the native TargetInfo init function, if available */
+#define LLVM_NATIVE_TARGETINFO LLVMInitializeX86TargetInfo
+
+/* LLVM name for the native target MC init function, if available */
+#define LLVM_NATIVE_TARGETMC LLVMInitializeX86TargetMC
+
+/* Define if this is Unixish platform */
+/* #undef LLVM_ON_UNIX */
+
+/* Define if this is Win32ish platform */
+#define LLVM_ON_WIN32 1
+
+/* Define to path to circo program if found or 'echo circo' otherwise */
+/* #undef LLVM_PATH_CIRCO */
+
+/* Define to path to dot program if found or 'echo dot' otherwise */
+/* #undef LLVM_PATH_DOT */
+
+/* Define to path to dotty program if found or 'echo dotty' otherwise */
+/* #undef LLVM_PATH_DOTTY */
+
+/* Define to path to fdp program if found or 'echo fdp' otherwise */
+/* #undef LLVM_PATH_FDP */
+
+/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */
+/* #undef LLVM_PATH_GRAPHVIZ */
+
+/* Define to path to gv program if found or 'echo gv' otherwise */
+/* #undef LLVM_PATH_GV */
+
+/* Define to path to neato program if found or 'echo neato' otherwise */
+/* #undef LLVM_PATH_NEATO */
+
+/* Define to path to twopi program if found or 'echo twopi' otherwise */
+/* #undef LLVM_PATH_TWOPI */
+
+/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */
+/* #undef LLVM_PATH_XDOT_PY */
+
+/* Installation prefix directory */
+#define LLVM_PREFIX "C:/Program Files (x86)/LLVM"
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Argument.h b/third_party/llvm-subzero/include/llvm/IR/Argument.h
new file mode 100644
index 0000000..d8b280a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Argument.h
@@ -0,0 +1,152 @@
+//===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the Argument class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_ARGUMENT_H
+#define LLVM_IR_ARGUMENT_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Value.h"
+
+namespace llvm {
+
+template <typename NodeTy> class SymbolTableListTraits;
+
+/// \brief LLVM Argument representation
+///
+/// This class represents an incoming formal argument to a Function. A formal
+/// argument, since it is ``formal'', does not contain an actual value but
+/// instead represents the type, argument number, and attributes of an argument
+/// for a specific function. When used in the body of said function, the
+/// argument of course represents the value of the actual argument that the
+/// function was called with.
+class Argument : public Value, public ilist_node<Argument> {
+  virtual void anchor();
+  Function *Parent;
+
+  friend class SymbolTableListTraits<Argument>;
+  void setParent(Function *parent);
+
+public:
+  /// \brief Constructor.
+  ///
+  /// If \p F is specified, the argument is inserted at the end of the argument
+  /// list for \p F.
+  explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr);
+
+  inline const Function *getParent() const { return Parent; }
+  inline       Function *getParent()       { return Parent; }
+
+  /// \brief Return the index of this formal argument in its containing
+  /// function.
+  ///
+  /// For example in "void foo(int a, float b)" a is 0 and b is 1.
+  unsigned getArgNo() const;
+
+  /// \brief Return true if this argument has the nonnull attribute on it in
+  /// its containing function. Also returns true if at least one byte is known
+  /// to be dereferenceable and the pointer is in addrspace(0).
+  bool hasNonNullAttr() const;
+
+  /// \brief If this argument has the dereferenceable attribute on it in its
+  /// containing function, return the number of bytes known to be
+  /// dereferenceable. Otherwise, zero is returned.
+  uint64_t getDereferenceableBytes() const;
+
+  /// \brief If this argument has the dereferenceable_or_null attribute on
+  /// it in its containing function, return the number of bytes known to be
+  /// dereferenceable. Otherwise, zero is returned.
+  uint64_t getDereferenceableOrNullBytes() const;
+
+  /// \brief Return true if this argument has the byval attribute on it in its
+  /// containing function.
+  bool hasByValAttr() const;
+
+  /// \brief Return true if this argument has the swiftself attribute.
+  bool hasSwiftSelfAttr() const;
+
+  /// \brief Return true if this argument has the swifterror attribute.
+  bool hasSwiftErrorAttr() const;
+
+  /// \brief Return true if this argument has the byval attribute or inalloca
+  /// attribute on it in its containing function.  These attributes both
+  /// represent arguments being passed by value.
+  bool hasByValOrInAllocaAttr() const;
+
+  /// \brief If this is a byval or inalloca argument, return its alignment.
+  unsigned getParamAlignment() const;
+
+  /// \brief Return true if this argument has the nest attribute on it in its
+  /// containing function.
+  bool hasNestAttr() const;
+
+  /// \brief Return true if this argument has the noalias attribute on it in its
+  /// containing function.
+  bool hasNoAliasAttr() const;
+
+  /// \brief Return true if this argument has the nocapture attribute on it in
+  /// its containing function.
+  bool hasNoCaptureAttr() const;
+
+  /// \brief Return true if this argument has the sret attribute on it in its
+  /// containing function.
+  bool hasStructRetAttr() const;
+
+  /// \brief Return true if this argument has the returned attribute on it in
+  /// its containing function.
+  bool hasReturnedAttr() const;
+
+  /// \brief Return true if this argument has the readonly or readnone attribute
+  /// on it in its containing function.
+  bool onlyReadsMemory() const;
+
+  /// \brief Return true if this argument has the inalloca attribute on it in
+  /// its containing function.
+  bool hasInAllocaAttr() const;
+
+  /// \brief Return true if this argument has the zext attribute on it in its
+  /// containing function.
+  bool hasZExtAttr() const;
+
+  /// \brief Return true if this argument has the sext attribute on it in its
+  /// containing function.
+  bool hasSExtAttr() const;
+
+  /// \brief Add a Attribute to an argument.
+  void addAttr(AttributeSet AS);
+
+  void addAttr(Attribute::AttrKind Kind) {
+    addAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+  }
+
+  /// \brief Remove a Attribute from an argument.
+  void removeAttr(AttributeSet AS);
+
+  void removeAttr(Attribute::AttrKind Kind) {
+    removeAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+  }
+
+  /// \brief Checks if an argument has a given attribute.
+  bool hasAttribute(Attribute::AttrKind Kind) const;
+
+  /// \brief Method for support type inquiry through isa, cast, and
+  /// dyn_cast.
+  static inline bool classof(const Value *V) {
+    return V->getValueID() == ArgumentVal;
+  }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Attributes.h b/third_party/llvm-subzero/include/llvm/IR/Attributes.h
new file mode 100644
index 0000000..5ef0371
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Attributes.h
@@ -0,0 +1,612 @@
+//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the simple types necessary to represent the
+/// attributes associated with functions and their calls.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_ATTRIBUTES_H
+#define LLVM_IR_ATTRIBUTES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm-c/Types.h"
+#include <bitset>
+#include <cassert>
+#include <map>
+#include <string>
+
+namespace llvm {
+
+class AttrBuilder;
+class AttributeImpl;
+class AttributeSetImpl;
+class AttributeSetNode;
+class Constant;
+template<typename T> struct DenseMapInfo;
+class Function;
+class LLVMContext;
+class Type;
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief Functions, function parameters, and return types can have attributes
+/// to indicate how they should be treated by optimizations and code
+/// generation. This class represents one of those attributes. It's light-weight
+/// and should be passed around by-value.
+class Attribute {
+public:
+  /// This enumeration lists the attributes that can be associated with
+  /// parameters, function results, or the function itself.
+  ///
+  /// Note: The `uwtable' attribute is about the ABI or the user mandating an
+  /// entry in the unwind table. The `nounwind' attribute is about an exception
+  /// passing by the function.
+  ///
+  /// In a theoretical system that uses tables for profiling and SjLj for
+  /// exceptions, they would be fully independent. In a normal system that uses
+  /// tables for both, the semantics are:
+  ///
+  /// nil                = Needs an entry because an exception might pass by.
+  /// nounwind           = No need for an entry
+  /// uwtable            = Needs an entry because the ABI says so and because
+  ///                      an exception might pass by.
+  /// uwtable + nounwind = Needs an entry because the ABI says so.
+
+  enum AttrKind {
+    // IR-Level Attributes
+    None,                  ///< No attributes have been set
+    #define GET_ATTR_ENUM
+    #include "llvm/IR/Attributes.inc"
+    EndAttrKinds           ///< Sentinal value useful for loops
+  };
+
+private:
+  AttributeImpl *pImpl;
+  Attribute(AttributeImpl *A) : pImpl(A) {}
+
+public:
+  Attribute() : pImpl(nullptr) {}
+
+  //===--------------------------------------------------------------------===//
+  // Attribute Construction
+  //===--------------------------------------------------------------------===//
+
+  /// \brief Return a uniquified Attribute object.
+  static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0);
+  static Attribute get(LLVMContext &Context, StringRef Kind,
+                       StringRef Val = StringRef());
+
+  /// \brief Return a uniquified Attribute object that has the specific
+  /// alignment set.
+  static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align);
+  static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align);
+  static Attribute getWithDereferenceableBytes(LLVMContext &Context,
+                                              uint64_t Bytes);
+  static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context,
+                                                     uint64_t Bytes);
+  static Attribute getWithAllocSizeArgs(LLVMContext &Context,
+                                        unsigned ElemSizeArg,
+                                        const Optional<unsigned> &NumElemsArg);
+
+  //===--------------------------------------------------------------------===//
+  // Attribute Accessors
+  //===--------------------------------------------------------------------===//
+
+  /// \brief Return true if the attribute is an Attribute::AttrKind type.
+  bool isEnumAttribute() const;
+
+  /// \brief Return true if the attribute is an integer attribute.
+  bool isIntAttribute() const;
+
+  /// \brief Return true if the attribute is a string (target-dependent)
+  /// attribute.
+  bool isStringAttribute() const;
+
+  /// \brief Return true if the attribute is present.
+  bool hasAttribute(AttrKind Val) const;
+
+  /// \brief Return true if the target-dependent attribute is present.
+  bool hasAttribute(StringRef Val) const;
+
+  /// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This
+  /// requires the attribute to be an enum or integer attribute.
+  Attribute::AttrKind getKindAsEnum() const;
+
+  /// \brief Return the attribute's value as an integer. This requires that the
+  /// attribute be an integer attribute.
+  uint64_t getValueAsInt() const;
+
+  /// \brief Return the attribute's kind as a string. This requires the
+  /// attribute to be a string attribute.
+  StringRef getKindAsString() const;
+
+  /// \brief Return the attribute's value as a string. This requires the
+  /// attribute to be a string attribute.
+  StringRef getValueAsString() const;
+
+  /// \brief Returns the alignment field of an attribute as a byte alignment
+  /// value.
+  unsigned getAlignment() const;
+
+  /// \brief Returns the stack alignment field of an attribute as a byte
+  /// alignment value.
+  unsigned getStackAlignment() const;
+
+  /// \brief Returns the number of dereferenceable bytes from the
+  /// dereferenceable attribute.
+  uint64_t getDereferenceableBytes() const;
+
+  /// \brief Returns the number of dereferenceable_or_null bytes from the
+  /// dereferenceable_or_null attribute.
+  uint64_t getDereferenceableOrNullBytes() const;
+
+  /// Returns the argument numbers for the allocsize attribute (or pair(0, 0)
+  /// if not known).
+  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+
+  /// \brief The Attribute is converted to a string of equivalent mnemonic. This
+  /// is, presumably, for writing out the mnemonics for the assembly writer.
+  std::string getAsString(bool InAttrGrp = false) const;
+
+  /// \brief Equality and non-equality operators.
+  bool operator==(Attribute A) const { return pImpl == A.pImpl; }
+  bool operator!=(Attribute A) const { return pImpl != A.pImpl; }
+
+  /// \brief Less-than operator. Useful for sorting the attributes list.
+  bool operator<(Attribute A) const;
+
+  void Profile(FoldingSetNodeID &ID) const {
+    ID.AddPointer(pImpl);
+  }
+
+  /// \brief Return a raw pointer that uniquely identifies this attribute.
+  void *getRawPointer() const {
+    return pImpl;
+  }
+
+  /// \brief Get an attribute from a raw pointer created by getRawPointer.
+  static Attribute fromRawPointer(void *RawPtr) {
+    return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr));
+  }
+};
+
+// Specialized opaque value conversions.
+inline LLVMAttributeRef wrap(Attribute Attr) {
+  return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
+}
+
+// Specialized opaque value conversions.
+inline Attribute unwrap(LLVMAttributeRef Attr) {
+  return Attribute::fromRawPointer(Attr);
+}
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief This class holds the attributes for a function, its return value, and
+/// its parameters. You access the attributes for each of them via an index into
+/// the AttributeSet object. The function attributes are at index
+/// `AttributeSet::FunctionIndex', the return value is at index
+/// `AttributeSet::ReturnIndex', and the attributes for the parameters start at
+/// index `1'.
+class AttributeSet {
+public:
+  enum AttrIndex : unsigned {
+    ReturnIndex = 0U,
+    FunctionIndex = ~0U
+  };
+
+private:
+  friend class AttrBuilder;
+  friend class AttributeSetImpl;
+  friend class AttributeSetNode;
+  template <typename Ty> friend struct DenseMapInfo;
+
+  /// \brief The attributes that we are managing. This can be null to represent
+  /// the empty attributes list.
+  AttributeSetImpl *pImpl;
+
+  /// \brief The attributes for the specified index are returned.
+  AttributeSetNode *getAttributes(unsigned Index) const;
+
+  /// \brief Create an AttributeSet with the specified parameters in it.
+  static AttributeSet get(LLVMContext &C,
+                          ArrayRef<std::pair<unsigned, Attribute> > Attrs);
+  static AttributeSet get(LLVMContext &C,
+                          ArrayRef<std::pair<unsigned,
+                                             AttributeSetNode*> > Attrs);
+
+  static AttributeSet getImpl(LLVMContext &C,
+                              ArrayRef<std::pair<unsigned,
+                                                 AttributeSetNode*> > Attrs);
+
+  explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {}
+
+public:
+  AttributeSet() : pImpl(nullptr) {}
+
+  //===--------------------------------------------------------------------===//
+  // AttributeSet Construction and Mutation
+  //===--------------------------------------------------------------------===//
+
+  /// \brief Return an AttributeSet with the specified parameters in it.
+  static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs);
+  static AttributeSet get(LLVMContext &C, unsigned Index,
+                          ArrayRef<Attribute::AttrKind> Kinds);
+  static AttributeSet get(LLVMContext &C, unsigned Index,
+                          ArrayRef<StringRef> Kind);
+  static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B);
+
+  /// \brief Add an attribute to the attribute set at the given index. Because
+  /// attribute sets are immutable, this returns a new set.
+  AttributeSet addAttribute(LLVMContext &C, unsigned Index,
+                            Attribute::AttrKind Kind) const;
+
+  /// \brief Add an attribute to the attribute set at the given index. Because
+  /// attribute sets are immutable, this returns a new set.
+  AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
+                            StringRef Value = StringRef()) const;
+
+  /// Add an attribute to the attribute set at the given indices. Because
+  /// attribute sets are immutable, this returns a new set.
+  AttributeSet addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
+                            Attribute A) const;
+
+  /// \brief Add attributes to the attribute set at the given index. Because
+  /// attribute sets are immutable, this returns a new set.
+  AttributeSet addAttributes(LLVMContext &C, unsigned Index,
+                             AttributeSet Attrs) const;
+
+  /// \brief Remove the specified attribute at the specified index from this
+  /// attribute list. Because attribute lists are immutable, this returns the
+  /// new list.
+  AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
+                               Attribute::AttrKind Kind) const;
+
+  /// \brief Remove the specified attribute at the specified index from this
+  /// attribute list. Because attribute lists are immutable, this returns the
+  /// new list.
+  AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
+                               StringRef Kind) const;
+
+  /// \brief Remove the specified attributes at the specified index from this
+  /// attribute list. Because attribute lists are immutable, this returns the
+  /// new list.
+  AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
+                                AttributeSet Attrs) const;
+
+  /// \brief Remove the specified attributes at the specified index from this
+  /// attribute list. Because attribute lists are immutable, this returns the
+  /// new list.
+  AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
+                                const AttrBuilder &Attrs) const;
+
+  /// \brief Add the dereferenceable attribute to the attribute set at the given
+  /// index. Because attribute sets are immutable, this returns a new set.
+  AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index,
+                                      uint64_t Bytes) const;
+
+  /// \brief Add the dereferenceable_or_null attribute to the attribute set at
+  /// the given index. Because attribute sets are immutable, this returns a new
+  /// set.
+  AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
+                                            uint64_t Bytes) const;
+
+  /// Add the allocsize attribute to the attribute set at the given index.
+  /// Because attribute sets are immutable, this returns a new set.
+  AttributeSet addAllocSizeAttr(LLVMContext &C, unsigned Index,
+                                unsigned ElemSizeArg,
+                                const Optional<unsigned> &NumElemsArg);
+
+  //===--------------------------------------------------------------------===//
+  // AttributeSet Accessors
+  //===--------------------------------------------------------------------===//
+
+  /// \brief Retrieve the LLVM context.
+  LLVMContext &getContext() const;
+
+  /// \brief The attributes for the specified index are returned.
+  AttributeSet getParamAttributes(unsigned Index) const;
+
+  /// \brief The attributes for the ret value are returned.
+  AttributeSet getRetAttributes() const;
+
+  /// \brief The function attributes are returned.
+  AttributeSet getFnAttributes() const;
+
+  /// \brief Return true if the attribute exists at the given index.
+  bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;
+
+  /// \brief Return true if the attribute exists at the given index.
+  bool hasAttribute(unsigned Index, StringRef Kind) const;
+
+  /// \brief Return true if attribute exists at the given index.
+  bool hasAttributes(unsigned Index) const;
+
+  /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+  /// may be faster.
+  bool hasFnAttribute(Attribute::AttrKind Kind) const;
+
+  /// \brief Return true if the specified attribute is set for at least one
+  /// parameter or for the return value. If Index is not nullptr, the index
+  /// of a parameter with the specified attribute is provided.
+  bool hasAttrSomewhere(Attribute::AttrKind Kind,
+                        unsigned *Index = nullptr) const;
+
+  /// \brief Return the attribute object that exists at the given index.
+  Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const;
+
+  /// \brief Return the attribute object that exists at the given index.
+  Attribute getAttribute(unsigned Index, StringRef Kind) const;
+
+  /// \brief Return the alignment for the specified function parameter.
+  unsigned getParamAlignment(unsigned Index) const;
+
+  /// \brief Get the stack alignment.
+  unsigned getStackAlignment(unsigned Index) const;
+
+  /// \brief Get the number of dereferenceable bytes (or zero if unknown).
+  uint64_t getDereferenceableBytes(unsigned Index) const;
+
+  /// \brief Get the number of dereferenceable_or_null bytes (or zero if
+  /// unknown).
+  uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
+
+  /// Get the allocsize argument numbers (or pair(0, 0) if unknown).
+  std::pair<unsigned, Optional<unsigned>>
+  getAllocSizeArgs(unsigned Index) const;
+
+  /// \brief Return the attributes at the index as a string.
+  std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
+
+  typedef ArrayRef<Attribute>::iterator iterator;
+
+  iterator begin(unsigned Slot) const;
+  iterator end(unsigned Slot) const;
+
+  /// operator==/!= - Provide equality predicates.
+  bool operator==(const AttributeSet &RHS) const {
+    return pImpl == RHS.pImpl;
+  }
+  bool operator!=(const AttributeSet &RHS) const {
+    return pImpl != RHS.pImpl;
+  }
+
+  //===--------------------------------------------------------------------===//
+  // AttributeSet Introspection
+  //===--------------------------------------------------------------------===//
+
+  // FIXME: Remove this.
+  uint64_t Raw(unsigned Index) const;
+
+  /// \brief Return a raw pointer that uniquely identifies this attribute list.
+  void *getRawPointer() const {
+    return pImpl;
+  }
+
+  /// \brief Return true if there are no attributes.
+  bool isEmpty() const {
+    return getNumSlots() == 0;
+  }
+
+  /// \brief Return the number of slots used in this attribute list.  This is
+  /// the number of arguments that have an attribute set on them (including the
+  /// function itself).
+  unsigned getNumSlots() const;
+
+  /// \brief Return the index for the given slot.
+  unsigned getSlotIndex(unsigned Slot) const;
+
+  /// \brief Return the attributes at the given slot.
+  AttributeSet getSlotAttributes(unsigned Slot) const;
+
+  void dump() const;
+};
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief Provide DenseMapInfo for AttributeSet.
+template<> struct DenseMapInfo<AttributeSet> {
+  static inline AttributeSet getEmptyKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
+    return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
+  }
+  static inline AttributeSet getTombstoneKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-2);
+    Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
+    return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
+  }
+  static unsigned getHashValue(AttributeSet AS) {
+    return (unsigned((uintptr_t)AS.pImpl) >> 4) ^
+           (unsigned((uintptr_t)AS.pImpl) >> 9);
+  }
+  static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
+};
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief This class is used in conjunction with the Attribute::get method to
+/// create an Attribute object. The object itself is uniquified. The Builder's
+/// value, however, is not. So this can be used as a quick way to test for
+/// equality, presence of attributes, etc.
+class AttrBuilder {
+  std::bitset<Attribute::EndAttrKinds> Attrs;
+  std::map<std::string, std::string> TargetDepAttrs;
+  uint64_t Alignment;
+  uint64_t StackAlignment;
+  uint64_t DerefBytes;
+  uint64_t DerefOrNullBytes;
+  uint64_t AllocSizeArgs;
+
+public:
+  AttrBuilder()
+      : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+        DerefOrNullBytes(0), AllocSizeArgs(0) {}
+  explicit AttrBuilder(uint64_t Val)
+      : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+        DerefOrNullBytes(0), AllocSizeArgs(0) {
+    addRawValue(Val);
+  }
+  AttrBuilder(const Attribute &A)
+      : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+        DerefOrNullBytes(0), AllocSizeArgs(0) {
+    addAttribute(A);
+  }
+  AttrBuilder(AttributeSet AS, unsigned Idx);
+
+  void clear();
+
+  /// \brief Add an attribute to the builder.
+  AttrBuilder &addAttribute(Attribute::AttrKind Val);
+
+  /// \brief Add the Attribute object to the builder.
+  AttrBuilder &addAttribute(Attribute A);
+
+  /// \brief Add the target-dependent attribute to the builder.
+  AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef());
+
+  /// \brief Remove an attribute from the builder.
+  AttrBuilder &removeAttribute(Attribute::AttrKind Val);
+
+  /// \brief Remove the attributes from the builder.
+  AttrBuilder &removeAttributes(AttributeSet A, uint64_t Index);
+
+  /// \brief Remove the target-dependent attribute to the builder.
+  AttrBuilder &removeAttribute(StringRef A);
+
+  /// \brief Add the attributes from the builder.
+  AttrBuilder &merge(const AttrBuilder &B);
+
+  /// \brief Remove the attributes from the builder.
+  AttrBuilder &remove(const AttrBuilder &B);
+
+  /// \brief Return true if the builder has any attribute that's in the
+  /// specified builder.
+  bool overlaps(const AttrBuilder &B) const;
+
+  /// \brief Return true if the builder has the specified attribute.
+  bool contains(Attribute::AttrKind A) const {
+    assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
+    return Attrs[A];
+  }
+
+  /// \brief Return true if the builder has the specified target-dependent
+  /// attribute.
+  bool contains(StringRef A) const;
+
+  /// \brief Return true if the builder has IR-level attributes.
+  bool hasAttributes() const;
+
+  /// \brief Return true if the builder has any attribute that's in the
+  /// specified attribute.
+  bool hasAttributes(AttributeSet A, uint64_t Index) const;
+
+  /// \brief Return true if the builder has an alignment attribute.
+  bool hasAlignmentAttr() const;
+
+  /// \brief Retrieve the alignment attribute, if it exists.
+  uint64_t getAlignment() const { return Alignment; }
+
+  /// \brief Retrieve the stack alignment attribute, if it exists.
+  uint64_t getStackAlignment() const { return StackAlignment; }
+
+  /// \brief Retrieve the number of dereferenceable bytes, if the
+  /// dereferenceable attribute exists (zero is returned otherwise).
+  uint64_t getDereferenceableBytes() const { return DerefBytes; }
+
+  /// \brief Retrieve the number of dereferenceable_or_null bytes, if the
+  /// dereferenceable_or_null attribute exists (zero is returned otherwise).
+  uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
+
+  /// Retrieve the allocsize args, if the allocsize attribute exists.  If it
+  /// doesn't exist, pair(0, 0) is returned.
+  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+
+  /// \brief This turns an int alignment (which must be a power of 2) into the
+  /// form used internally in Attribute.
+  AttrBuilder &addAlignmentAttr(unsigned Align);
+
+  /// \brief This turns an int stack alignment (which must be a power of 2) into
+  /// the form used internally in Attribute.
+  AttrBuilder &addStackAlignmentAttr(unsigned Align);
+
+  /// \brief This turns the number of dereferenceable bytes into the form used
+  /// internally in Attribute.
+  AttrBuilder &addDereferenceableAttr(uint64_t Bytes);
+
+  /// \brief This turns the number of dereferenceable_or_null bytes into the
+  /// form used internally in Attribute.
+  AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
+
+  /// This turns one (or two) ints into the form used internally in Attribute.
+  AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg,
+                                const Optional<unsigned> &NumElemsArg);
+
+  /// Add an allocsize attribute, using the representation returned by
+  /// Attribute.getIntValue().
+  AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);
+
+  /// \brief Return true if the builder contains no target-independent
+  /// attributes.
+  bool empty() const { return Attrs.none(); }
+
+  // Iterators for target-dependent attributes.
+  typedef std::pair<std::string, std::string>                td_type;
+  typedef std::map<std::string, std::string>::iterator       td_iterator;
+  typedef std::map<std::string, std::string>::const_iterator td_const_iterator;
+  typedef llvm::iterator_range<td_iterator>                  td_range;
+  typedef llvm::iterator_range<td_const_iterator>            td_const_range;
+
+  td_iterator td_begin()             { return TargetDepAttrs.begin(); }
+  td_iterator td_end()               { return TargetDepAttrs.end(); }
+
+  td_const_iterator td_begin() const { return TargetDepAttrs.begin(); }
+  td_const_iterator td_end() const   { return TargetDepAttrs.end(); }
+
+  td_range td_attrs() { return td_range(td_begin(), td_end()); }
+  td_const_range td_attrs() const {
+    return td_const_range(td_begin(), td_end());
+  }
+
+  bool td_empty() const              { return TargetDepAttrs.empty(); }
+
+  bool operator==(const AttrBuilder &B);
+  bool operator!=(const AttrBuilder &B) {
+    return !(*this == B);
+  }
+
+  // FIXME: Remove this in 4.0.
+
+  /// \brief Add the raw value to the internal representation.
+  AttrBuilder &addRawValue(uint64_t Val);
+};
+
+namespace AttributeFuncs {
+
+/// \brief Which attributes cannot be applied to a type.
+AttrBuilder typeIncompatible(Type *Ty);
+
+/// \returns Return true if the two functions have compatible target-independent
+/// attributes for inlining purposes.
+bool areInlineCompatible(const Function &Caller, const Function &Callee);
+
+/// \brief Merge caller's and callee's attributes.
+void mergeAttributesForInlining(Function &Caller, const Function &Callee);
+
+} // end AttributeFuncs namespace
+
+} // end llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Attributes.inc b/third_party/llvm-subzero/include/llvm/IR/Attributes.inc
new file mode 100644
index 0000000..57cc506
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Attributes.inc
@@ -0,0 +1,458 @@
+#ifdef GET_ATTR_ENUM

+#undef GET_ATTR_ENUM

+Alignment,

+AllocSize,

+AlwaysInline,

+ArgMemOnly,

+Builtin,

+ByVal,

+Cold,

+Convergent,

+Dereferenceable,

+DereferenceableOrNull,

+InAlloca,

+InReg,

+InaccessibleMemOnly,

+InaccessibleMemOrArgMemOnly,

+InlineHint,

+JumpTable,

+MinSize,

+Naked,

+Nest,

+NoAlias,

+NoBuiltin,

+NoCapture,

+NoDuplicate,

+NoImplicitFloat,

+NoInline,

+NoRecurse,

+NoRedZone,

+NoReturn,

+NoUnwind,

+NonLazyBind,

+NonNull,

+OptimizeForSize,

+OptimizeNone,

+ReadNone,

+ReadOnly,

+Returned,

+ReturnsTwice,

+SExt,

+SafeStack,

+SanitizeAddress,

+SanitizeMemory,

+SanitizeThread,

+StackAlignment,

+StackProtect,

+StackProtectReq,

+StackProtectStrong,

+StructRet,

+SwiftError,

+SwiftSelf,

+UWTable,

+WriteOnly,

+ZExt,

+#endif

+#ifdef GET_ATTR_KIND_FROM_NAME

+#undef GET_ATTR_KIND_FROM_NAME

+static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {

+  return StringSwitch<Attribute::AttrKind>(AttrName)

+    .Case("align", Attribute::Alignment)

+    .Case("allocsize", Attribute::AllocSize)

+    .Case("alwaysinline", Attribute::AlwaysInline)

+    .Case("argmemonly", Attribute::ArgMemOnly)

+    .Case("builtin", Attribute::Builtin)

+    .Case("byval", Attribute::ByVal)

+    .Case("cold", Attribute::Cold)

+    .Case("convergent", Attribute::Convergent)

+    .Case("dereferenceable", Attribute::Dereferenceable)

+    .Case("dereferenceable_or_null", Attribute::DereferenceableOrNull)

+    .Case("inalloca", Attribute::InAlloca)

+    .Case("inreg", Attribute::InReg)

+    .Case("inaccessiblememonly", Attribute::InaccessibleMemOnly)

+    .Case("inaccessiblemem_or_argmemonly", Attribute::InaccessibleMemOrArgMemOnly)

+    .Case("inlinehint", Attribute::InlineHint)

+    .Case("jumptable", Attribute::JumpTable)

+    .Case("minsize", Attribute::MinSize)

+    .Case("naked", Attribute::Naked)

+    .Case("nest", Attribute::Nest)

+    .Case("noalias", Attribute::NoAlias)

+    .Case("nobuiltin", Attribute::NoBuiltin)

+    .Case("nocapture", Attribute::NoCapture)

+    .Case("noduplicate", Attribute::NoDuplicate)

+    .Case("noimplicitfloat", Attribute::NoImplicitFloat)

+    .Case("noinline", Attribute::NoInline)

+    .Case("norecurse", Attribute::NoRecurse)

+    .Case("noredzone", Attribute::NoRedZone)

+    .Case("noreturn", Attribute::NoReturn)

+    .Case("nounwind", Attribute::NoUnwind)

+    .Case("nonlazybind", Attribute::NonLazyBind)

+    .Case("nonnull", Attribute::NonNull)

+    .Case("optsize", Attribute::OptimizeForSize)

+    .Case("optnone", Attribute::OptimizeNone)

+    .Case("readnone", Attribute::ReadNone)

+    .Case("readonly", Attribute::ReadOnly)

+    .Case("returned", Attribute::Returned)

+    .Case("returns_twice", Attribute::ReturnsTwice)

+    .Case("signext", Attribute::SExt)

+    .Case("safestack", Attribute::SafeStack)

+    .Case("sanitize_address", Attribute::SanitizeAddress)

+    .Case("sanitize_memory", Attribute::SanitizeMemory)

+    .Case("sanitize_thread", Attribute::SanitizeThread)

+    .Case("alignstack", Attribute::StackAlignment)

+    .Case("ssp", Attribute::StackProtect)

+    .Case("sspreq", Attribute::StackProtectReq)

+    .Case("sspstrong", Attribute::StackProtectStrong)

+    .Case("sret", Attribute::StructRet)

+    .Case("swifterror", Attribute::SwiftError)

+    .Case("swiftself", Attribute::SwiftSelf)

+    .Case("uwtable", Attribute::UWTable)

+    .Case("writeonly", Attribute::WriteOnly)

+    .Case("zeroext", Attribute::ZExt)

+    .Default(Attribute::None);

+}

+

+#endif

+#ifdef GET_ATTR_COMPAT_FUNC

+#undef GET_ATTR_COMPAT_FUNC

+struct EnumAttr {

+  static bool isSet(const Function &Fn,

+                    Attribute::AttrKind Kind) {

+    return Fn.hasFnAttribute(Kind);

+  }

+

+  static void set(Function &Fn,

+                  Attribute::AttrKind Kind, bool Val) {

+    if (Val)

+      Fn.addFnAttr(Kind);

+    else

+      Fn.removeFnAttr(Kind);

+  }

+};

+

+struct StrBoolAttr {

+  static bool isSet(const Function &Fn,

+                    StringRef Kind) {

+    auto A = Fn.getFnAttribute(Kind);

+    return A.getValueAsString().equals("true");

+  }

+

+  static void set(Function &Fn,

+                  StringRef Kind, bool Val) {

+    Fn.addFnAttr(Kind, Val ? "true" : "false");

+  }

+};

+

+// EnumAttr classes

+struct AlignmentAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Alignment;

+  }

+};

+struct AllocSizeAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::AllocSize;

+  }

+};

+struct AlwaysInlineAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::AlwaysInline;

+  }

+};

+struct ArgMemOnlyAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::ArgMemOnly;

+  }

+};

+struct BuiltinAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Builtin;

+  }

+};

+struct ByValAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::ByVal;

+  }

+};

+struct ColdAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Cold;

+  }

+};

+struct ConvergentAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Convergent;

+  }

+};

+struct DereferenceableAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Dereferenceable;

+  }

+};

+struct DereferenceableOrNullAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::DereferenceableOrNull;

+  }

+};

+struct InAllocaAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::InAlloca;

+  }

+};

+struct InRegAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::InReg;

+  }

+};

+struct InaccessibleMemOnlyAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::InaccessibleMemOnly;

+  }

+};

+struct InaccessibleMemOrArgMemOnlyAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::InaccessibleMemOrArgMemOnly;

+  }

+};

+struct InlineHintAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::InlineHint;

+  }

+};

+struct JumpTableAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::JumpTable;

+  }

+};

+struct MinSizeAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::MinSize;

+  }

+};

+struct NakedAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Naked;

+  }

+};

+struct NestAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Nest;

+  }

+};

+struct NoAliasAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoAlias;

+  }

+};

+struct NoBuiltinAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoBuiltin;

+  }

+};

+struct NoCaptureAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoCapture;

+  }

+};

+struct NoDuplicateAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoDuplicate;

+  }

+};

+struct NoImplicitFloatAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoImplicitFloat;

+  }

+};

+struct NoInlineAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoInline;

+  }

+};

+struct NoRecurseAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoRecurse;

+  }

+};

+struct NoRedZoneAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoRedZone;

+  }

+};

+struct NoReturnAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoReturn;

+  }

+};

+struct NoUnwindAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NoUnwind;

+  }

+};

+struct NonLazyBindAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NonLazyBind;

+  }

+};

+struct NonNullAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::NonNull;

+  }

+};

+struct OptimizeForSizeAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::OptimizeForSize;

+  }

+};

+struct OptimizeNoneAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::OptimizeNone;

+  }

+};

+struct ReadNoneAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::ReadNone;

+  }

+};

+struct ReadOnlyAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::ReadOnly;

+  }

+};

+struct ReturnedAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::Returned;

+  }

+};

+struct ReturnsTwiceAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::ReturnsTwice;

+  }

+};

+struct SExtAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SExt;

+  }

+};

+struct SafeStackAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SafeStack;

+  }

+};

+struct SanitizeAddressAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SanitizeAddress;

+  }

+};

+struct SanitizeMemoryAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SanitizeMemory;

+  }

+};

+struct SanitizeThreadAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SanitizeThread;

+  }

+};

+struct StackAlignmentAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::StackAlignment;

+  }

+};

+struct StackProtectAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::StackProtect;

+  }

+};

+struct StackProtectReqAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::StackProtectReq;

+  }

+};

+struct StackProtectStrongAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::StackProtectStrong;

+  }

+};

+struct StructRetAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::StructRet;

+  }

+};

+struct SwiftErrorAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SwiftError;

+  }

+};

+struct SwiftSelfAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::SwiftSelf;

+  }

+};

+struct UWTableAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::UWTable;

+  }

+};

+struct WriteOnlyAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::WriteOnly;

+  }

+};

+struct ZExtAttr : EnumAttr {

+  static enum Attribute::AttrKind getKind() {

+    return llvm::Attribute::ZExt;

+  }

+};

+

+// StrBoolAttr classes

+struct LessPreciseFPMADAttr : StrBoolAttr {

+  static const char *getKind() {

+    return "less-precise-fpmad";

+  }

+};

+struct NoInfsFPMathAttr : StrBoolAttr {

+  static const char *getKind() {

+    return "no-infs-fp-math";

+  }

+};

+struct NoJumpTablesAttr : StrBoolAttr {

+  static const char *getKind() {

+    return "no-jump-tables";

+  }

+};

+struct NoNansFPMathAttr : StrBoolAttr {

+  static const char *getKind() {

+    return "no-nans-fp-math";

+  }

+};

+struct UnsafeFPMathAttr : StrBoolAttr {

+  static const char *getKind() {

+    return "unsafe-fp-math";

+  }

+};

+

+static inline bool hasCompatibleFnAttrs(const Function &Caller,

+                                        const Function &Callee) {

+  bool Ret = true;

+

+  Ret &= isEqual<SanitizeAddressAttr>(Caller, Callee);

+  Ret &= isEqual<SanitizeThreadAttr>(Caller, Callee);

+  Ret &= isEqual<SanitizeMemoryAttr>(Caller, Callee);

+  Ret &= isEqual<SafeStackAttr>(Caller, Callee);

+

+  return Ret;

+}

+

+static inline void mergeFnAttrs(Function &Caller,

+                                const Function &Callee) {

+  adjustCallerSSPLevel(Caller, Callee);

+  setAND<LessPreciseFPMADAttr>(Caller, Callee);

+  setAND<NoInfsFPMathAttr>(Caller, Callee);

+  setAND<NoNansFPMathAttr>(Caller, Callee);

+  setAND<UnsafeFPMathAttr>(Caller, Callee);

+  setOR<NoImplicitFloatAttr>(Caller, Callee);

+  setOR<NoJumpTablesAttr>(Caller, Callee);

+}

+

+#endif

diff --git a/third_party/llvm-subzero/include/llvm/IR/BasicBlock.h b/third_party/llvm-subzero/include/llvm/IR/BasicBlock.h
new file mode 100644
index 0000000..50eedec
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/BasicBlock.h
@@ -0,0 +1,345 @@
+//===-- llvm/BasicBlock.h - Represent a basic block in the VM ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the BasicBlock class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_BASICBLOCK_H
+#define LLVM_IR_BASICBLOCK_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/SymbolTableListTraits.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class CallInst;
+class LandingPadInst;
+class TerminatorInst;
+class LLVMContext;
+class BlockAddress;
+class Function;
+
+/// \brief LLVM Basic Block Representation
+///
+/// This represents a single basic block in LLVM. A basic block is simply a
+/// container of instructions that execute sequentially. Basic blocks are Values
+/// because they are referenced by instructions such as branches and switch
+/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block
+/// represents a label to which a branch can jump.
+///
+/// A well formed basic block is formed of a list of non-terminating
+/// instructions followed by a single TerminatorInst instruction.
+/// TerminatorInst's may not occur in the middle of basic blocks, and must
+/// terminate the blocks. The BasicBlock class allows malformed basic blocks to
+/// occur because it may be useful in the intermediate stage of constructing or
+/// modifying a program. However, the verifier will ensure that basic blocks
+/// are "well formed".
+class BasicBlock : public Value, // Basic blocks are data objects also
+                   public ilist_node_with_parent<BasicBlock, Function> {
+  friend class BlockAddress;
+public:
+  typedef SymbolTableList<Instruction> InstListType;
+
+private:
+  InstListType InstList;
+  Function *Parent;
+
+  void setParent(Function *parent);
+  friend class SymbolTableListTraits<BasicBlock>;
+
+  BasicBlock(const BasicBlock &) = delete;
+  void operator=(const BasicBlock &) = delete;
+
+  /// \brief Constructor.
+  ///
+  /// If the function parameter is specified, the basic block is automatically
+  /// inserted at either the end of the function (if InsertBefore is null), or
+  /// before the specified basic block.
+  explicit BasicBlock(LLVMContext &C, const Twine &Name = "",
+                      Function *Parent = nullptr,
+                      BasicBlock *InsertBefore = nullptr);
+public:
+  /// \brief Get the context in which this basic block lives.
+  LLVMContext &getContext() const;
+
+  /// Instruction iterators...
+  typedef InstListType::iterator iterator;
+  typedef InstListType::const_iterator const_iterator;
+  typedef InstListType::reverse_iterator reverse_iterator;
+  typedef InstListType::const_reverse_iterator const_reverse_iterator;
+
+  /// \brief Creates a new BasicBlock.
+  ///
+  /// If the Parent parameter is specified, the basic block is automatically
+  /// inserted at either the end of the function (if InsertBefore is 0), or
+  /// before the specified basic block.
+  static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "",
+                            Function *Parent = nullptr,
+                            BasicBlock *InsertBefore = nullptr) {
+    return new BasicBlock(Context, Name, Parent, InsertBefore);
+  }
+  ~BasicBlock() override;
+
+  /// \brief Return the enclosing method, or null if none.
+  const Function *getParent() const { return Parent; }
+        Function *getParent()       { return Parent; }
+
+  /// \brief Return the module owning the function this basic block belongs to,
+  /// or nullptr it the function does not have a module.
+  ///
+  /// Note: this is undefined behavior if the block does not have a parent.
+  const Module *getModule() const;
+  Module *getModule();
+
+  /// \brief Returns the terminator instruction if the block is well formed or
+  /// null if the block is not well formed.
+  TerminatorInst *getTerminator();
+  const TerminatorInst *getTerminator() const;
+
+  /// \brief Returns the call instruction calling @llvm.experimental.deoptimize
+  /// prior to the terminating return instruction of this basic block, if such a
+  /// call is present.  Otherwise, returns null.
+  CallInst *getTerminatingDeoptimizeCall();
+  const CallInst *getTerminatingDeoptimizeCall() const {
+    return const_cast<BasicBlock *>(this)->getTerminatingDeoptimizeCall();
+  }
+
+  /// \brief Returns the call instruction marked 'musttail' prior to the
+  /// terminating return instruction of this basic block, if such a call is
+  /// present.  Otherwise, returns null.
+  CallInst *getTerminatingMustTailCall();
+  const CallInst *getTerminatingMustTailCall() const {
+    return const_cast<BasicBlock *>(this)->getTerminatingMustTailCall();
+  }
+
+  /// \brief Returns a pointer to the first instruction in this block that is
+  /// not a PHINode instruction.
+  ///
+  /// When adding instructions to the beginning of the basic block, they should
+  /// be added before the returned value, not before the first instruction,
+  /// which might be PHI. Returns 0 is there's no non-PHI instruction.
+  Instruction* getFirstNonPHI();
+  const Instruction* getFirstNonPHI() const {
+    return const_cast<BasicBlock*>(this)->getFirstNonPHI();
+  }
+
+  /// \brief Returns a pointer to the first instruction in this block that is not
+  /// a PHINode or a debug intrinsic.
+  Instruction* getFirstNonPHIOrDbg();
+  const Instruction* getFirstNonPHIOrDbg() const {
+    return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg();
+  }
+
+  /// \brief Returns a pointer to the first instruction in this block that is not
+  /// a PHINode, a debug intrinsic, or a lifetime intrinsic.
+  Instruction* getFirstNonPHIOrDbgOrLifetime();
+  const Instruction* getFirstNonPHIOrDbgOrLifetime() const {
+    return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime();
+  }
+
+  /// \brief Returns an iterator to the first instruction in this block that is
+  /// suitable for inserting a non-PHI instruction.
+  ///
+  /// In particular, it skips all PHIs and LandingPad instructions.
+  iterator getFirstInsertionPt();
+  const_iterator getFirstInsertionPt() const {
+    return const_cast<BasicBlock*>(this)->getFirstInsertionPt();
+  }
+
+  /// \brief Unlink 'this' from the containing function, but do not delete it.
+  void removeFromParent();
+
+  /// \brief Unlink 'this' from the containing function and delete it.
+  ///
+  // \returns an iterator pointing to the element after the erased one.
+  SymbolTableList<BasicBlock>::iterator eraseFromParent();
+
+  /// \brief Unlink this basic block from its current function and insert it
+  /// into the function that \p MovePos lives in, right before \p MovePos.
+  void moveBefore(BasicBlock *MovePos);
+
+  /// \brief Unlink this basic block from its current function and insert it
+  /// right after \p MovePos in the function \p MovePos lives in.
+  void moveAfter(BasicBlock *MovePos);
+
+  /// \brief Insert unlinked basic block into a function.
+  ///
+  /// Inserts an unlinked basic block into \c Parent.  If \c InsertBefore is
+  /// provided, inserts before that basic block, otherwise inserts at the end.
+  ///
+  /// \pre \a getParent() is \c nullptr.
+  void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr);
+
+  /// \brief Return the predecessor of this block if it has a single predecessor
+  /// block. Otherwise return a null pointer.
+  BasicBlock *getSinglePredecessor();
+  const BasicBlock *getSinglePredecessor() const {
+    return const_cast<BasicBlock*>(this)->getSinglePredecessor();
+  }
+
+  /// \brief Return the predecessor of this block if it has a unique predecessor
+  /// block. Otherwise return a null pointer.
+  ///
+  /// Note that unique predecessor doesn't mean single edge, there can be
+  /// multiple edges from the unique predecessor to this block (for example a
+  /// switch statement with multiple cases having the same destination).
+  BasicBlock *getUniquePredecessor();
+  const BasicBlock *getUniquePredecessor() const {
+    return const_cast<BasicBlock*>(this)->getUniquePredecessor();
+  }
+
+  /// \brief Return the successor of this block if it has a single successor.
+  /// Otherwise return a null pointer.
+  ///
+  /// This method is analogous to getSinglePredecessor above.
+  BasicBlock *getSingleSuccessor();
+  const BasicBlock *getSingleSuccessor() const {
+    return const_cast<BasicBlock*>(this)->getSingleSuccessor();
+  }
+
+  /// \brief Return the successor of this block if it has a unique successor.
+  /// Otherwise return a null pointer.
+  ///
+  /// This method is analogous to getUniquePredecessor above.
+  BasicBlock *getUniqueSuccessor();
+  const BasicBlock *getUniqueSuccessor() const {
+    return const_cast<BasicBlock*>(this)->getUniqueSuccessor();
+  }
+
+  //===--------------------------------------------------------------------===//
+  /// Instruction iterator methods
+  ///
+  inline iterator                begin()       { return InstList.begin(); }
+  inline const_iterator          begin() const { return InstList.begin(); }
+  inline iterator                end  ()       { return InstList.end();   }
+  inline const_iterator          end  () const { return InstList.end();   }
+
+  inline reverse_iterator        rbegin()       { return InstList.rbegin(); }
+  inline const_reverse_iterator  rbegin() const { return InstList.rbegin(); }
+  inline reverse_iterator        rend  ()       { return InstList.rend();   }
+  inline const_reverse_iterator  rend  () const { return InstList.rend();   }
+
+  inline size_t                   size() const { return InstList.size();  }
+  inline bool                    empty() const { return InstList.empty(); }
+  inline const Instruction      &front() const { return InstList.front(); }
+  inline       Instruction      &front()       { return InstList.front(); }
+  inline const Instruction       &back() const { return InstList.back();  }
+  inline       Instruction       &back()       { return InstList.back();  }
+
+  /// \brief Return the underlying instruction list container.
+  ///
+  /// Currently you need to access the underlying instruction list container
+  /// directly if you want to modify it.
+  const InstListType &getInstList() const { return InstList; }
+        InstListType &getInstList()       { return InstList; }
+
+  /// \brief Returns a pointer to a member of the instruction list.
+  static InstListType BasicBlock::*getSublistAccess(Instruction*) {
+    return &BasicBlock::InstList;
+  }
+
+  /// \brief Returns a pointer to the symbol table if one exists.
+  ValueSymbolTable *getValueSymbolTable();
+
+  /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Value *V) {
+    return V->getValueID() == Value::BasicBlockVal;
+  }
+
+  /// \brief Cause all subinstructions to "let go" of all the references that
+  /// said subinstructions are maintaining.
+  ///
+  /// This allows one to 'delete' a whole class at a time, even though there may
+  /// be circular references... first all references are dropped, and all use
+  /// counts go to zero.  Then everything is delete'd for real.  Note that no
+  /// operations are valid on an object that has "dropped all references",
+  /// except operator delete.
+  void dropAllReferences();
+
+  /// \brief Notify the BasicBlock that the predecessor \p Pred is no longer
+  /// able to reach it.
+  ///
+  /// This is actually not used to update the Predecessor list, but is actually
+  /// used to update the PHI nodes that reside in the block.  Note that this
+  /// should be called while the predecessor still refers to this block.
+  void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false);
+
+  bool canSplitPredecessors() const;
+
+  /// \brief Split the basic block into two basic blocks at the specified
+  /// instruction.
+  ///
+  /// Note that all instructions BEFORE the specified iterator stay as part of
+  /// the original basic block, an unconditional branch is added to the original
+  /// BB, and the rest of the instructions in the BB are moved to the new BB,
+  /// including the old terminator.  The newly formed BasicBlock is returned.
+  /// This function invalidates the specified iterator.
+  ///
+  /// Note that this only works on well formed basic blocks (must have a
+  /// terminator), and 'I' must not be the end of instruction list (which would
+  /// cause a degenerate basic block to be formed, having a terminator inside of
+  /// the basic block).
+  ///
+  /// Also note that this doesn't preserve any passes. To split blocks while
+  /// keeping loop information consistent, use the SplitBlock utility function.
+  BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = "");
+  BasicBlock *splitBasicBlock(Instruction *I, const Twine &BBName = "") {
+    return splitBasicBlock(I->getIterator(), BBName);
+  }
+
+  /// \brief Returns true if there are any uses of this basic block other than
+  /// direct branches, switches, etc. to it.
+  bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; }
+
+  /// \brief Update all phi nodes in this basic block's successors to refer to
+  /// basic block \p New instead of to it.
+  void replaceSuccessorsPhiUsesWith(BasicBlock *New);
+
+  /// \brief Return true if this basic block is an exception handling block.
+  bool isEHPad() const { return getFirstNonPHI()->isEHPad(); }
+
+  /// \brief Return true if this basic block is a landing pad.
+  ///
+  /// Being a ``landing pad'' means that the basic block is the destination of
+  /// the 'unwind' edge of an invoke instruction.
+  bool isLandingPad() const;
+
+  /// \brief Return the landingpad instruction associated with the landing pad.
+  LandingPadInst *getLandingPadInst();
+  const LandingPadInst *getLandingPadInst() const;
+
+private:
+  /// \brief Increment the internal refcount of the number of BlockAddresses
+  /// referencing this BasicBlock by \p Amt.
+  ///
+  /// This is almost always 0, sometimes one possibly, but almost never 2, and
+  /// inconceivably 3 or more.
+  void AdjustBlockAddressRefCount(int Amt) {
+    setValueSubclassData(getSubclassDataFromValue()+Amt);
+    assert((int)(signed char)getSubclassDataFromValue() >= 0 &&
+           "Refcount wrap-around");
+  }
+  /// \brief Shadow Value::setValueSubclassData with a private forwarding method
+  /// so that any future subclasses cannot accidentally use it.
+  void setValueSubclassData(unsigned short D) {
+    Value::setValueSubclassData(D);
+  }
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef)
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/CallingConv.h b/third_party/llvm-subzero/include/llvm/IR/CallingConv.h
new file mode 100644
index 0000000..4987b7e
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/CallingConv.h
@@ -0,0 +1,203 @@
+//===-- llvm/CallingConv.h - LLVM Calling Conventions -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines LLVM's set of calling conventions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_CALLINGCONV_H
+#define LLVM_IR_CALLINGCONV_H
+
+namespace llvm {
+
+/// CallingConv Namespace - This namespace contains an enum with a value for
+/// the well-known calling conventions.
+///
+namespace CallingConv {
+  /// LLVM IR allows to use arbitrary numbers as calling convention identifiers.
+  typedef unsigned ID;
+
+  /// A set of enums which specify the assigned numeric values for known llvm
+  /// calling conventions.
+  /// @brief LLVM Calling Convention Representation
+  enum {
+    /// C - The default llvm calling convention, compatible with C.  This
+    /// convention is the only calling convention that supports varargs calls.
+    /// As with typical C calling conventions, the callee/caller have to
+    /// tolerate certain amounts of prototype mismatch.
+    C = 0,
+
+    // Generic LLVM calling conventions.  None of these calling conventions
+    // support varargs calls, and all assume that the caller and callee
+    // prototype exactly match.
+
+    /// Fast - This calling convention attempts to make calls as fast as
+    /// possible (e.g. by passing things in registers).
+    Fast = 8,
+
+    // Cold - This calling convention attempts to make code in the caller as
+    // efficient as possible under the assumption that the call is not commonly
+    // executed.  As such, these calls often preserve all registers so that the
+    // call does not break any live ranges in the caller side.
+    Cold = 9,
+
+    // GHC - Calling convention used by the Glasgow Haskell Compiler (GHC).
+    GHC = 10,
+
+    // HiPE - Calling convention used by the High-Performance Erlang Compiler
+    // (HiPE).
+    HiPE = 11,
+
+    // WebKit JS - Calling convention for stack based JavaScript calls
+    WebKit_JS = 12,
+
+    // AnyReg - Calling convention for dynamic register based calls (e.g.
+    // stackmap and patchpoint intrinsics).
+    AnyReg = 13,
+
+    // PreserveMost - Calling convention for runtime calls that preserves most
+    // registers.
+    PreserveMost = 14,
+
+    // PreserveAll - Calling convention for runtime calls that preserves
+    // (almost) all registers.
+    PreserveAll = 15,
+
+    // Swift - Calling convention for Swift.
+    Swift = 16,
+
+    // CXX_FAST_TLS - Calling convention for access functions.
+    CXX_FAST_TLS = 17,
+
+    // Target - This is the start of the target-specific calling conventions,
+    // e.g. fastcall and thiscall on X86.
+    FirstTargetCC = 64,
+
+    /// X86_StdCall - stdcall is the calling conventions mostly used by the
+    /// Win32 API. It is basically the same as the C convention with the
+    /// difference in that the callee is responsible for popping the arguments
+    /// from the stack.
+    X86_StdCall = 64,
+
+    /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments
+    /// in ECX:EDX registers, others - via stack. Callee is responsible for
+    /// stack cleaning.
+    X86_FastCall = 65,
+
+    /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete,
+    /// but still used on some targets).
+    ARM_APCS = 66,
+
+    /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling
+    /// convention (aka EABI). Soft float variant.
+    ARM_AAPCS = 67,
+
+    /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI.
+    ARM_AAPCS_VFP = 68,
+
+    /// MSP430_INTR - Calling convention used for MSP430 interrupt routines.
+    MSP430_INTR = 69,
+
+    /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX,
+    /// others via stack. Callee is responsible for stack cleaning. MSVC uses
+    /// this by default for methods in its ABI.
+    X86_ThisCall = 70,
+
+    /// PTX_Kernel - Call to a PTX kernel.
+    /// Passes all arguments in parameter space.
+    PTX_Kernel = 71,
+
+    /// PTX_Device - Call to a PTX device function.
+    /// Passes all arguments in register or parameter space.
+    PTX_Device = 72,
+
+    /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions.
+    /// No lowering or expansion of arguments.
+    /// Structures are passed as a pointer to a struct with the byval attribute.
+    /// Functions can only call SPIR_FUNC and SPIR_KERNEL functions.
+    /// Functions can only have zero or one return values.
+    /// Variable arguments are not allowed, except for printf.
+    /// How arguments/return values are lowered are not specified.
+    /// Functions are only visible to the devices.
+    SPIR_FUNC = 75,
+
+    /// SPIR_KERNEL - Calling convention for SPIR kernel functions.
+    /// Inherits the restrictions of SPIR_FUNC, except
+    /// Cannot have non-void return values.
+    /// Cannot have variable arguments.
+    /// Can also be called by the host.
+    /// Is externally visible.
+    SPIR_KERNEL = 76,
+
+    /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins
+    Intel_OCL_BI = 77,
+
+    /// \brief The C convention as specified in the x86-64 supplement to the
+    /// System V ABI, used on most non-Windows systems.
+    X86_64_SysV = 78,
+
+    /// \brief The C convention as implemented on Windows/x86-64. This
+    /// convention differs from the more common \c X86_64_SysV convention
+    /// in a number of ways, most notably in that XMM registers used to pass
+    /// arguments are shadowed by GPRs, and vice versa.
+    X86_64_Win64 = 79,
+
+    /// \brief MSVC calling convention that passes vectors and vector aggregates
+    /// in SSE registers.
+    X86_VectorCall = 80,
+
+    /// \brief Calling convention used by HipHop Virtual Machine (HHVM) to
+    /// perform calls to and from translation cache, and for calling PHP
+    /// functions.
+    /// HHVM calling convention supports tail/sibling call elimination.
+    HHVM = 81,
+
+    /// \brief HHVM calling convention for invoking C/C++ helpers.
+    HHVM_C = 82,
+
+    /// X86_INTR - x86 hardware interrupt context. Callee may take one or two
+    /// parameters, where the 1st represents a pointer to hardware context frame
+    /// and the 2nd represents hardware error code, the presence of the later
+    /// depends on the interrupt vector taken. Valid for both 32- and 64-bit
+    /// subtargets.
+    X86_INTR = 83,
+
+    /// Used for AVR interrupt routines.
+    AVR_INTR = 84,
+
+    /// Calling convention used for AVR signal routines.
+    AVR_SIGNAL = 85,
+
+    /// Calling convention used for special AVR rtlib functions
+    /// which have an "optimized" convention to preserve registers.
+    AVR_BUILTIN = 86,
+
+    /// Calling convention used for Mesa vertex shaders.
+    AMDGPU_VS = 87,
+
+    /// Calling convention used for Mesa geometry shaders.
+    AMDGPU_GS = 88,
+
+    /// Calling convention used for Mesa pixel shaders.
+    AMDGPU_PS = 89,
+
+    /// Calling convention used for Mesa compute shaders.
+    AMDGPU_CS = 90,
+
+    /// Calling convention for AMDGPU code object kernels.
+    AMDGPU_KERNEL = 91,
+
+    /// The highest possible calling convention ID. Must be some 2^k - 1.
+    MaxID = 1023
+  };
+} // End CallingConv namespace
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Constant.h b/third_party/llvm-subzero/include/llvm/IR/Constant.h
new file mode 100644
index 0000000..3c5fe55
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Constant.h
@@ -0,0 +1,164 @@
+//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the Constant class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_CONSTANT_H
+#define LLVM_IR_CONSTANT_H
+
+#include "llvm/IR/User.h"
+
+namespace llvm {
+  class APInt;
+
+  template<typename T> class SmallVectorImpl;
+
+/// This is an important base class in LLVM. It provides the common facilities
+/// of all constant values in an LLVM program. A constant is a value that is
+/// immutable at runtime. Functions are constants because their address is
+/// immutable. Same with global variables.
+///
+/// All constants share the capabilities provided in this class. All constants
+/// can have a null value. They can have an operand list. Constants can be
+/// simple (integer and floating point values), complex (arrays and structures),
+/// or expression based (computations yielding a constant value composed of
+/// only certain operators and other constant values).
+///
+/// Note that Constants are immutable (once created they never change)
+/// and are fully shared by structural equivalence.  This means that two
+/// structurally equivalent constants will always have the same address.
+/// Constants are created on demand as needed and never deleted: thus clients
+/// don't have to worry about the lifetime of the objects.
+/// @brief LLVM Constant Representation
+class Constant : public User {
+  void operator=(const Constant &) = delete;
+  Constant(const Constant &) = delete;
+  void anchor() override;
+
+protected:
+  Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps)
+    : User(ty, vty, Ops, NumOps) {}
+
+public:
+  /// Return true if this is the value that would be returned by getNullValue.
+  bool isNullValue() const;
+
+  /// Returns true if the value is one.
+  bool isOneValue() const;
+
+  /// Return true if this is the value that would be returned by
+  /// getAllOnesValue.
+  bool isAllOnesValue() const;
+
+  /// Return true if the value is what would be returned by
+  /// getZeroValueForNegation.
+  bool isNegativeZeroValue() const;
+
+  /// Return true if the value is negative zero or null value.
+  bool isZeroValue() const;
+
+  /// Return true if the value is not the smallest signed value.
+  bool isNotMinSignedValue() const;
+
+  /// Return true if the value is the smallest signed value.
+  bool isMinSignedValue() const;
+
+  /// Return true if evaluation of this constant could trap. This is true for
+  /// things like constant expressions that could divide by zero.
+  bool canTrap() const;
+
+  /// Return true if the value can vary between threads.
+  bool isThreadDependent() const;
+
+  /// Return true if the value is dependent on a dllimport variable.
+  bool isDLLImportDependent() const;
+
+  /// Return true if the constant has users other than constant expressions and
+  /// other dangling things.
+  bool isConstantUsed() const;
+
+  /// This method classifies the entry according to whether or not it may
+  /// generate a relocation entry.  This must be conservative, so if it might
+  /// codegen to a relocatable entry, it should say so.
+  ///
+  /// FIXME: This really should not be in IR.
+  bool needsRelocation() const;
+
+  /// For aggregates (struct/array/vector) return the constant that corresponds
+  /// to the specified element if possible, or null if not. This can return null
+  /// if the element index is a ConstantExpr, or if 'this' is a constant expr.
+  Constant *getAggregateElement(unsigned Elt) const;
+  Constant *getAggregateElement(Constant *Elt) const;
+
+  /// If this is a splat vector constant, meaning that all of the elements have
+  /// the same value, return that value. Otherwise return 0.
+  Constant *getSplatValue() const;
+
+  /// If C is a constant integer then return its value, otherwise C must be a
+  /// vector of constant integers, all equal, and the common value is returned.
+  const APInt &getUniqueInteger() const;
+
+  /// Called if some element of this constant is no longer valid.
+  /// At this point only other constants may be on the use_list for this
+  /// constant.  Any constants on our Use list must also be destroy'd.  The
+  /// implementation must be sure to remove the constant from the list of
+  /// available cached constants.  Implementations should implement
+  /// destroyConstantImpl to remove constants from any pools/maps they are
+  /// contained it.
+  void destroyConstant();
+
+  //// Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Value *V) {
+    return V->getValueID() >= ConstantFirstVal &&
+           V->getValueID() <= ConstantLastVal;
+  }
+
+  /// This method is a special form of User::replaceUsesOfWith
+  /// (which does not work on constants) that does work
+  /// on constants.  Basically this method goes through the trouble of building
+  /// a new constant that is equivalent to the current one, with all uses of
+  /// From replaced with uses of To.  After this construction is completed, all
+  /// of the users of 'this' are replaced to use the new constant, and then
+  /// 'this' is deleted.  In general, you should not call this method, instead,
+  /// use Value::replaceAllUsesWith, which automatically dispatches to this
+  /// method as needed.
+  ///
+  void handleOperandChange(Value *, Value *);
+
+  static Constant *getNullValue(Type* Ty);
+
+  /// @returns the value for an integer or vector of integer constant of the
+  /// given type that has all its bits set to true.
+  /// @brief Get the all ones value
+  static Constant *getAllOnesValue(Type* Ty);
+
+  /// Return the value for an integer or pointer constant, or a vector thereof,
+  /// with the given scalar value.
+  static Constant *getIntegerValue(Type *Ty, const APInt &V);
+
+  /// If there are any dead constant users dangling off of this constant, remove
+  /// them. This method is useful for clients that want to check to see if a
+  /// global is unused, but don't want to deal with potentially dead constants
+  /// hanging off of the globals.
+  void removeDeadConstantUsers() const;
+
+  Constant *stripPointerCasts() {
+    return cast<Constant>(Value::stripPointerCasts());
+  }
+
+  const Constant *stripPointerCasts() const {
+    return const_cast<Constant*>(this)->stripPointerCasts();
+  }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/DebugLoc.h b/third_party/llvm-subzero/include/llvm/IR/DebugLoc.h
new file mode 100644
index 0000000..8ea5875
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/DebugLoc.h
@@ -0,0 +1,126 @@
+//===- DebugLoc.h - Debug Location Information ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a number of light weight data structures used
+// to describe and track debug location information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DEBUGLOC_H
+#define LLVM_IR_DEBUGLOC_H
+
+#include "llvm/IR/TrackingMDRef.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+  class LLVMContext;
+  class raw_ostream;
+  class DILocation;
+
+  /// \brief A debug info location.
+  ///
+  /// This class is a wrapper around a tracking reference to an \a DILocation
+  /// pointer.
+  ///
+  /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a
+  /// one based on relatively opaque \a MDNode pointers.
+  class DebugLoc {
+    TrackingMDNodeRef Loc;
+
+  public:
+    DebugLoc() {}
+    DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {}
+    DebugLoc(const DebugLoc &X) : Loc(X.Loc) {}
+    DebugLoc &operator=(DebugLoc &&X) {
+      Loc = std::move(X.Loc);
+      return *this;
+    }
+    DebugLoc &operator=(const DebugLoc &X) {
+      Loc = X.Loc;
+      return *this;
+    }
+
+    /// \brief Construct from an \a DILocation.
+    DebugLoc(const DILocation *L);
+
+    /// \brief Construct from an \a MDNode.
+    ///
+    /// Note: if \c N is not an \a DILocation, a verifier check will fail, and
+    /// accessors will crash.  However, construction from other nodes is
+    /// supported in order to handle forward references when reading textual
+    /// IR.
+    explicit DebugLoc(const MDNode *N);
+
+    /// \brief Get the underlying \a DILocation.
+    ///
+    /// \pre !*this or \c isa<DILocation>(getAsMDNode()).
+    /// @{
+    DILocation *get() const;
+    operator DILocation *() const { return get(); }
+    DILocation *operator->() const { return get(); }
+    DILocation &operator*() const { return *get(); }
+    /// @}
+
+    /// \brief Check for null.
+    ///
+    /// Check for null in a way that is safe with broken debug info.  Unlike
+    /// the conversion to \c DILocation, this doesn't require that \c Loc is of
+    /// the right type.  Important for cases like \a llvm::StripDebugInfo() and
+    /// \a Instruction::hasMetadata().
+    explicit operator bool() const { return Loc; }
+
+    /// \brief Check whether this has a trivial destructor.
+    bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); }
+
+    /// \brief Create a new DebugLoc.
+    ///
+    /// Create a new DebugLoc at the specified line/col and scope/inline.  This
+    /// forwards to \a DILocation::get().
+    ///
+    /// If \c !Scope, returns a default-constructed \a DebugLoc.
+    ///
+    /// FIXME: Remove this.  Users should use DILocation::get().
+    static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope,
+                        const MDNode *InlinedAt = nullptr);
+
+    unsigned getLine() const;
+    unsigned getCol() const;
+    MDNode *getScope() const;
+    DILocation *getInlinedAt() const;
+
+    /// \brief Get the fully inlined-at scope for a DebugLoc.
+    ///
+    /// Gets the inlined-at scope for a DebugLoc.
+    MDNode *getInlinedAtScope() const;
+
+    /// \brief Find the debug info location for the start of the function.
+    ///
+    /// Walk up the scope chain of given debug loc and find line number info
+    /// for the function.
+    ///
+    /// FIXME: Remove this.  Users should use DILocation/DILocalScope API to
+    /// find the subprogram, and then DILocation::get().
+    DebugLoc getFnDebugLoc() const;
+
+    /// \brief Return \c this as a bar \a MDNode.
+    MDNode *getAsMDNode() const { return Loc; }
+
+    bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
+    bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; }
+
+    void dump() const;
+
+    /// \brief prints source location /path/to/file.exe:line:col @[inlined at]
+    void print(raw_ostream &OS) const;
+  };
+
+} // end namespace llvm
+
+#endif /* LLVM_SUPPORT_DEBUGLOC_H */
diff --git a/third_party/llvm-subzero/include/llvm/IR/DerivedTypes.h b/third_party/llvm-subzero/include/llvm/IR/DerivedTypes.h
new file mode 100644
index 0000000..efd0d07
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/DerivedTypes.h
@@ -0,0 +1,480 @@
+//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations of classes that represent "derived
+// types".  These are things like "arrays of x" or "structure of x, y, z" or
+// "function returning x taking (y,z) as parameters", etc...
+//
+// The implementations of these classes live in the Type.cpp file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DERIVEDTYPES_H
+#define LLVM_IR_DERIVEDTYPES_H
+
+#include "llvm/IR/Type.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class Value;
+class APInt;
+class LLVMContext;
+template<typename T> class ArrayRef;
+class StringRef;
+
+/// Class to represent integer types. Note that this class is also used to
+/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and
+/// Int64Ty.
+/// @brief Integer representation type
+class IntegerType : public Type {
+  friend class LLVMContextImpl;
+
+protected:
+  explicit IntegerType(LLVMContext &C, unsigned NumBits) : Type(C, IntegerTyID){
+    setSubclassData(NumBits);
+  }
+
+public:
+  /// This enum is just used to hold constants we need for IntegerType.
+  enum {
+    MIN_INT_BITS = 1,        ///< Minimum number of bits that can be specified
+    MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified
+      ///< Note that bit width is stored in the Type classes SubclassData field
+      ///< which has 23 bits. This yields a maximum bit width of 8,388,607 bits.
+  };
+
+  /// This static method is the primary way of constructing an IntegerType.
+  /// If an IntegerType with the same NumBits value was previously instantiated,
+  /// that instance will be returned. Otherwise a new one will be created. Only
+  /// one instance with a given NumBits value is ever created.
+  /// @brief Get or create an IntegerType instance.
+  static IntegerType *get(LLVMContext &C, unsigned NumBits);
+
+  /// @brief Get the number of bits in this IntegerType
+  unsigned getBitWidth() const { return getSubclassData(); }
+
+  /// Return a bitmask with ones set for all of the bits that can be set by an
+  /// unsigned version of this type. This is 0xFF for i8, 0xFFFF for i16, etc.
+  uint64_t getBitMask() const {
+    return ~uint64_t(0UL) >> (64-getBitWidth());
+  }
+
+  /// Return a uint64_t with just the most significant bit set (the sign bit, if
+  /// the value is treated as a signed number).
+  uint64_t getSignBit() const {
+    return 1ULL << (getBitWidth()-1);
+  }
+
+  /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc.
+  /// @returns a bit mask with ones set for all the bits of this type.
+  /// @brief Get a bit mask for this type.
+  APInt getMask() const;
+
+  /// This method determines if the width of this IntegerType is a power-of-2
+  /// in terms of 8 bit bytes.
+  /// @returns true if this is a power-of-2 byte width.
+  /// @brief Is this a power-of-2 byte-width IntegerType ?
+  bool isPowerOf2ByteWidth() const;
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == IntegerTyID;
+  }
+};
+
+unsigned Type::getIntegerBitWidth() const {
+  return cast<IntegerType>(this)->getBitWidth();
+}
+
+/// Class to represent function types
+///
+class FunctionType : public Type {
+  FunctionType(const FunctionType &) = delete;
+  const FunctionType &operator=(const FunctionType &) = delete;
+  FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs);
+
+public:
+  /// This static method is the primary way of constructing a FunctionType.
+  static FunctionType *get(Type *Result,
+                           ArrayRef<Type*> Params, bool isVarArg);
+
+  /// Create a FunctionType taking no parameters.
+  static FunctionType *get(Type *Result, bool isVarArg);
+
+  /// Return true if the specified type is valid as a return type.
+  static bool isValidReturnType(Type *RetTy);
+
+  /// Return true if the specified type is valid as an argument type.
+  static bool isValidArgumentType(Type *ArgTy);
+
+  bool isVarArg() const { return getSubclassData()!=0; }
+  Type *getReturnType() const { return ContainedTys[0]; }
+
+  typedef Type::subtype_iterator param_iterator;
+  param_iterator param_begin() const { return ContainedTys + 1; }
+  param_iterator param_end() const { return &ContainedTys[NumContainedTys]; }
+  ArrayRef<Type *> params() const {
+    return makeArrayRef(param_begin(), param_end());
+  }
+
+  /// Parameter type accessors.
+  Type *getParamType(unsigned i) const { return ContainedTys[i+1]; }
+
+  /// Return the number of fixed parameters this function type requires.
+  /// This does not consider varargs.
+  unsigned getNumParams() const { return NumContainedTys - 1; }
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == FunctionTyID;
+  }
+};
+static_assert(AlignOf<FunctionType>::Alignment >= AlignOf<Type *>::Alignment,
+              "Alignment sufficient for objects appended to FunctionType");
+
+bool Type::isFunctionVarArg() const {
+  return cast<FunctionType>(this)->isVarArg();
+}
+
+Type *Type::getFunctionParamType(unsigned i) const {
+  return cast<FunctionType>(this)->getParamType(i);
+}
+
+unsigned Type::getFunctionNumParams() const {
+  return cast<FunctionType>(this)->getNumParams();
+}
+
+/// Common super class of ArrayType, StructType, PointerType and VectorType.
+class CompositeType : public Type {
+protected:
+  explicit CompositeType(LLVMContext &C, TypeID tid) : Type(C, tid) {}
+
+public:
+  /// Given an index value into the type, return the type of the element.
+  Type *getTypeAtIndex(const Value *V) const;
+  Type *getTypeAtIndex(unsigned Idx) const;
+  bool indexValid(const Value *V) const;
+  bool indexValid(unsigned Idx) const;
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == ArrayTyID ||
+           T->getTypeID() == StructTyID ||
+           T->getTypeID() == PointerTyID ||
+           T->getTypeID() == VectorTyID;
+  }
+};
+
+/// Class to represent struct types. There are two different kinds of struct
+/// types: Literal structs and Identified structs.
+///
+/// Literal struct types (e.g. { i32, i32 }) are uniqued structurally, and must
+/// always have a body when created.  You can get one of these by using one of
+/// the StructType::get() forms.
+///
+/// Identified structs (e.g. %foo or %42) may optionally have a name and are not
+/// uniqued.  The names for identified structs are managed at the LLVMContext
+/// level, so there can only be a single identified struct with a given name in
+/// a particular LLVMContext.  Identified structs may also optionally be opaque
+/// (have no body specified).  You get one of these by using one of the
+/// StructType::create() forms.
+///
+/// Independent of what kind of struct you have, the body of a struct type are
+/// laid out in memory consequtively with the elements directly one after the
+/// other (if the struct is packed) or (if not packed) with padding between the
+/// elements as defined by DataLayout (which is required to match what the code
+/// generator for a target expects).
+///
+class StructType : public CompositeType {
+  StructType(const StructType &) = delete;
+  const StructType &operator=(const StructType &) = delete;
+  StructType(LLVMContext &C)
+    : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {}
+  enum {
+    /// This is the contents of the SubClassData field.
+    SCDB_HasBody = 1,
+    SCDB_Packed = 2,
+    SCDB_IsLiteral = 4,
+    SCDB_IsSized = 8
+  };
+
+  /// For a named struct that actually has a name, this is a pointer to the
+  /// symbol table entry (maintained by LLVMContext) for the struct.
+  /// This is null if the type is an literal struct or if it is a identified
+  /// type that has an empty name.
+  void *SymbolTableEntry;
+
+public:
+  /// This creates an identified struct.
+  static StructType *create(LLVMContext &Context, StringRef Name);
+  static StructType *create(LLVMContext &Context);
+
+  static StructType *create(ArrayRef<Type *> Elements, StringRef Name,
+                            bool isPacked = false);
+  static StructType *create(ArrayRef<Type *> Elements);
+  static StructType *create(LLVMContext &Context, ArrayRef<Type *> Elements,
+                            StringRef Name, bool isPacked = false);
+  static StructType *create(LLVMContext &Context, ArrayRef<Type *> Elements);
+  static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL;
+
+  /// This static method is the primary way to create a literal StructType.
+  static StructType *get(LLVMContext &Context, ArrayRef<Type*> Elements,
+                         bool isPacked = false);
+
+  /// Create an empty structure type.
+  static StructType *get(LLVMContext &Context, bool isPacked = false);
+
+  /// This static method is a convenience method for creating structure types by
+  /// specifying the elements as arguments. Note that this method always returns
+  /// a non-packed struct, and requires at least one element type.
+  static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL;
+
+  bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; }
+
+  /// Return true if this type is uniqued by structural equivalence, false if it
+  /// is a struct definition.
+  bool isLiteral() const { return (getSubclassData() & SCDB_IsLiteral) != 0; }
+
+  /// Return true if this is a type with an identity that has no body specified
+  /// yet. These prints as 'opaque' in .ll files.
+  bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
+
+  /// isSized - Return true if this is a sized type.
+  bool isSized(SmallPtrSetImpl<Type *> *Visited = nullptr) const;
+
+  /// Return true if this is a named struct that has a non-empty name.
+  bool hasName() const { return SymbolTableEntry != nullptr; }
+
+  /// Return the name for this struct type if it has an identity.
+  /// This may return an empty string for an unnamed struct type.  Do not call
+  /// this on an literal type.
+  StringRef getName() const;
+
+  /// Change the name of this type to the specified name, or to a name with a
+  /// suffix if there is a collision. Do not call this on an literal type.
+  void setName(StringRef Name);
+
+  /// Specify a body for an opaque identified type.
+  void setBody(ArrayRef<Type*> Elements, bool isPacked = false);
+  void setBody(Type *elt1, ...) LLVM_END_WITH_NULL;
+
+  /// Return true if the specified type is valid as a element type.
+  static bool isValidElementType(Type *ElemTy);
+
+  // Iterator access to the elements.
+  typedef Type::subtype_iterator element_iterator;
+  element_iterator element_begin() const { return ContainedTys; }
+  element_iterator element_end() const { return &ContainedTys[NumContainedTys];}
+  ArrayRef<Type *> const elements() const {
+    return makeArrayRef(element_begin(), element_end());
+  }
+
+  /// Return true if this is layout identical to the specified struct.
+  bool isLayoutIdentical(StructType *Other) const;
+
+  /// Random access to the elements
+  unsigned getNumElements() const { return NumContainedTys; }
+  Type *getElementType(unsigned N) const {
+    assert(N < NumContainedTys && "Element number out of range!");
+    return ContainedTys[N];
+  }
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == StructTyID;
+  }
+};
+
+StringRef Type::getStructName() const {
+  return cast<StructType>(this)->getName();
+}
+
+unsigned Type::getStructNumElements() const {
+  return cast<StructType>(this)->getNumElements();
+}
+
+Type *Type::getStructElementType(unsigned N) const {
+  return cast<StructType>(this)->getElementType(N);
+}
+
+/// This is the superclass of the array, pointer and vector type classes.
+/// All of these represent "arrays" in memory. The array type represents a
+/// specifically sized array, pointer types are unsized/unknown size arrays,
+/// vector types represent specifically sized arrays that allow for use of SIMD
+/// instructions. SequentialType holds the common features of all, which stem
+/// from the fact that all three lay their components out in memory identically.
+class SequentialType : public CompositeType {
+  Type *ContainedType;               ///< Storage for the single contained type.
+  SequentialType(const SequentialType &) = delete;
+  const SequentialType &operator=(const SequentialType &) = delete;
+
+protected:
+  SequentialType(TypeID TID, Type *ElType)
+    : CompositeType(ElType->getContext(), TID), ContainedType(ElType) {
+    ContainedTys = &ContainedType;
+    NumContainedTys = 1;
+  }
+
+public:
+  Type *getElementType() const { return getSequentialElementType(); }
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == ArrayTyID ||
+           T->getTypeID() == PointerTyID ||
+           T->getTypeID() == VectorTyID;
+  }
+};
+
+/// Class to represent array types.
+class ArrayType : public SequentialType {
+  uint64_t NumElements;
+
+  ArrayType(const ArrayType &) = delete;
+  const ArrayType &operator=(const ArrayType &) = delete;
+  ArrayType(Type *ElType, uint64_t NumEl);
+
+public:
+  /// This static method is the primary way to construct an ArrayType
+  static ArrayType *get(Type *ElementType, uint64_t NumElements);
+
+  /// Return true if the specified type is valid as a element type.
+  static bool isValidElementType(Type *ElemTy);
+
+  uint64_t getNumElements() const { return NumElements; }
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == ArrayTyID;
+  }
+};
+
+uint64_t Type::getArrayNumElements() const {
+  return cast<ArrayType>(this)->getNumElements();
+}
+
+/// Class to represent vector types.
+class VectorType : public SequentialType {
+  unsigned NumElements;
+
+  VectorType(const VectorType &) = delete;
+  const VectorType &operator=(const VectorType &) = delete;
+  VectorType(Type *ElType, unsigned NumEl);
+
+public:
+  /// This static method is the primary way to construct an VectorType.
+  static VectorType *get(Type *ElementType, unsigned NumElements);
+
+  /// This static method gets a VectorType with the same number of elements as
+  /// the input type, and the element type is an integer type of the same width
+  /// as the input element type.
+  static VectorType *getInteger(VectorType *VTy) {
+    unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+    assert(EltBits && "Element size must be of a non-zero size");
+    Type *EltTy = IntegerType::get(VTy->getContext(), EltBits);
+    return VectorType::get(EltTy, VTy->getNumElements());
+  }
+
+  /// This static method is like getInteger except that the element types are
+  /// twice as wide as the elements in the input type.
+  static VectorType *getExtendedElementVectorType(VectorType *VTy) {
+    unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+    Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2);
+    return VectorType::get(EltTy, VTy->getNumElements());
+  }
+
+  /// This static method is like getInteger except that the element types are
+  /// half as wide as the elements in the input type.
+  static VectorType *getTruncatedElementVectorType(VectorType *VTy) {
+    unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+    assert((EltBits & 1) == 0 &&
+           "Cannot truncate vector element with odd bit-width");
+    Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2);
+    return VectorType::get(EltTy, VTy->getNumElements());
+  }
+
+  /// This static method returns a VectorType with half as many elements as the
+  /// input type and the same element type.
+  static VectorType *getHalfElementsVectorType(VectorType *VTy) {
+    unsigned NumElts = VTy->getNumElements();
+    assert ((NumElts & 1) == 0 &&
+            "Cannot halve vector with odd number of elements.");
+    return VectorType::get(VTy->getElementType(), NumElts/2);
+  }
+
+  /// This static method returns a VectorType with twice as many elements as the
+  /// input type and the same element type.
+  static VectorType *getDoubleElementsVectorType(VectorType *VTy) {
+    unsigned NumElts = VTy->getNumElements();
+    return VectorType::get(VTy->getElementType(), NumElts*2);
+  }
+
+  /// Return true if the specified type is valid as a element type.
+  static bool isValidElementType(Type *ElemTy);
+
+  /// Return the number of elements in the Vector type.
+  unsigned getNumElements() const { return NumElements; }
+
+  /// Return the number of bits in the Vector type.
+  /// Returns zero when the vector is a vector of pointers.
+  unsigned getBitWidth() const {
+    return NumElements * getElementType()->getPrimitiveSizeInBits();
+  }
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == VectorTyID;
+  }
+};
+
+unsigned Type::getVectorNumElements() const {
+  return cast<VectorType>(this)->getNumElements();
+}
+
+/// Class to represent pointers.
+class PointerType : public SequentialType {
+  PointerType(const PointerType &) = delete;
+  const PointerType &operator=(const PointerType &) = delete;
+  explicit PointerType(Type *ElType, unsigned AddrSpace);
+
+public:
+  /// This constructs a pointer to an object of the specified type in a numbered
+  /// address space.
+  static PointerType *get(Type *ElementType, unsigned AddressSpace);
+
+  /// This constructs a pointer to an object of the specified type in the
+  /// generic address space (address space zero).
+  static PointerType *getUnqual(Type *ElementType) {
+    return PointerType::get(ElementType, 0);
+  }
+
+  /// Return true if the specified type is valid as a element type.
+  static bool isValidElementType(Type *ElemTy);
+
+  /// Return true if we can load or store from a pointer to this type.
+  static bool isLoadableOrStorableType(Type *ElemTy);
+
+  /// Return the address space of the Pointer type.
+  inline unsigned getAddressSpace() const { return getSubclassData(); }
+
+  /// Implement support type inquiry through isa, cast, and dyn_cast.
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == PointerTyID;
+  }
+};
+
+unsigned Type::getPointerAddressSpace() const {
+  return cast<PointerType>(getScalarType())->getAddressSpace();
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Function.h b/third_party/llvm-subzero/include/llvm/IR/Function.h
new file mode 100644
index 0000000..ff55fcb
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Function.h
@@ -0,0 +1,666 @@
+//===-- llvm/Function.h - Class to represent a single function --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the Function class, which represents a
+// single function/procedure in LLVM.
+//
+// A function basically consists of a list of basic blocks, a list of arguments,
+// and a symbol table.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_FUNCTION_H
+#define LLVM_IR_FUNCTION_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Argument.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/GlobalObject.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+template <typename T> class Optional;
+class FunctionType;
+class LLVMContext;
+class DISubprogram;
+
+class Function : public GlobalObject, public ilist_node<Function> {
+public:
+  typedef SymbolTableList<Argument> ArgumentListType;
+  typedef SymbolTableList<BasicBlock> BasicBlockListType;
+
+  // BasicBlock iterators...
+  typedef BasicBlockListType::iterator iterator;
+  typedef BasicBlockListType::const_iterator const_iterator;
+
+  typedef ArgumentListType::iterator arg_iterator;
+  typedef ArgumentListType::const_iterator const_arg_iterator;
+
+private:
+  // Important things that make up a function!
+  BasicBlockListType  BasicBlocks;        ///< The basic blocks
+  mutable ArgumentListType ArgumentList;  ///< The formal arguments
+  ValueSymbolTable *SymTab;               ///< Symbol table of args/instructions
+  AttributeSet AttributeSets;             ///< Parameter attributes
+
+  /*
+   * Value::SubclassData
+   *
+   * bit 0      : HasLazyArguments
+   * bit 1      : HasPrefixData
+   * bit 2      : HasPrologueData
+   * bit 3      : HasPersonalityFn
+   * bits 4-13  : CallingConvention
+   * bits 14    : HasGC
+   * bits 15 : [reserved]
+   */
+
+  /// Bits from GlobalObject::GlobalObjectSubclassData.
+  enum {
+    /// Whether this function is materializable.
+    IsMaterializableBit = 0,
+  };
+
+  friend class SymbolTableListTraits<Function>;
+
+  void setParent(Module *parent);
+
+  /// hasLazyArguments/CheckLazyArguments - The argument list of a function is
+  /// built on demand, so that the list isn't allocated until the first client
+  /// needs it.  The hasLazyArguments predicate returns true if the arg list
+  /// hasn't been set up yet.
+public:
+  bool hasLazyArguments() const {
+    return getSubclassDataFromValue() & (1<<0);
+  }
+
+private:
+  void CheckLazyArguments() const {
+    if (hasLazyArguments())
+      BuildLazyArguments();
+  }
+  void BuildLazyArguments() const;
+
+  Function(const Function&) = delete;
+  void operator=(const Function&) = delete;
+
+  /// Function ctor - If the (optional) Module argument is specified, the
+  /// function is automatically inserted into the end of the function list for
+  /// the module.
+  ///
+  Function(FunctionType *Ty, LinkageTypes Linkage,
+           const Twine &N = "", Module *M = nullptr);
+
+public:
+  static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
+                          const Twine &N = "", Module *M = nullptr) {
+    return new Function(Ty, Linkage, N, M);
+  }
+
+  ~Function() override;
+
+  /// \brief Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+  Type *getReturnType() const;           // Return the type of the ret val
+  FunctionType *getFunctionType() const; // Return the FunctionType for me
+
+  /// getContext - Return a reference to the LLVMContext associated with this
+  /// function.
+  LLVMContext &getContext() const;
+
+  /// isVarArg - Return true if this function takes a variable number of
+  /// arguments.
+  bool isVarArg() const;
+
+  bool isMaterializable() const;
+  void setIsMaterializable(bool V);
+
+  /// getIntrinsicID - This method returns the ID number of the specified
+  /// function, or Intrinsic::not_intrinsic if the function is not an
+  /// intrinsic, or if the pointer is null.  This value is always defined to be
+  /// zero to allow easy checking for whether a function is intrinsic or not.
+  /// The particular intrinsic functions which correspond to this value are
+  /// defined in llvm/Intrinsics.h.
+  Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; }
+  bool isIntrinsic() const { return getName().startswith("llvm."); }
+
+  static Intrinsic::ID lookupIntrinsicID(StringRef Name);
+
+  /// \brief Recalculate the ID for this function if it is an Intrinsic defined
+  /// in llvm/Intrinsics.h.  Sets the intrinsic ID to Intrinsic::not_intrinsic
+  /// if the name of this function does not match an intrinsic in that header.
+  /// Note, this method does not need to be called directly, as it is called
+  /// from Value::setName() whenever the name of this function changes.
+  void recalculateIntrinsicID();
+
+  /// getCallingConv()/setCallingConv(CC) - These method get and set the
+  /// calling convention of this function.  The enum values for the known
+  /// calling conventions are defined in CallingConv.h.
+  CallingConv::ID getCallingConv() const {
+    return static_cast<CallingConv::ID>((getSubclassDataFromValue() >> 4) &
+                                        CallingConv::MaxID);
+  }
+  void setCallingConv(CallingConv::ID CC) {
+    auto ID = static_cast<unsigned>(CC);
+    assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention");
+    setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4));
+  }
+
+  /// @brief Return the attribute list for this Function.
+  AttributeSet getAttributes() const { return AttributeSets; }
+
+  /// @brief Set the attribute list for this Function.
+  void setAttributes(AttributeSet Attrs) { AttributeSets = Attrs; }
+
+  /// @brief Add function attributes to this function.
+  void addFnAttr(Attribute::AttrKind N) {
+    setAttributes(AttributeSets.addAttribute(getContext(),
+                                             AttributeSet::FunctionIndex, N));
+  }
+
+  /// @brief Remove function attributes from this function.
+  void removeFnAttr(Attribute::AttrKind Kind) {
+    setAttributes(AttributeSets.removeAttribute(
+        getContext(), AttributeSet::FunctionIndex, Kind));
+  }
+
+  /// @brief Add function attributes to this function.
+  void addFnAttr(StringRef Kind) {
+    setAttributes(
+      AttributeSets.addAttribute(getContext(),
+                                 AttributeSet::FunctionIndex, Kind));
+  }
+  void addFnAttr(StringRef Kind, StringRef Value) {
+    setAttributes(
+      AttributeSets.addAttribute(getContext(),
+                                 AttributeSet::FunctionIndex, Kind, Value));
+  }
+
+  /// @brief Remove function attribute from this function.
+  void removeFnAttr(StringRef Kind) {
+    setAttributes(AttributeSets.removeAttribute(
+        getContext(), AttributeSet::FunctionIndex, Kind));
+  }
+
+  /// Set the entry count for this function.
+  void setEntryCount(uint64_t Count);
+
+  /// Get the entry count for this function.
+  Optional<uint64_t> getEntryCount() const;
+
+  /// @brief Return true if the function has the attribute.
+  bool hasFnAttribute(Attribute::AttrKind Kind) const {
+    return AttributeSets.hasFnAttribute(Kind);
+  }
+  bool hasFnAttribute(StringRef Kind) const {
+    return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
+  }
+
+  /// @brief Return the attribute for the given attribute kind.
+  Attribute getFnAttribute(Attribute::AttrKind Kind) const {
+    return getAttribute(AttributeSet::FunctionIndex, Kind);
+  }
+  Attribute getFnAttribute(StringRef Kind) const {
+    return getAttribute(AttributeSet::FunctionIndex, Kind);
+  }
+
+  /// \brief Return the stack alignment for the function.
+  unsigned getFnStackAlignment() const {
+    if (!hasFnAttribute(Attribute::StackAlignment))
+      return 0;
+    return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
+  }
+
+  /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm
+  ///                             to use during code generation.
+  bool hasGC() const {
+    return getSubclassDataFromValue() & (1<<14);
+  }
+  const std::string &getGC() const;
+  void setGC(std::string Str);
+  void clearGC();
+
+  /// @brief adds the attribute to the list of attributes.
+  void addAttribute(unsigned i, Attribute::AttrKind Kind);
+
+  /// @brief adds the attribute to the list of attributes.
+  void addAttribute(unsigned i, Attribute Attr);
+
+  /// @brief adds the attributes to the list of attributes.
+  void addAttributes(unsigned i, AttributeSet Attrs);
+
+  /// @brief removes the attribute from the list of attributes.
+  void removeAttribute(unsigned i, Attribute::AttrKind Kind);
+
+  /// @brief removes the attribute from the list of attributes.
+  void removeAttribute(unsigned i, StringRef Kind);
+
+  /// @brief removes the attributes from the list of attributes.
+  void removeAttributes(unsigned i, AttributeSet Attrs);
+
+  /// @brief check if an attributes is in the list of attributes.
+  bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
+    return getAttributes().hasAttribute(i, Kind);
+  }
+
+  Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
+    return AttributeSets.getAttribute(i, Kind);
+  }
+
+  Attribute getAttribute(unsigned i, StringRef Kind) const {
+    return AttributeSets.getAttribute(i, Kind);
+  }
+
+  /// @brief adds the dereferenceable attribute to the list of attributes.
+  void addDereferenceableAttr(unsigned i, uint64_t Bytes);
+
+  /// @brief adds the dereferenceable_or_null attribute to the list of
+  /// attributes.
+  void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
+
+  /// @brief Extract the alignment for a call or parameter (0=unknown).
+  unsigned getParamAlignment(unsigned i) const {
+    return AttributeSets.getParamAlignment(i);
+  }
+
+  /// @brief Extract the number of dereferenceable bytes for a call or
+  /// parameter (0=unknown).
+  uint64_t getDereferenceableBytes(unsigned i) const {
+    return AttributeSets.getDereferenceableBytes(i);
+  }
+
+  /// @brief Extract the number of dereferenceable_or_null bytes for a call or
+  /// parameter (0=unknown).
+  uint64_t getDereferenceableOrNullBytes(unsigned i) const {
+    return AttributeSets.getDereferenceableOrNullBytes(i);
+  }
+
+  /// @brief Determine if the function does not access memory.
+  bool doesNotAccessMemory() const {
+    return hasFnAttribute(Attribute::ReadNone);
+  }
+  void setDoesNotAccessMemory() {
+    addFnAttr(Attribute::ReadNone);
+  }
+
+  /// @brief Determine if the function does not access or only reads memory.
+  bool onlyReadsMemory() const {
+    return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly);
+  }
+  void setOnlyReadsMemory() {
+    addFnAttr(Attribute::ReadOnly);
+  }
+
+  /// @brief Determine if the function does not access or only writes memory.
+  bool doesNotReadMemory() const {
+    return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly);
+  }
+  void setDoesNotReadMemory() {
+    addFnAttr(Attribute::WriteOnly);
+  }
+
+  /// @brief Determine if the call can access memmory only using pointers based
+  /// on its arguments.
+  bool onlyAccessesArgMemory() const {
+    return hasFnAttribute(Attribute::ArgMemOnly);
+  }
+  void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); }
+
+  /// @brief Determine if the function may only access memory that is 
+  ///  inaccessible from the IR.
+  bool onlyAccessesInaccessibleMemory() const {
+    return hasFnAttribute(Attribute::InaccessibleMemOnly);
+  }
+  void setOnlyAccessesInaccessibleMemory() {
+    addFnAttr(Attribute::InaccessibleMemOnly);
+  }
+
+  /// @brief Determine if the function may only access memory that is
+  //  either inaccessible from the IR or pointed to by its arguments.
+  bool onlyAccessesInaccessibleMemOrArgMem() const {
+    return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly);
+  }
+  void setOnlyAccessesInaccessibleMemOrArgMem() {
+    addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
+  }
+
+  /// @brief Determine if the function cannot return.
+  bool doesNotReturn() const {
+    return hasFnAttribute(Attribute::NoReturn);
+  }
+  void setDoesNotReturn() {
+    addFnAttr(Attribute::NoReturn);
+  }
+
+  /// @brief Determine if the function cannot unwind.
+  bool doesNotThrow() const {
+    return hasFnAttribute(Attribute::NoUnwind);
+  }
+  void setDoesNotThrow() {
+    addFnAttr(Attribute::NoUnwind);
+  }
+
+  /// @brief Determine if the call cannot be duplicated.
+  bool cannotDuplicate() const {
+    return hasFnAttribute(Attribute::NoDuplicate);
+  }
+  void setCannotDuplicate() {
+    addFnAttr(Attribute::NoDuplicate);
+  }
+
+  /// @brief Determine if the call is convergent.
+  bool isConvergent() const {
+    return hasFnAttribute(Attribute::Convergent);
+  }
+  void setConvergent() {
+    addFnAttr(Attribute::Convergent);
+  }
+  void setNotConvergent() {
+    removeFnAttr(Attribute::Convergent);
+  }
+
+  /// Determine if the function is known not to recurse, directly or
+  /// indirectly.
+  bool doesNotRecurse() const {
+    return hasFnAttribute(Attribute::NoRecurse);
+  }
+  void setDoesNotRecurse() {
+    addFnAttr(Attribute::NoRecurse);
+  }  
+
+  /// @brief True if the ABI mandates (or the user requested) that this
+  /// function be in a unwind table.
+  bool hasUWTable() const {
+    return hasFnAttribute(Attribute::UWTable);
+  }
+  void setHasUWTable() {
+    addFnAttr(Attribute::UWTable);
+  }
+
+  /// @brief True if this function needs an unwind table.
+  bool needsUnwindTableEntry() const {
+    return hasUWTable() || !doesNotThrow();
+  }
+
+  /// @brief Determine if the function returns a structure through first
+  /// pointer argument.
+  bool hasStructRetAttr() const {
+    return AttributeSets.hasAttribute(1, Attribute::StructRet) ||
+           AttributeSets.hasAttribute(2, Attribute::StructRet);
+  }
+
+  /// @brief Determine if the parameter or return value is marked with NoAlias
+  /// attribute.
+  /// @param n The parameter to check. 1 is the first parameter, 0 is the return
+  bool doesNotAlias(unsigned n) const {
+    return AttributeSets.hasAttribute(n, Attribute::NoAlias);
+  }
+  void setDoesNotAlias(unsigned n) {
+    addAttribute(n, Attribute::NoAlias);
+  }
+
+  /// @brief Determine if the parameter can be captured.
+  /// @param n The parameter to check. 1 is the first parameter, 0 is the return
+  bool doesNotCapture(unsigned n) const {
+    return AttributeSets.hasAttribute(n, Attribute::NoCapture);
+  }
+  void setDoesNotCapture(unsigned n) {
+    addAttribute(n, Attribute::NoCapture);
+  }
+
+  bool doesNotAccessMemory(unsigned n) const {
+    return AttributeSets.hasAttribute(n, Attribute::ReadNone);
+  }
+  void setDoesNotAccessMemory(unsigned n) {
+    addAttribute(n, Attribute::ReadNone);
+  }
+
+  bool onlyReadsMemory(unsigned n) const {
+    return doesNotAccessMemory(n) ||
+      AttributeSets.hasAttribute(n, Attribute::ReadOnly);
+  }
+  void setOnlyReadsMemory(unsigned n) {
+    addAttribute(n, Attribute::ReadOnly);
+  }
+
+  /// Optimize this function for minimum size (-Oz).
+  bool optForMinSize() const { return hasFnAttribute(Attribute::MinSize); }
+
+  /// Optimize this function for size (-Os) or minimum size (-Oz).
+  bool optForSize() const {
+    return hasFnAttribute(Attribute::OptimizeForSize) || optForMinSize();
+  }
+
+  /// copyAttributesFrom - copy all additional attributes (those not needed to
+  /// create a Function) from the Function Src to this one.
+  void copyAttributesFrom(const GlobalValue *Src) override;
+
+  /// deleteBody - This method deletes the body of the function, and converts
+  /// the linkage to external.
+  ///
+  void deleteBody() {
+    dropAllReferences();
+    setLinkage(ExternalLinkage);
+  }
+
+  /// removeFromParent - This method unlinks 'this' from the containing module,
+  /// but does not delete it.
+  ///
+  void removeFromParent() override;
+
+  /// eraseFromParent - This method unlinks 'this' from the containing module
+  /// and deletes it.
+  ///
+  void eraseFromParent() override;
+
+  /// Steal arguments from another function.
+  ///
+  /// Drop this function's arguments and splice in the ones from \c Src.
+  /// Requires that this has no function body.
+  void stealArgumentListFrom(Function &Src);
+
+  /// Get the underlying elements of the Function... the basic block list is
+  /// empty for external functions.
+  ///
+  const ArgumentListType &getArgumentList() const {
+    CheckLazyArguments();
+    return ArgumentList;
+  }
+  ArgumentListType &getArgumentList() {
+    CheckLazyArguments();
+    return ArgumentList;
+  }
+  static ArgumentListType Function::*getSublistAccess(Argument*) {
+    return &Function::ArgumentList;
+  }
+
+  const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; }
+        BasicBlockListType &getBasicBlockList()       { return BasicBlocks; }
+  static BasicBlockListType Function::*getSublistAccess(BasicBlock*) {
+    return &Function::BasicBlocks;
+  }
+
+  const BasicBlock       &getEntryBlock() const   { return front(); }
+        BasicBlock       &getEntryBlock()         { return front(); }
+
+  //===--------------------------------------------------------------------===//
+  // Symbol Table Accessing functions...
+
+  /// getSymbolTable() - Return the symbol table...
+  ///
+  inline       ValueSymbolTable &getValueSymbolTable()       { return *SymTab; }
+  inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; }
+
+  //===--------------------------------------------------------------------===//
+  // BasicBlock iterator forwarding functions
+  //
+  iterator                begin()       { return BasicBlocks.begin(); }
+  const_iterator          begin() const { return BasicBlocks.begin(); }
+  iterator                end  ()       { return BasicBlocks.end();   }
+  const_iterator          end  () const { return BasicBlocks.end();   }
+
+  size_t                   size() const { return BasicBlocks.size();  }
+  bool                    empty() const { return BasicBlocks.empty(); }
+  const BasicBlock       &front() const { return BasicBlocks.front(); }
+        BasicBlock       &front()       { return BasicBlocks.front(); }
+  const BasicBlock        &back() const { return BasicBlocks.back();  }
+        BasicBlock        &back()       { return BasicBlocks.back();  }
+
+/// @name Function Argument Iteration
+/// @{
+
+  arg_iterator arg_begin() {
+    CheckLazyArguments();
+    return ArgumentList.begin();
+  }
+  const_arg_iterator arg_begin() const {
+    CheckLazyArguments();
+    return ArgumentList.begin();
+  }
+  arg_iterator arg_end() {
+    CheckLazyArguments();
+    return ArgumentList.end();
+  }
+  const_arg_iterator arg_end() const {
+    CheckLazyArguments();
+    return ArgumentList.end();
+  }
+
+  iterator_range<arg_iterator> args() {
+    return make_range(arg_begin(), arg_end());
+  }
+
+  iterator_range<const_arg_iterator> args() const {
+    return make_range(arg_begin(), arg_end());
+  }
+
+/// @}
+
+  size_t arg_size() const;
+  bool arg_empty() const;
+
+  /// \brief Check whether this function has a personality function.
+  bool hasPersonalityFn() const {
+    return getSubclassDataFromValue() & (1<<3);
+  }
+
+  /// \brief Get the personality function associated with this function.
+  Constant *getPersonalityFn() const;
+  void setPersonalityFn(Constant *Fn);
+
+  /// \brief Check whether this function has prefix data.
+  bool hasPrefixData() const {
+    return getSubclassDataFromValue() & (1<<1);
+  }
+
+  /// \brief Get the prefix data associated with this function.
+  Constant *getPrefixData() const;
+  void setPrefixData(Constant *PrefixData);
+
+  /// \brief Check whether this function has prologue data.
+  bool hasPrologueData() const {
+    return getSubclassDataFromValue() & (1<<2);
+  }
+
+  /// \brief Get the prologue data associated with this function.
+  Constant *getPrologueData() const;
+  void setPrologueData(Constant *PrologueData);
+
+  /// Print the function to an output stream with an optional
+  /// AssemblyAnnotationWriter.
+  void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr,
+             bool ShouldPreserveUseListOrder = false,
+             bool IsForDebug = false) const;
+
+  /// viewCFG - This function is meant for use from the debugger.  You can just
+  /// say 'call F->viewCFG()' and a ghostview window should pop up from the
+  /// program, displaying the CFG of the current function with the code for each
+  /// basic block inside.  This depends on there being a 'dot' and 'gv' program
+  /// in your path.
+  ///
+  void viewCFG() const;
+
+  /// viewCFGOnly - This function is meant for use from the debugger.  It works
+  /// just like viewCFG, but it does not include the contents of basic blocks
+  /// into the nodes, just the label.  If you are only interested in the CFG
+  /// this can make the graph smaller.
+  ///
+  void viewCFGOnly() const;
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Value *V) {
+    return V->getValueID() == Value::FunctionVal;
+  }
+
+  /// dropAllReferences() - This method causes all the subinstructions to "let
+  /// go" of all references that they are maintaining.  This allows one to
+  /// 'delete' a whole module at a time, even though there may be circular
+  /// references... first all references are dropped, and all use counts go to
+  /// zero.  Then everything is deleted for real.  Note that no operations are
+  /// valid on an object that has "dropped all references", except operator
+  /// delete.
+  ///
+  /// Since no other object in the module can have references into the body of a
+  /// function, dropping all references deletes the entire body of the function,
+  /// including any contained basic blocks.
+  ///
+  void dropAllReferences();
+
+  /// hasAddressTaken - returns true if there are any uses of this function
+  /// other than direct calls or invokes to it, or blockaddress expressions.
+  /// Optionally passes back an offending user for diagnostic purposes.
+  ///
+  bool hasAddressTaken(const User** = nullptr) const;
+
+  /// isDefTriviallyDead - Return true if it is trivially safe to remove
+  /// this function definition from the module (because it isn't externally
+  /// visible, does not have its address taken, and has no callers).  To make
+  /// this more accurate, call removeDeadConstantUsers first.
+  bool isDefTriviallyDead() const;
+
+  /// callsFunctionThatReturnsTwice - Return true if the function has a call to
+  /// setjmp or other function that gcc recognizes as "returning twice".
+  bool callsFunctionThatReturnsTwice() const;
+
+  /// \brief Set the attached subprogram.
+  ///
+  /// Calls \a setMetadata() with \a LLVMContext::MD_dbg.
+  void setSubprogram(DISubprogram *SP);
+
+  /// \brief Get the attached subprogram.
+  ///
+  /// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result
+  /// to \a DISubprogram.
+  DISubprogram *getSubprogram() const;
+
+private:
+  void allocHungoffUselist();
+  template<int Idx> void setHungoffOperand(Constant *C);
+
+  // Shadow Value::setValueSubclassData with a private forwarding method so that
+  // subclasses cannot accidentally use it.
+  void setValueSubclassData(unsigned short D) {
+    Value::setValueSubclassData(D);
+  }
+  void setValueSubclassDataBit(unsigned Bit, bool On);
+};
+
+template <>
+struct OperandTraits<Function> : public HungoffOperandTraits<3> {};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value)
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/GlobalObject.h b/third_party/llvm-subzero/include/llvm/IR/GlobalObject.h
new file mode 100644
index 0000000..04737a0
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/GlobalObject.h
@@ -0,0 +1,146 @@
+//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This represents an independent object. That is, a function or a global
+// variable, but not an alias.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_GLOBALOBJECT_H
+#define LLVM_IR_GLOBALOBJECT_H
+
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GlobalValue.h"
+
+namespace llvm {
+class Comdat;
+class MDNode;
+class Metadata;
+class Module;
+
+class GlobalObject : public GlobalValue {
+  GlobalObject(const GlobalObject &) = delete;
+
+protected:
+  GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
+               LinkageTypes Linkage, const Twine &Name,
+               unsigned AddressSpace = 0)
+      : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name, AddressSpace),
+        ObjComdat(nullptr) {
+    setGlobalValueSubClassData(0);
+  }
+
+  std::string Section;     // Section to emit this into, empty means default
+  Comdat *ObjComdat;
+  enum {
+    LastAlignmentBit = 4,
+    HasMetadataHashEntryBit,
+
+    GlobalObjectBits,
+  };
+  static const unsigned GlobalObjectSubClassDataBits =
+      GlobalValueSubClassDataBits - GlobalObjectBits;
+
+private:
+  static const unsigned AlignmentBits = LastAlignmentBit + 1;
+  static const unsigned AlignmentMask = (1 << AlignmentBits) - 1;
+  static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1;
+
+public:
+  unsigned getAlignment() const {
+    unsigned Data = getGlobalValueSubClassData();
+    unsigned AlignmentData = Data & AlignmentMask;
+    return (1u << AlignmentData) >> 1;
+  }
+  void setAlignment(unsigned Align);
+
+  unsigned getGlobalObjectSubClassData() const;
+  void setGlobalObjectSubClassData(unsigned Val);
+
+  bool hasSection() const { return !getSection().empty(); }
+  StringRef getSection() const { return Section; }
+  void setSection(StringRef S);
+
+  bool hasComdat() const { return getComdat() != nullptr; }
+  const Comdat *getComdat() const { return ObjComdat; }
+  Comdat *getComdat() { return ObjComdat; }
+  void setComdat(Comdat *C) { ObjComdat = C; }
+
+  /// Check if this has any metadata.
+  bool hasMetadata() const { return hasMetadataHashEntry(); }
+
+  /// Get the current metadata attachments for the given kind, if any.
+  ///
+  /// These functions require that the function have at most a single attachment
+  /// of the given kind, and return \c nullptr if such an attachment is missing.
+  /// @{
+  MDNode *getMetadata(unsigned KindID) const;
+  MDNode *getMetadata(StringRef Kind) const;
+  /// @}
+
+  /// Appends all attachments with the given ID to \c MDs in insertion order.
+  /// If the global has no attachments with the given ID, or if ID is invalid,
+  /// leaves MDs unchanged.
+  /// @{
+  void getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const;
+  void getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &MDs) const;
+  /// @}
+
+  /// Set a particular kind of metadata attachment.
+  ///
+  /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
+  /// replacing it if it already exists.
+  /// @{
+  void setMetadata(unsigned KindID, MDNode *MD);
+  void setMetadata(StringRef Kind, MDNode *MD);
+  /// @}
+
+  /// Add a metadata attachment.
+  /// @{
+  void addMetadata(unsigned KindID, MDNode &MD);
+  void addMetadata(StringRef Kind, MDNode &MD);
+  /// @}
+
+  /// Appends all attachments for the global to \c MDs, sorting by attachment
+  /// ID. Attachments with the same ID appear in insertion order.
+  void
+  getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
+
+  /// Erase all metadata attachments with the given kind.
+  void eraseMetadata(unsigned KindID);
+
+  /// Copy metadata from Src, adjusting offsets by Offset.
+  void copyMetadata(const GlobalObject *Src, unsigned Offset);
+
+  void addTypeMetadata(unsigned Offset, Metadata *TypeID);
+
+  void copyAttributesFrom(const GlobalValue *Src) override;
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Value *V) {
+    return V->getValueID() == Value::FunctionVal ||
+           V->getValueID() == Value::GlobalVariableVal;
+  }
+
+  void clearMetadata();
+
+private:
+  bool hasMetadataHashEntry() const {
+    return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit);
+  }
+  void setHasMetadataHashEntry(bool HasEntry) {
+    unsigned Mask = 1 << HasMetadataHashEntryBit;
+    setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) |
+                               (HasEntry ? Mask : 0u));
+  }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/GlobalValue.h b/third_party/llvm-subzero/include/llvm/IR/GlobalValue.h
new file mode 100644
index 0000000..09682f7
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/GlobalValue.h
@@ -0,0 +1,517 @@
+//===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a common base class of all globally definable objects.  As such,
+// it is subclassed by GlobalVariable, GlobalAlias and by Function.  This is
+// used because you can do certain things with these global objects that you
+// can't do to anything else.  For example, use the address of one as a
+// constant.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_GLOBALVALUE_H
+#define LLVM_IR_GLOBALVALUE_H
+
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Support/MD5.h"
+#include <system_error>
+
+namespace llvm {
+
+class Comdat;
+class PointerType;
+class Module;
+
+namespace Intrinsic {
+  enum ID : unsigned;
+}
+
+class GlobalValue : public Constant {
+  GlobalValue(const GlobalValue &) = delete;
+public:
+  /// @brief An enumeration for the kinds of linkage for global values.
+  enum LinkageTypes {
+    ExternalLinkage = 0,///< Externally visible function
+    AvailableExternallyLinkage, ///< Available for inspection, not emission.
+    LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline)
+    LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent.
+    WeakAnyLinkage,     ///< Keep one copy of named function when linking (weak)
+    WeakODRLinkage,     ///< Same, but only replaced by something equivalent.
+    AppendingLinkage,   ///< Special purpose, only applies to global arrays
+    InternalLinkage,    ///< Rename collisions when linking (static functions).
+    PrivateLinkage,     ///< Like Internal, but omit from symbol table.
+    ExternalWeakLinkage,///< ExternalWeak linkage description.
+    CommonLinkage       ///< Tentative definitions.
+  };
+
+  /// @brief An enumeration for the kinds of visibility of global values.
+  enum VisibilityTypes {
+    DefaultVisibility = 0,  ///< The GV is visible
+    HiddenVisibility,       ///< The GV is hidden
+    ProtectedVisibility     ///< The GV is protected
+  };
+
+  /// @brief Storage classes of global values for PE targets.
+  enum DLLStorageClassTypes {
+    DefaultStorageClass   = 0,
+    DLLImportStorageClass = 1, ///< Function to be imported from DLL
+    DLLExportStorageClass = 2  ///< Function to be accessible from DLL.
+  };
+
+protected:
+  GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
+              LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace)
+      : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps),
+        ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility),
+        UnnamedAddrVal(unsigned(UnnamedAddr::None)),
+        DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),
+        IntID((Intrinsic::ID)0U), Parent(nullptr) {
+    setName(Name);
+  }
+
+  Type *ValueType;
+  // All bitfields use unsigned as the underlying type so that MSVC will pack
+  // them.
+  unsigned Linkage : 4;       // The linkage of this global
+  unsigned Visibility : 2;    // The visibility style of this global
+  unsigned UnnamedAddrVal : 2; // This value's address is not significant
+  unsigned DllStorageClass : 2; // DLL storage class
+
+  unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is
+                            // the desired model?
+  static const unsigned GlobalValueSubClassDataBits = 19;
+
+private:
+  // Give subclasses access to what otherwise would be wasted padding.
+  // (19 + 4 + 2 + 2 + 2 + 3) == 32.
+  unsigned SubClassData : GlobalValueSubClassDataBits;
+
+  friend class Constant;
+  void destroyConstantImpl();
+  Value *handleOperandChangeImpl(Value *From, Value *To);
+
+  /// Returns true if the definition of this global may be replaced by a
+  /// differently optimized variant of the same source level function at link
+  /// time.
+  bool mayBeDerefined() const {
+    switch (getLinkage()) {
+    case WeakODRLinkage:
+    case LinkOnceODRLinkage:
+    case AvailableExternallyLinkage:
+      return true;
+
+    case WeakAnyLinkage:
+    case LinkOnceAnyLinkage:
+    case CommonLinkage:
+    case ExternalWeakLinkage:
+    case ExternalLinkage:
+    case AppendingLinkage:
+    case InternalLinkage:
+    case PrivateLinkage:
+      return isInterposable();
+    }
+
+    llvm_unreachable("Fully covered switch above!");
+  }
+
+protected:
+  /// \brief The intrinsic ID for this subclass (which must be a Function).
+  ///
+  /// This member is defined by this class, but not used for anything.
+  /// Subclasses can use it to store their intrinsic ID, if they have one.
+  ///
+  /// This is stored here to save space in Function on 64-bit hosts.
+  Intrinsic::ID IntID;
+
+  unsigned getGlobalValueSubClassData() const {
+    return SubClassData;
+  }
+  void setGlobalValueSubClassData(unsigned V) {
+    assert(V < (1 << GlobalValueSubClassDataBits) && "It will not fit");
+    SubClassData = V;
+  }
+
+  Module *Parent;             // The containing module.
+public:
+  enum ThreadLocalMode {
+    NotThreadLocal = 0,
+    GeneralDynamicTLSModel,
+    LocalDynamicTLSModel,
+    InitialExecTLSModel,
+    LocalExecTLSModel
+  };
+
+  ~GlobalValue() override {
+    removeDeadConstantUsers();   // remove any dead constants using this.
+  }
+
+  unsigned getAlignment() const;
+
+  enum class UnnamedAddr {
+    None,
+    Local,
+    Global,
+  };
+
+  bool hasGlobalUnnamedAddr() const {
+    return getUnnamedAddr() == UnnamedAddr::Global;
+  }
+
+  /// Returns true if this value's address is not significant in this module.
+  /// This attribute is intended to be used only by the code generator and LTO
+  /// to allow the linker to decide whether the global needs to be in the symbol
+  /// table. It should probably not be used in optimizations, as the value may
+  /// have uses outside the module; use hasGlobalUnnamedAddr() instead.
+  bool hasAtLeastLocalUnnamedAddr() const {
+    return getUnnamedAddr() != UnnamedAddr::None;
+  }
+
+  UnnamedAddr getUnnamedAddr() const {
+    return UnnamedAddr(UnnamedAddrVal);
+  }
+  void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); }
+
+  static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) {
+    if (A == UnnamedAddr::None || B == UnnamedAddr::None)
+      return UnnamedAddr::None;
+    if (A == UnnamedAddr::Local || B == UnnamedAddr::Local)
+      return UnnamedAddr::Local;
+    return UnnamedAddr::Global;
+  }
+
+  bool hasComdat() const { return getComdat() != nullptr; }
+  Comdat *getComdat();
+  const Comdat *getComdat() const {
+    return const_cast<GlobalValue *>(this)->getComdat();
+  }
+
+  VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); }
+  bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; }
+  bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; }
+  bool hasProtectedVisibility() const {
+    return Visibility == ProtectedVisibility;
+  }
+  void setVisibility(VisibilityTypes V) {
+    assert((!hasLocalLinkage() || V == DefaultVisibility) &&
+           "local linkage requires default visibility");
+    Visibility = V;
+  }
+
+  /// If the value is "Thread Local", its value isn't shared by the threads.
+  bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; }
+  void setThreadLocal(bool Val) {
+    setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal);
+  }
+  void setThreadLocalMode(ThreadLocalMode Val) {
+    assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal);
+    ThreadLocal = Val;
+  }
+  ThreadLocalMode getThreadLocalMode() const {
+    return static_cast<ThreadLocalMode>(ThreadLocal);
+  }
+
+  DLLStorageClassTypes getDLLStorageClass() const {
+    return DLLStorageClassTypes(DllStorageClass);
+  }
+  bool hasDLLImportStorageClass() const {
+    return DllStorageClass == DLLImportStorageClass;
+  }
+  bool hasDLLExportStorageClass() const {
+    return DllStorageClass == DLLExportStorageClass;
+  }
+  void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; }
+
+  bool hasSection() const { return !getSection().empty(); }
+  StringRef getSection() const;
+
+  /// Global values are always pointers.
+  PointerType *getType() const { return cast<PointerType>(User::getType()); }
+
+  Type *getValueType() const { return ValueType; }
+
+  static LinkageTypes getLinkOnceLinkage(bool ODR) {
+    return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage;
+  }
+  static LinkageTypes getWeakLinkage(bool ODR) {
+    return ODR ? WeakODRLinkage : WeakAnyLinkage;
+  }
+
+  static bool isExternalLinkage(LinkageTypes Linkage) {
+    return Linkage == ExternalLinkage;
+  }
+  static bool isAvailableExternallyLinkage(LinkageTypes Linkage) {
+    return Linkage == AvailableExternallyLinkage;
+  }
+  static bool isLinkOnceODRLinkage(LinkageTypes Linkage) {
+    return Linkage == LinkOnceODRLinkage;
+  }
+  static bool isLinkOnceLinkage(LinkageTypes Linkage) {
+    return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage;
+  }
+  static bool isWeakAnyLinkage(LinkageTypes Linkage) {
+    return Linkage == WeakAnyLinkage;
+  }
+  static bool isWeakODRLinkage(LinkageTypes Linkage) {
+    return Linkage == WeakODRLinkage;
+  }
+  static bool isWeakLinkage(LinkageTypes Linkage) {
+    return isWeakAnyLinkage(Linkage) || isWeakODRLinkage(Linkage);
+  }
+  static bool isAppendingLinkage(LinkageTypes Linkage) {
+    return Linkage == AppendingLinkage;
+  }
+  static bool isInternalLinkage(LinkageTypes Linkage) {
+    return Linkage == InternalLinkage;
+  }
+  static bool isPrivateLinkage(LinkageTypes Linkage) {
+    return Linkage == PrivateLinkage;
+  }
+  static bool isLocalLinkage(LinkageTypes Linkage) {
+    return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage);
+  }
+  static bool isExternalWeakLinkage(LinkageTypes Linkage) {
+    return Linkage == ExternalWeakLinkage;
+  }
+  static bool isCommonLinkage(LinkageTypes Linkage) {
+    return Linkage == CommonLinkage;
+  }
+  static bool isValidDeclarationLinkage(LinkageTypes Linkage) {
+    return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage);
+  }
+
+  /// Whether the definition of this global may be replaced by something
+  /// non-equivalent at link time. For example, if a function has weak linkage
+  /// then the code defining it may be replaced by different code.
+  static bool isInterposableLinkage(LinkageTypes Linkage) {
+    switch (Linkage) {
+    case WeakAnyLinkage:
+    case LinkOnceAnyLinkage:
+    case CommonLinkage:
+    case ExternalWeakLinkage:
+      return true;
+
+    case AvailableExternallyLinkage:
+    case LinkOnceODRLinkage:
+    case WeakODRLinkage:
+    // The above three cannot be overridden but can be de-refined.
+
+    case ExternalLinkage:
+    case AppendingLinkage:
+    case InternalLinkage:
+    case PrivateLinkage:
+      return false;
+    }
+    llvm_unreachable("Fully covered switch above!");
+  }
+
+  /// Whether the definition of this global may be discarded if it is not used
+  /// in its compilation unit.
+  static bool isDiscardableIfUnused(LinkageTypes Linkage) {
+    return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage) ||
+           isAvailableExternallyLinkage(Linkage);
+  }
+
+  /// Whether the definition of this global may be replaced at link time.  NB:
+  /// Using this method outside of the code generators is almost always a
+  /// mistake: when working at the IR level use isInterposable instead as it
+  /// knows about ODR semantics.
+  static bool isWeakForLinker(LinkageTypes Linkage)  {
+    return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage ||
+           Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage ||
+           Linkage == CommonLinkage || Linkage == ExternalWeakLinkage;
+  }
+
+  /// Return true if the currently visible definition of this global (if any) is
+  /// exactly the definition we will see at runtime.
+  ///
+  /// Non-exact linkage types inhibits most non-inlining IPO, since a
+  /// differently optimized variant of the same function can have different
+  /// observable or undefined behavior than in the variant currently visible.
+  /// For instance, we could have started with
+  ///
+  ///   void foo(int *v) {
+  ///     int t = 5 / v[0];
+  ///     (void) t;
+  ///   }
+  ///
+  /// and "refined" it to
+  ///
+  ///   void foo(int *v) { }
+  ///
+  /// However, we cannot infer readnone for `foo`, since that would justify
+  /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause
+  /// undefined behavior if the linker replaces the actual call destination with
+  /// the unoptimized `foo`.
+  ///
+  /// Inlining is okay across non-exact linkage types as long as they're not
+  /// interposable (see \c isInterposable), since in such cases the currently
+  /// visible variant is *a* correct implementation of the original source
+  /// function; it just isn't the *only* correct implementation.
+  bool isDefinitionExact() const {
+    return !mayBeDerefined();
+  }
+
+  /// Return true if this global has an exact defintion.
+  bool hasExactDefinition() const {
+    // While this computes exactly the same thing as
+    // isStrongDefinitionForLinker, the intended uses are different.  This
+    // function is intended to help decide if specific inter-procedural
+    // transforms are correct, while isStrongDefinitionForLinker's intended use
+    // is in low level code generation.
+    return !isDeclaration() && isDefinitionExact();
+  }
+
+  /// Return true if this global's definition can be substituted with an
+  /// *arbitrary* definition at link time.  We cannot do any IPO or inlinining
+  /// across interposable call edges, since the callee can be replaced with
+  /// something arbitrary at link time.
+  bool isInterposable() const { return isInterposableLinkage(getLinkage()); }
+
+  bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); }
+  bool hasAvailableExternallyLinkage() const {
+    return isAvailableExternallyLinkage(getLinkage());
+  }
+  bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); }
+  bool hasLinkOnceODRLinkage() const {
+    return isLinkOnceODRLinkage(getLinkage());
+  }
+  bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); }
+  bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); }
+  bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); }
+  bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); }
+  bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); }
+  bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); }
+  bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); }
+  bool hasExternalWeakLinkage() const {
+    return isExternalWeakLinkage(getLinkage());
+  }
+  bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); }
+  bool hasValidDeclarationLinkage() const {
+    return isValidDeclarationLinkage(getLinkage());
+  }
+
+  void setLinkage(LinkageTypes LT) {
+    if (isLocalLinkage(LT))
+      Visibility = DefaultVisibility;
+    Linkage = LT;
+  }
+  LinkageTypes getLinkage() const { return LinkageTypes(Linkage); }
+
+  bool isDiscardableIfUnused() const {
+    return isDiscardableIfUnused(getLinkage());
+  }
+
+  bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); }
+
+  /// Copy all additional attributes (those not needed to create a GlobalValue)
+  /// from the GlobalValue Src to this one.
+  virtual void copyAttributesFrom(const GlobalValue *Src);
+
+  /// If special LLVM prefix that is used to inform the asm printer to not emit
+  /// usual symbol prefix before the symbol name is used then return linkage
+  /// name after skipping this special LLVM prefix.
+  static StringRef getRealLinkageName(StringRef Name) {
+    if (!Name.empty() && Name[0] == '\1')
+      return Name.substr(1);
+    return Name;
+  }
+
+  /// Return the modified name for a global value suitable to be
+  /// used as the key for a global lookup (e.g. profile or ThinLTO).
+  /// The value's original name is \c Name and has linkage of type
+  /// \c Linkage. The value is defined in module \c FileName.
+  static std::string getGlobalIdentifier(StringRef Name,
+                                         GlobalValue::LinkageTypes Linkage,
+                                         StringRef FileName);
+
+  /// Return the modified name for this global value suitable to be
+  /// used as the key for a global lookup (e.g. profile or ThinLTO).
+  std::string getGlobalIdentifier() const;
+
+  /// Declare a type to represent a global unique identifier for a global value.
+  /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact
+  /// unique way to identify a symbol.
+  using GUID = uint64_t;
+
+  /// Return a 64-bit global unique ID constructed from global value name
+  /// (i.e. returned by getGlobalIdentifier()).
+  static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); }
+
+  /// Return a 64-bit global unique ID constructed from global value name
+  /// (i.e. returned by getGlobalIdentifier()).
+  GUID getGUID() const { return getGUID(getGlobalIdentifier()); }
+
+  /// @name Materialization
+  /// Materialization is used to construct functions only as they're needed.
+  /// This
+  /// is useful to reduce memory usage in LLVM or parsing work done by the
+  /// BitcodeReader to load the Module.
+  /// @{
+
+  /// If this function's Module is being lazily streamed in functions from disk
+  /// or some other source, this method can be used to check to see if the
+  /// function has been read in yet or not.
+  bool isMaterializable() const;
+
+  /// Make sure this GlobalValue is fully read. If the module is corrupt, this
+  /// returns true and fills in the optional string with information about the
+  /// problem.  If successful, this returns false.
+  std::error_code materialize();
+
+/// @}
+
+  /// Return true if the primary definition of this global value is outside of
+  /// the current translation unit.
+  bool isDeclaration() const;
+
+  bool isDeclarationForLinker() const {
+    if (hasAvailableExternallyLinkage())
+      return true;
+
+    return isDeclaration();
+  }
+
+  /// Returns true if this global's definition will be the one chosen by the
+  /// linker.
+  ///
+  /// NB! Ideally this should not be used at the IR level at all.  If you're
+  /// interested in optimization constraints implied by the linker's ability to
+  /// choose an implementation, prefer using \c hasExactDefinition.
+  bool isStrongDefinitionForLinker() const {
+    return !(isDeclarationForLinker() || isWeakForLinker());
+  }
+
+  // Returns true if the alignment of the value can be unilaterally
+  // increased.
+  bool canIncreaseAlignment() const;
+
+  /// This method unlinks 'this' from the containing module, but does not delete
+  /// it.
+  virtual void removeFromParent() = 0;
+
+  /// This method unlinks 'this' from the containing module and deletes it.
+  virtual void eraseFromParent() = 0;
+
+  /// Get the module that this global value is contained inside of...
+  Module *getParent() { return Parent; }
+  const Module *getParent() const { return Parent; }
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static bool classof(const Value *V) {
+    return V->getValueID() == Value::FunctionVal ||
+           V->getValueID() == Value::GlobalVariableVal ||
+           V->getValueID() == Value::GlobalAliasVal ||
+           V->getValueID() == Value::GlobalIFuncVal;
+  }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Instruction.def b/third_party/llvm-subzero/include/llvm/IR/Instruction.def
new file mode 100644
index 0000000..18711ab
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Instruction.def
@@ -0,0 +1,225 @@
+//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains descriptions of the various LLVM instructions.  This is
+// used as a central place for enumerating the different instructions and
+// should eventually be the place to put comments about the instructions.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+// Provide definitions of macros so that users of this file do not have to
+// define everything to use it...
+//
+#ifndef FIRST_TERM_INST
+#define FIRST_TERM_INST(num)
+#endif
+#ifndef HANDLE_TERM_INST
+#ifndef HANDLE_INST
+#define HANDLE_TERM_INST(num, opcode, Class)
+#else
+#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_TERM_INST
+#define LAST_TERM_INST(num)
+#endif
+
+#ifndef FIRST_BINARY_INST
+#define FIRST_BINARY_INST(num)
+#endif
+#ifndef HANDLE_BINARY_INST
+#ifndef HANDLE_INST
+#define HANDLE_BINARY_INST(num, opcode, instclass)
+#else
+#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_BINARY_INST
+#define LAST_BINARY_INST(num)
+#endif
+
+#ifndef FIRST_MEMORY_INST
+#define FIRST_MEMORY_INST(num)
+#endif
+#ifndef HANDLE_MEMORY_INST
+#ifndef HANDLE_INST
+#define HANDLE_MEMORY_INST(num, opcode, Class)
+#else
+#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_MEMORY_INST
+#define LAST_MEMORY_INST(num)
+#endif
+
+#ifndef FIRST_CAST_INST
+#define FIRST_CAST_INST(num)
+#endif
+#ifndef HANDLE_CAST_INST
+#ifndef HANDLE_INST
+#define HANDLE_CAST_INST(num, opcode, Class)
+#else
+#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_CAST_INST
+#define LAST_CAST_INST(num)
+#endif
+
+#ifndef FIRST_FUNCLETPAD_INST
+#define FIRST_FUNCLETPAD_INST(num)
+#endif
+#ifndef HANDLE_FUNCLETPAD_INST
+#ifndef HANDLE_INST
+#define HANDLE_FUNCLETPAD_INST(num, opcode, Class)
+#else
+#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_FUNCLETPAD_INST
+#define LAST_FUNCLETPAD_INST(num)
+#endif
+
+#ifndef FIRST_OTHER_INST
+#define FIRST_OTHER_INST(num)
+#endif
+#ifndef HANDLE_OTHER_INST
+#ifndef HANDLE_INST
+#define HANDLE_OTHER_INST(num, opcode, Class)
+#else
+#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_OTHER_INST
+#define LAST_OTHER_INST(num)
+#endif
+
+// Terminator Instructions - These instructions are used to terminate a basic
+// block of the program.   Every basic block must end with one of these
+// instructions for it to be a well formed basic block.
+//
+ FIRST_TERM_INST  ( 1)
+HANDLE_TERM_INST  ( 1, Ret           , ReturnInst)
+HANDLE_TERM_INST  ( 2, Br            , BranchInst)
+HANDLE_TERM_INST  ( 3, Switch        , SwitchInst)
+HANDLE_TERM_INST  ( 4, IndirectBr    , IndirectBrInst)
+HANDLE_TERM_INST  ( 5, Invoke        , InvokeInst)
+HANDLE_TERM_INST  ( 6, Resume        , ResumeInst)
+HANDLE_TERM_INST  ( 7, Unreachable   , UnreachableInst)
+HANDLE_TERM_INST  ( 8, CleanupRet    , CleanupReturnInst)
+HANDLE_TERM_INST  ( 9, CatchRet      , CatchReturnInst)
+HANDLE_TERM_INST  (10, CatchSwitch   , CatchSwitchInst)
+  LAST_TERM_INST  (10)
+
+// Standard binary operators...
+ FIRST_BINARY_INST(11)
+HANDLE_BINARY_INST(11, Add  , BinaryOperator)
+HANDLE_BINARY_INST(12, FAdd , BinaryOperator)
+HANDLE_BINARY_INST(13, Sub  , BinaryOperator)
+HANDLE_BINARY_INST(14, FSub , BinaryOperator)
+HANDLE_BINARY_INST(15, Mul  , BinaryOperator)
+HANDLE_BINARY_INST(16, FMul , BinaryOperator)
+HANDLE_BINARY_INST(17, UDiv , BinaryOperator)
+HANDLE_BINARY_INST(18, SDiv , BinaryOperator)
+HANDLE_BINARY_INST(19, FDiv , BinaryOperator)
+HANDLE_BINARY_INST(20, URem , BinaryOperator)
+HANDLE_BINARY_INST(21, SRem , BinaryOperator)
+HANDLE_BINARY_INST(22, FRem , BinaryOperator)
+
+// Logical operators (integer operands)
+HANDLE_BINARY_INST(23, Shl  , BinaryOperator) // Shift left  (logical)
+HANDLE_BINARY_INST(24, LShr , BinaryOperator) // Shift right (logical)
+HANDLE_BINARY_INST(25, AShr , BinaryOperator) // Shift right (arithmetic)
+HANDLE_BINARY_INST(26, And  , BinaryOperator)
+HANDLE_BINARY_INST(27, Or   , BinaryOperator)
+HANDLE_BINARY_INST(28, Xor  , BinaryOperator)
+  LAST_BINARY_INST(28)
+
+// Memory operators...
+ FIRST_MEMORY_INST(29)
+HANDLE_MEMORY_INST(29, Alloca, AllocaInst)  // Stack management
+HANDLE_MEMORY_INST(30, Load  , LoadInst  )  // Memory manipulation instrs
+HANDLE_MEMORY_INST(31, Store , StoreInst )
+HANDLE_MEMORY_INST(32, GetElementPtr, GetElementPtrInst)
+HANDLE_MEMORY_INST(33, Fence , FenceInst )
+HANDLE_MEMORY_INST(34, AtomicCmpXchg , AtomicCmpXchgInst )
+HANDLE_MEMORY_INST(35, AtomicRMW , AtomicRMWInst )
+  LAST_MEMORY_INST(35)
+
+// Cast operators ...
+// NOTE: The order matters here because CastInst::isEliminableCastPair
+// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
+ FIRST_CAST_INST(36)
+HANDLE_CAST_INST(36, Trunc   , TruncInst   )  // Truncate integers
+HANDLE_CAST_INST(37, ZExt    , ZExtInst    )  // Zero extend integers
+HANDLE_CAST_INST(38, SExt    , SExtInst    )  // Sign extend integers
+HANDLE_CAST_INST(39, FPToUI  , FPToUIInst  )  // floating point -> UInt
+HANDLE_CAST_INST(40, FPToSI  , FPToSIInst  )  // floating point -> SInt
+HANDLE_CAST_INST(41, UIToFP  , UIToFPInst  )  // UInt -> floating point
+HANDLE_CAST_INST(42, SIToFP  , SIToFPInst  )  // SInt -> floating point
+HANDLE_CAST_INST(43, FPTrunc , FPTruncInst )  // Truncate floating point
+HANDLE_CAST_INST(44, FPExt   , FPExtInst   )  // Extend floating point
+HANDLE_CAST_INST(45, PtrToInt, PtrToIntInst)  // Pointer -> Integer
+HANDLE_CAST_INST(46, IntToPtr, IntToPtrInst)  // Integer -> Pointer
+HANDLE_CAST_INST(47, BitCast , BitCastInst )  // Type cast
+HANDLE_CAST_INST(48, AddrSpaceCast, AddrSpaceCastInst)  // addrspace cast
+  LAST_CAST_INST(48)
+
+ FIRST_FUNCLETPAD_INST(49)
+HANDLE_FUNCLETPAD_INST(49, CleanupPad, CleanupPadInst)
+HANDLE_FUNCLETPAD_INST(50, CatchPad  , CatchPadInst)
+  LAST_FUNCLETPAD_INST(50)
+
+// Other operators...
+ FIRST_OTHER_INST(51)
+HANDLE_OTHER_INST(51, ICmp   , ICmpInst   )  // Integer comparison instruction
+HANDLE_OTHER_INST(52, FCmp   , FCmpInst   )  // Floating point comparison instr.
+HANDLE_OTHER_INST(53, PHI    , PHINode    )  // PHI node instruction
+HANDLE_OTHER_INST(54, Call   , CallInst   )  // Call a function
+HANDLE_OTHER_INST(55, Select , SelectInst )  // select instruction
+HANDLE_OTHER_INST(56, UserOp1, Instruction)  // May be used internally in a pass
+HANDLE_OTHER_INST(57, UserOp2, Instruction)  // Internal to passes only
+HANDLE_OTHER_INST(58, VAArg  , VAArgInst  )  // vaarg instruction
+HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
+HANDLE_OTHER_INST(60, InsertElement, InsertElementInst)  // insert into vector
+HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst)  // shuffle two vectors.
+HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate
+HANDLE_OTHER_INST(63, InsertValue, InsertValueInst)  // insert into aggregate
+HANDLE_OTHER_INST(64, LandingPad, LandingPadInst)  // Landing pad instruction.
+  LAST_OTHER_INST(64)
+
+#undef  FIRST_TERM_INST
+#undef HANDLE_TERM_INST
+#undef   LAST_TERM_INST
+
+#undef  FIRST_BINARY_INST
+#undef HANDLE_BINARY_INST
+#undef   LAST_BINARY_INST
+
+#undef  FIRST_MEMORY_INST
+#undef HANDLE_MEMORY_INST
+#undef   LAST_MEMORY_INST
+
+#undef  FIRST_CAST_INST
+#undef HANDLE_CAST_INST
+#undef   LAST_CAST_INST
+
+#undef  FIRST_FUNCLETPAD_INST
+#undef HANDLE_FUNCLETPAD_INST
+#undef   LAST_FUNCLETPAD_INST
+
+#undef  FIRST_OTHER_INST
+#undef HANDLE_OTHER_INST
+#undef   LAST_OTHER_INST
+
+#ifdef HANDLE_INST
+#undef HANDLE_INST
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Instruction.h b/third_party/llvm-subzero/include/llvm/IR/Instruction.h
new file mode 100644
index 0000000..027d9f3
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Instruction.h
@@ -0,0 +1,599 @@
+//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the Instruction class, which is the
+// base class for all of the LLVM instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_INSTRUCTION_H
+#define LLVM_IR_INSTRUCTION_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/SymbolTableListTraits.h"
+#include "llvm/IR/User.h"
+
+namespace llvm {
+
+class FastMathFlags;
+class LLVMContext;
+class MDNode;
+class BasicBlock;
+struct AAMDNodes;
+
+class Instruction : public User,
+                    public ilist_node_with_parent<Instruction, BasicBlock> {
+  void operator=(const Instruction &) = delete;
+  Instruction(const Instruction &) = delete;
+
+  BasicBlock *Parent;
+  DebugLoc DbgLoc;                         // 'dbg' Metadata cache.
+
+  enum {
+    /// This is a bit stored in the SubClassData field which indicates whether
+    /// this instruction has metadata attached to it or not.
+    HasMetadataBit = 1 << 15
+  };
+public:
+  // Out of line virtual method, so the vtable, etc has a home.
+  ~Instruction() override;
+
+  /// Specialize the methods defined in Value, as we know that an instruction
+  /// can only be used by other instructions.
+  Instruction       *user_back()       { return cast<Instruction>(*user_begin());}
+  const Instruction *user_back() const { return cast<Instruction>(*user_begin());}
+
+  inline const BasicBlock *getParent() const { return Parent; }
+  inline       BasicBlock *getParent()       { return Parent; }
+
+  /// Return the module owning the function this instruction belongs to
+  /// or nullptr it the function does not have a module.
+  ///
+  /// Note: this is undefined behavior if the instruction does not have a
+  /// parent, or the parent basic block does not have a parent function.
+  const Module *getModule() const;
+  Module *getModule();
+
+  /// Return the function this instruction belongs to.
+  ///
+  /// Note: it is undefined behavior to call this on an instruction not
+  /// currently inserted into a function.
+  const Function *getFunction() const;
+  Function *getFunction();
+
+  /// This method unlinks 'this' from the containing basic block, but does not
+  /// delete it.
+  void removeFromParent();
+
+  /// This method unlinks 'this' from the containing basic block and deletes it.
+  ///
+  /// \returns an iterator pointing to the element after the erased one
+  SymbolTableList<Instruction>::iterator eraseFromParent();
+
+  /// Insert an unlinked instruction into a basic block immediately before
+  /// the specified instruction.
+  void insertBefore(Instruction *InsertPos);
+
+  /// Insert an unlinked instruction into a basic block immediately after the
+  /// specified instruction.
+  void insertAfter(Instruction *InsertPos);
+
+  /// Unlink this instruction from its current basic block and insert it into
+  /// the basic block that MovePos lives in, right before MovePos.
+  void moveBefore(Instruction *MovePos);
+
+  /// Unlink this instruction and insert into BB before I.
+  ///
+  /// \pre I is a valid iterator into BB.
+  void moveBefore(BasicBlock &BB, SymbolTableList<Instruction>::iterator I);
+
+  //===--------------------------------------------------------------------===//
+  // Subclass classification.
+  //===--------------------------------------------------------------------===//
+
+  /// Returns a member of one of the enums like Instruction::Add.
+  unsigned getOpcode() const { return getValueID() - InstructionVal; }
+
+  const char *getOpcodeName() const { return getOpcodeName(getOpcode()); }
+  bool isTerminator() const { return isTerminator(getOpcode()); }
+  bool isBinaryOp() const { return isBinaryOp(getOpcode()); }
+  bool isShift() { return isShift(getOpcode()); }
+  bool isCast() const { return isCast(getOpcode()); }
+  bool isFuncletPad() const { return isFuncletPad(getOpcode()); }
+
+  static const char* getOpcodeName(unsigned OpCode);
+
+  static inline bool isTerminator(unsigned OpCode) {
+    return OpCode >= TermOpsBegin && OpCode < TermOpsEnd;
+  }
+
+  static inline bool isBinaryOp(unsigned Opcode) {
+    return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd;
+  }
+
+  /// Determine if the Opcode is one of the shift instructions.
+  static inline bool isShift(unsigned Opcode) {
+    return Opcode >= Shl && Opcode <= AShr;
+  }
+
+  /// Return true if this is a logical shift left or a logical shift right.
+  inline bool isLogicalShift() const {
+    return getOpcode() == Shl || getOpcode() == LShr;
+  }
+
+  /// Return true if this is an arithmetic shift right.
+  inline bool isArithmeticShift() const {
+    return getOpcode() == AShr;
+  }
+
+  /// Determine if the OpCode is one of the CastInst instructions.
+  static inline bool isCast(unsigned OpCode) {
+    return OpCode >= CastOpsBegin && OpCode < CastOpsEnd;
+  }
+
+  /// Determine if the OpCode is one of the FuncletPadInst instructions.
+  static inline bool isFuncletPad(unsigned OpCode) {
+    return OpCode >= FuncletPadOpsBegin && OpCode < FuncletPadOpsEnd;
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Metadata manipulation.
+  //===--------------------------------------------------------------------===//
+
+  /// Return true if this instruction has any metadata attached to it.
+  bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); }
+
+  /// Return true if this instruction has metadata attached to it other than a
+  /// debug location.
+  bool hasMetadataOtherThanDebugLoc() const {
+    return hasMetadataHashEntry();
+  }
+
+  /// Get the metadata of given kind attached to this Instruction.
+  /// If the metadata is not found then return null.
+  MDNode *getMetadata(unsigned KindID) const {
+    if (!hasMetadata()) return nullptr;
+    return getMetadataImpl(KindID);
+  }
+
+  /// Get the metadata of given kind attached to this Instruction.
+  /// If the metadata is not found then return null.
+  MDNode *getMetadata(StringRef Kind) const {
+    if (!hasMetadata()) return nullptr;
+    return getMetadataImpl(Kind);
+  }
+
+  /// Get all metadata attached to this Instruction. The first element of each
+  /// pair returned is the KindID, the second element is the metadata value.
+  /// This list is returned sorted by the KindID.
+  void
+  getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
+    if (hasMetadata())
+      getAllMetadataImpl(MDs);
+  }
+
+  /// This does the same thing as getAllMetadata, except that it filters out the
+  /// debug location.
+  void getAllMetadataOtherThanDebugLoc(
+      SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
+    if (hasMetadataOtherThanDebugLoc())
+      getAllMetadataOtherThanDebugLocImpl(MDs);
+  }
+
+  /// Fills the AAMDNodes structure with AA metadata from this instruction.
+  /// When Merge is true, the existing AA metadata is merged with that from this
+  /// instruction providing the most-general result.
+  void getAAMetadata(AAMDNodes &N, bool Merge = false) const;
+
+  /// Set the metadata of the specified kind to the specified node. This updates
+  /// or replaces metadata if already present, or removes it if Node is null.
+  void setMetadata(unsigned KindID, MDNode *Node);
+  void setMetadata(StringRef Kind, MDNode *Node);
+
+  /// Copy metadata from \p SrcInst to this instruction. \p WL, if not empty,
+  /// specifies the list of meta data that needs to be copied. If \p WL is
+  /// empty, all meta data will be copied.
+  void copyMetadata(const Instruction &SrcInst,
+                    ArrayRef<unsigned> WL = ArrayRef<unsigned>());
+
+  /// If the instruction has "branch_weights" MD_prof metadata and the MDNode
+  /// has three operands (including name string), swap the order of the
+  /// metadata.
+  void swapProfMetadata();
+
+  /// Drop all unknown metadata except for debug locations.
+  /// @{
+  /// Passes are required to drop metadata they don't understand. This is a
+  /// convenience method for passes to do so.
+  void dropUnknownNonDebugMetadata(ArrayRef<unsigned> KnownIDs);
+  void dropUnknownNonDebugMetadata() {
+    return dropUnknownNonDebugMetadata(None);
+  }
+  void dropUnknownNonDebugMetadata(unsigned ID1) {
+    return dropUnknownNonDebugMetadata(makeArrayRef(ID1));
+  }
+  void dropUnknownNonDebugMetadata(unsigned ID1, unsigned ID2) {
+    unsigned IDs[] = {ID1, ID2};
+    return dropUnknownNonDebugMetadata(IDs);
+  }
+  /// @}
+
+  /// Sets the metadata on this instruction from the AAMDNodes structure.
+  void setAAMetadata(const AAMDNodes &N);
+
+  /// Retrieve the raw weight values of a conditional branch or select.
+  /// Returns true on success with profile weights filled in.
+  /// Returns false if no metadata or invalid metadata was found.
+  bool extractProfMetadata(uint64_t &TrueVal, uint64_t &FalseVal);
+
+  /// Retrieve total raw weight values of a branch.
+  /// Returns true on success with profile total weights filled in.
+  /// Returns false if no metadata was found.
+  bool extractProfTotalWeight(uint64_t &TotalVal);
+
+  /// Set the debug location information for this instruction.
+  void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }
+
+  /// Return the debug location for this node as a DebugLoc.
+  const DebugLoc &getDebugLoc() const { return DbgLoc; }
+
+  /// Set or clear the nsw flag on this instruction, which must be an operator
+  /// which supports this flag. See LangRef.html for the meaning of this flag.
+  void setHasNoUnsignedWrap(bool b = true);
+
+  /// Set or clear the nsw flag on this instruction, which must be an operator
+  /// which supports this flag. See LangRef.html for the meaning of this flag.
+  void setHasNoSignedWrap(bool b = true);
+
+  /// Set or clear the exact flag on this instruction, which must be an operator
+  /// which supports this flag. See LangRef.html for the meaning of this flag.
+  void setIsExact(bool b = true);
+
+  /// Determine whether the no unsigned wrap flag is set.
+  bool hasNoUnsignedWrap() const;
+
+  /// Determine whether the no signed wrap flag is set.
+  bool hasNoSignedWrap() const;
+
+  /// Determine whether the exact flag is set.
+  bool isExact() const;
+
+  /// Set or clear the unsafe-algebra flag on this instruction, which must be an
+  /// operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasUnsafeAlgebra(bool B);
+
+  /// Set or clear the no-nans flag on this instruction, which must be an
+  /// operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasNoNaNs(bool B);
+
+  /// Set or clear the no-infs flag on this instruction, which must be an
+  /// operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasNoInfs(bool B);
+
+  /// Set or clear the no-signed-zeros flag on this instruction, which must be
+  /// an operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasNoSignedZeros(bool B);
+
+  /// Set or clear the allow-reciprocal flag on this instruction, which must be
+  /// an operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasAllowReciprocal(bool B);
+
+  /// Convenience function for setting multiple fast-math flags on this
+  /// instruction, which must be an operator which supports these flags. See
+  /// LangRef.html for the meaning of these flags.
+  void setFastMathFlags(FastMathFlags FMF);
+
+  /// Convenience function for transferring all fast-math flag values to this
+  /// instruction, which must be an operator which supports these flags. See
+  /// LangRef.html for the meaning of these flags.
+  void copyFastMathFlags(FastMathFlags FMF);
+
+  /// Determine whether the unsafe-algebra flag is set.
+  bool hasUnsafeAlgebra() const;
+
+  /// Determine whether the no-NaNs flag is set.
+  bool hasNoNaNs() const;
+
+  /// Determine whether the no-infs flag is set.
+  bool hasNoInfs() const;
+
+  /// Determine whether the no-signed-zeros flag is set.
+  bool hasNoSignedZeros() const;
+
+  /// Determine whether the allow-reciprocal flag is set.
+  bool hasAllowReciprocal() const;
+
+  /// Convenience function for getting all the fast-math flags, which must be an
+  /// operator which supports these flags. See LangRef.html for the meaning of
+  /// these flags.
+  FastMathFlags getFastMathFlags() const;
+
+  /// Copy I's fast-math flags
+  void copyFastMathFlags(const Instruction *I);
+
+  /// Convenience method to copy supported wrapping, exact, and fast-math flags
+  /// from V to this instruction.
+  void copyIRFlags(const Value *V);
+
+  /// Logical 'and' of any supported wrapping, exact, and fast-math flags of
+  /// V and this instruction.
+  void andIRFlags(const Value *V);
+
+private:
+  /// Return true if we have an entry in the on-the-side metadata hash.
+  bool hasMetadataHashEntry() const {
+    return (getSubclassDataFromValue() & HasMetadataBit) != 0;
+  }
+
+  // These are all implemented in Metadata.cpp.
+  MDNode *getMetadataImpl(unsigned KindID) const;
+  MDNode *getMetadataImpl(StringRef Kind) const;
+  void
+  getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
+  void getAllMetadataOtherThanDebugLocImpl(
+      SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
+  /// Clear all hashtable-based metadata from this instruction.
+  void clearMetadataHashEntries();
+public:
+  //===--------------------------------------------------------------------===//
+  // Predicates and helper methods.
+  //===--------------------------------------------------------------------===//
+
+
+  /// Return true if the instruction is associative:
+  ///
+  ///   Associative operators satisfy:  x op (y op z) === (x op y) op z
+  ///
+  /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative.
+  ///
+  bool isAssociative() const;
+  static bool isAssociative(unsigned op);
+
+  /// Return true if the instruction is commutative:
+  ///
+  ///   Commutative operators satisfy: (x op y) === (y op x)
+  ///
+  /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when
+  /// applied to any type.
+  ///
+  bool isCommutative() const { return isCommutative(getOpcode()); }
+  static bool isCommutative(unsigned op);
+
+  /// Return true if the instruction is idempotent:
+  ///
+  ///   Idempotent operators satisfy:  x op x === x
+  ///
+  /// In LLVM, the And and Or operators are idempotent.
+  ///
+  bool isIdempotent() const { return isIdempotent(getOpcode()); }
+  static bool isIdempotent(unsigned op);
+
+  /// Return true if the instruction is nilpotent:
+  ///
+  ///   Nilpotent operators satisfy:  x op x === Id,
+  ///
+  ///   where Id is the identity for the operator, i.e. a constant such that
+  ///     x op Id === x and Id op x === x for all x.
+  ///
+  /// In LLVM, the Xor operator is nilpotent.
+  ///
+  bool isNilpotent() const { return isNilpotent(getOpcode()); }
+  static bool isNilpotent(unsigned op);
+
+  /// Return true if this instruction may modify memory.
+  bool mayWriteToMemory() const;
+
+  /// Return true if this instruction may read memory.
+  bool mayReadFromMemory() const;
+
+  /// Return true if this instruction may read or write memory.
+  bool mayReadOrWriteMemory() const {
+    return mayReadFromMemory() || mayWriteToMemory();
+  }
+
+  /// Return true if this instruction has an AtomicOrdering of unordered or
+  /// higher.
+  bool isAtomic() const;
+
+  /// Return true if this instruction may throw an exception.
+  bool mayThrow() const;
+
+  /// Return true if this instruction behaves like a memory fence: it can load
+  /// or store to memory location without being given a memory location.
+  bool isFenceLike() const {
+    switch (getOpcode()) {
+    default:
+      return false;
+    // This list should be kept in sync with the list in mayWriteToMemory for
+    // all opcodes which don't have a memory location.
+    case Instruction::Fence:
+    case Instruction::CatchPad:
+    case Instruction::CatchRet:
+    case Instruction::Call:
+    case Instruction::Invoke:
+      return true;
+    }
+  }
+
+  /// Return true if the instruction may have side effects.
+  ///
+  /// Note that this does not consider malloc and alloca to have side
+  /// effects because the newly allocated memory is completely invisible to
+  /// instructions which don't use the returned value.  For cases where this
+  /// matters, isSafeToSpeculativelyExecute may be more appropriate.
+  bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow(); }
+
+  /// Return true if the instruction is a variety of EH-block.
+  bool isEHPad() const {
+    switch (getOpcode()) {
+    case Instruction::CatchSwitch:
+    case Instruction::CatchPad:
+    case Instruction::CleanupPad:
+    case Instruction::LandingPad:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  /// Create a copy of 'this' instruction that is identical in all ways except
+  /// the following:
+  ///   * The instruction has no parent
+  ///   * The instruction has no name
+  ///
+  Instruction *clone() const;
+
+  /// Return true if the specified instruction is exactly identical to the
+  /// current one. This means that all operands match and any extra information
+  /// (e.g. load is volatile) agree.
+  bool isIdenticalTo(const Instruction *I) const;
+
+  /// This is like isIdenticalTo, except that it ignores the
+  /// SubclassOptionalData flags, which specify conditions under which the
+  /// instruction's result is undefined.
+  bool isIdenticalToWhenDefined(const Instruction *I) const;
+
+  /// When checking for operation equivalence (using isSameOperationAs) it is
+  /// sometimes useful to ignore certain attributes.
+  enum OperationEquivalenceFlags {
+    /// Check for equivalence ignoring load/store alignment.
+    CompareIgnoringAlignment = 1<<0,
+    /// Check for equivalence treating a type and a vector of that type
+    /// as equivalent.
+    CompareUsingScalarTypes = 1<<1
+  };
+
+  /// This function determines if the specified instruction executes the same
+  /// operation as the current one. This means that the opcodes, type, operand
+  /// types and any other factors affecting the operation must be the same. This
+  /// is similar to isIdenticalTo except the operands themselves don't have to
+  /// be identical.
+  /// @returns true if the specified instruction is the same operation as
+  /// the current one.
+  /// @brief Determine if one instruction is the same operation as another.
+  bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const;
+
+  /// Return true if there are any uses of this instruction in blocks other than
+  /// the specified block. Note that PHI nodes are considered to evaluate their
+  /// operands in the corresponding predecessor block.
+  bool isUsedOutsideOfBlock(const BasicBlock *BB) const;
+
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Value *V) {
+    return V->getValueID() >= Value::InstructionVal;
+  }
+
+  //----------------------------------------------------------------------
+  // Exported enumerations.
+  //
+  enum TermOps {       // These terminate basic blocks
+#define  FIRST_TERM_INST(N)             TermOpsBegin = N,
+#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_TERM_INST(N)             TermOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+
+  enum BinaryOps {
+#define  FIRST_BINARY_INST(N)             BinaryOpsBegin = N,
+#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_BINARY_INST(N)             BinaryOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+
+  enum MemoryOps {
+#define  FIRST_MEMORY_INST(N)             MemoryOpsBegin = N,
+#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_MEMORY_INST(N)             MemoryOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+
+  enum CastOps {
+#define  FIRST_CAST_INST(N)             CastOpsBegin = N,
+#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_CAST_INST(N)             CastOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+
+  enum FuncletPadOps {
+#define  FIRST_FUNCLETPAD_INST(N)             FuncletPadOpsBegin = N,
+#define HANDLE_FUNCLETPAD_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_FUNCLETPAD_INST(N)             FuncletPadOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+
+  enum OtherOps {
+#define  FIRST_OTHER_INST(N)             OtherOpsBegin = N,
+#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_OTHER_INST(N)             OtherOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+private:
+  // Shadow Value::setValueSubclassData with a private forwarding method so that
+  // subclasses cannot accidentally use it.
+  void setValueSubclassData(unsigned short D) {
+    Value::setValueSubclassData(D);
+  }
+  unsigned short getSubclassDataFromValue() const {
+    return Value::getSubclassDataFromValue();
+  }
+
+  void setHasMetadataHashEntry(bool V) {
+    setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) |
+                         (V ? HasMetadataBit : 0));
+  }
+
+  friend class SymbolTableListTraits<Instruction>;
+  void setParent(BasicBlock *P);
+protected:
+  // Instruction subclasses can stick up to 15 bits of stuff into the
+  // SubclassData field of instruction with these members.
+
+  // Verify that only the low 15 bits are used.
+  void setInstructionSubclassData(unsigned short D) {
+    assert((D & HasMetadataBit) == 0 && "Out of range value put into field");
+    setValueSubclassData((getSubclassDataFromValue() & HasMetadataBit) | D);
+  }
+
+  unsigned getSubclassDataFromInstruction() const {
+    return getSubclassDataFromValue() & ~HasMetadataBit;
+  }
+
+  Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps,
+              Instruction *InsertBefore = nullptr);
+  Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps,
+              BasicBlock *InsertAtEnd);
+
+private:
+  /// Create a copy of this instruction.
+  Instruction *cloneImpl() const;
+};
+
+// Instruction* is only 4-byte aligned.
+template<>
+class PointerLikeTypeTraits<Instruction*> {
+  typedef Instruction* PT;
+public:
+  static inline void *getAsVoidPointer(PT P) { return P; }
+  static inline PT getFromVoidPointer(void *P) {
+    return static_cast<PT>(P);
+  }
+  enum { NumLowBitsAvailable = 2 };
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/LLVMContext.h b/third_party/llvm-subzero/include/llvm/IR/LLVMContext.h
new file mode 100644
index 0000000..dbf2b45
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/LLVMContext.h
@@ -0,0 +1,276 @@
+//===-- llvm/LLVMContext.h - Class for managing "global" state --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares LLVMContext, a container of "global" state in LLVM, such
+// as the global type and constant uniquing tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_LLVMCONTEXT_H
+#define LLVM_IR_LLVMCONTEXT_H
+
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Options.h"
+
+namespace llvm {
+
+class LLVMContextImpl;
+class StringRef;
+class Twine;
+class Instruction;
+class Module;
+class MDString;
+class DICompositeType;
+class SMDiagnostic;
+class DiagnosticInfo;
+enum DiagnosticSeverity : char;
+template <typename T> class SmallVectorImpl;
+class Function;
+class DebugLoc;
+class OptBisect;
+
+/// This is an important class for using LLVM in a threaded context.  It
+/// (opaquely) owns and manages the core "global" data of LLVM's core
+/// infrastructure, including the type and constant uniquing tables.
+/// LLVMContext itself provides no locking guarantees, so you should be careful
+/// to have one context per thread.
+class LLVMContext {
+public:
+  LLVMContextImpl *const pImpl;
+  LLVMContext();
+  ~LLVMContext();
+
+  // Pinned metadata names, which always have the same value.  This is a
+  // compile-time performance optimization, not a correctness optimization.
+  enum {
+    MD_dbg = 0,                       // "dbg"
+    MD_tbaa = 1,                      // "tbaa"
+    MD_prof = 2,                      // "prof"
+    MD_fpmath = 3,                    // "fpmath"
+    MD_range = 4,                     // "range"
+    MD_tbaa_struct = 5,               // "tbaa.struct"
+    MD_invariant_load = 6,            // "invariant.load"
+    MD_alias_scope = 7,               // "alias.scope"
+    MD_noalias = 8,                   // "noalias",
+    MD_nontemporal = 9,               // "nontemporal"
+    MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access"
+    MD_nonnull = 11,                  // "nonnull"
+    MD_dereferenceable = 12,          // "dereferenceable"
+    MD_dereferenceable_or_null = 13,  // "dereferenceable_or_null"
+    MD_make_implicit = 14,            // "make.implicit"
+    MD_unpredictable = 15,            // "unpredictable"
+    MD_invariant_group = 16,          // "invariant.group"
+    MD_align = 17,                    // "align"
+    MD_loop = 18,                     // "llvm.loop"
+    MD_type = 19,                     // "type"
+  };
+
+  /// Known operand bundle tag IDs, which always have the same value.  All
+  /// operand bundle tags that LLVM has special knowledge of are listed here.
+  /// Additionally, this scheme allows LLVM to efficiently check for specific
+  /// operand bundle tags without comparing strings.
+  enum {
+    OB_deopt = 0,         // "deopt"
+    OB_funclet = 1,       // "funclet"
+    OB_gc_transition = 2, // "gc-transition"
+  };
+
+  /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
+  /// This ID is uniqued across modules in the current LLVMContext.
+  unsigned getMDKindID(StringRef Name) const;
+
+  /// getMDKindNames - Populate client supplied SmallVector with the name for
+  /// custom metadata IDs registered in this LLVMContext.
+  void getMDKindNames(SmallVectorImpl<StringRef> &Result) const;
+
+  /// getOperandBundleTags - Populate client supplied SmallVector with the
+  /// bundle tags registered in this LLVMContext.  The bundle tags are ordered
+  /// by increasing bundle IDs.
+  /// \see LLVMContext::getOperandBundleTagID
+  void getOperandBundleTags(SmallVectorImpl<StringRef> &Result) const;
+
+  /// getOperandBundleTagID - Maps a bundle tag to an integer ID.  Every bundle
+  /// tag registered with an LLVMContext has an unique ID.
+  uint32_t getOperandBundleTagID(StringRef Tag) const;
+
+  /// Define the GC for a function
+  void setGC(const Function &Fn, std::string GCName);
+
+  /// Return the GC for a function
+  const std::string &getGC(const Function &Fn);
+
+  /// Remove the GC for a function
+  void deleteGC(const Function &Fn);
+
+  /// Return true if the Context runtime configuration is set to discard all
+  /// value names. When true, only GlobalValue names will be available in the
+  /// IR.
+  bool shouldDiscardValueNames() const;
+
+  /// Set the Context runtime configuration to discard all value name (but
+  /// GlobalValue). Clients can use this flag to save memory and runtime,
+  /// especially in release mode.
+  void setDiscardValueNames(bool Discard);
+
+  /// Whether there is a string map for uniquing debug info
+  /// identifiers across the context.  Off by default.
+  bool isODRUniquingDebugTypes() const;
+  void enableDebugTypeODRUniquing();
+  void disableDebugTypeODRUniquing();
+
+  typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
+                                         unsigned LocCookie);
+
+  /// Defines the type of a diagnostic handler.
+  /// \see LLVMContext::setDiagnosticHandler.
+  /// \see LLVMContext::diagnose.
+  typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void *Context);
+
+  /// Defines the type of a yield callback.
+  /// \see LLVMContext::setYieldCallback.
+  typedef void (*YieldCallbackTy)(LLVMContext *Context, void *OpaqueHandle);
+
+  /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked
+  /// when problems with inline asm are detected by the backend.  The first
+  /// argument is a function pointer and the second is a context pointer that
+  /// gets passed into the DiagHandler.
+  ///
+  /// LLVMContext doesn't take ownership or interpret either of these
+  /// pointers.
+  void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler,
+                                     void *DiagContext = nullptr);
+
+  /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by
+  /// setInlineAsmDiagnosticHandler.
+  InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const;
+
+  /// getInlineAsmDiagnosticContext - Return the diagnostic context set by
+  /// setInlineAsmDiagnosticHandler.
+  void *getInlineAsmDiagnosticContext() const;
+
+  /// setDiagnosticHandler - This method sets a handler that is invoked
+  /// when the backend needs to report anything to the user.  The first
+  /// argument is a function pointer and the second is a context pointer that
+  /// gets passed into the DiagHandler.  The third argument should be set to
+  /// true if the handler only expects enabled diagnostics.
+  ///
+  /// LLVMContext doesn't take ownership or interpret either of these
+  /// pointers.
+  void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,
+                            void *DiagContext = nullptr,
+                            bool RespectFilters = false);
+
+  /// getDiagnosticHandler - Return the diagnostic handler set by
+  /// setDiagnosticHandler.
+  DiagnosticHandlerTy getDiagnosticHandler() const;
+
+  /// getDiagnosticContext - Return the diagnostic context set by
+  /// setDiagnosticContext.
+  void *getDiagnosticContext() const;
+
+  /// \brief Return if a code hotness metric should be included in optimization
+  /// diagnostics.
+  bool getDiagnosticHotnessRequested() const;
+  /// \brief Set if a code hotness metric should be included in optimization
+  /// diagnostics.
+  void setDiagnosticHotnessRequested(bool Requested);
+
+  /// \brief Get the prefix that should be printed in front of a diagnostic of
+  ///        the given \p Severity
+  static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity);
+
+  /// \brief Report a message to the currently installed diagnostic handler.
+  ///
+  /// This function returns, in particular in the case of error reporting
+  /// (DI.Severity == \a DS_Error), so the caller should leave the compilation
+  /// process in a self-consistent state, even though the generated code
+  /// need not be correct.
+  ///
+  /// The diagnostic message will be implicitly prefixed with a severity keyword
+  /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error,
+  /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note.
+  void diagnose(const DiagnosticInfo &DI);
+
+  /// \brief Registers a yield callback with the given context.
+  ///
+  /// The yield callback function may be called by LLVM to transfer control back
+  /// to the client that invoked the LLVM compilation. This can be used to yield
+  /// control of the thread, or perform periodic work needed by the client.
+  /// There is no guaranteed frequency at which callbacks must occur; in fact,
+  /// the client is not guaranteed to ever receive this callback. It is at the
+  /// sole discretion of LLVM to do so and only if it can guarantee that
+  /// suspending the thread won't block any forward progress in other LLVM
+  /// contexts in the same process.
+  ///
+  /// At a suspend point, the state of the current LLVM context is intentionally
+  /// undefined. No assumptions about it can or should be made. Only LLVM
+  /// context API calls that explicitly state that they can be used during a
+  /// yield callback are allowed to be used. Any other API calls into the
+  /// context are not supported until the yield callback function returns
+  /// control to LLVM. Other LLVM contexts are unaffected by this restriction.
+  void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle);
+
+  /// \brief Calls the yield callback (if applicable).
+  ///
+  /// This transfers control of the current thread back to the client, which may
+  /// suspend the current thread. Only call this method when LLVM doesn't hold
+  /// any global mutex or cannot block the execution in another LLVM context.
+  void yield();
+
+  /// emitError - Emit an error message to the currently installed error handler
+  /// with optional location information.  This function returns, so code should
+  /// be prepared to drop the erroneous construct on the floor and "not crash".
+  /// The generated code need not be correct.  The error message will be
+  /// implicitly prefixed with "error: " and should not end with a ".".
+  void emitError(unsigned LocCookie, const Twine &ErrorStr);
+  void emitError(const Instruction *I, const Twine &ErrorStr);
+  void emitError(const Twine &ErrorStr);
+
+  /// \brief Query for a debug option's value.
+  ///
+  /// This function returns typed data populated from command line parsing.
+  template <typename ValT, typename Base, ValT(Base::*Mem)>
+  ValT getOption() const {
+    return OptionRegistry::instance().template get<ValT, Base, Mem>();
+  }
+
+  /// \brief Access the object which manages optimization bisection for failure
+  /// analysis.
+  OptBisect &getOptBisect();
+private:
+  LLVMContext(LLVMContext&) = delete;
+  void operator=(LLVMContext&) = delete;
+
+  /// addModule - Register a module as being instantiated in this context.  If
+  /// the context is deleted, the module will be deleted as well.
+  void addModule(Module*);
+
+  /// removeModule - Unregister a module from this context.
+  void removeModule(Module*);
+
+  // Module needs access to the add/removeModule methods.
+  friend class Module;
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef)
+
+/* Specialized opaque context conversions.
+ */
+inline LLVMContext **unwrap(LLVMContextRef* Tys) {
+  return reinterpret_cast<LLVMContext**>(Tys);
+}
+
+inline LLVMContextRef *wrap(const LLVMContext **Tys) {
+  return reinterpret_cast<LLVMContextRef*>(const_cast<LLVMContext**>(Tys));
+}
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Metadata.def b/third_party/llvm-subzero/include/llvm/IR/Metadata.def
new file mode 100644
index 0000000..607f5ef
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Metadata.def
@@ -0,0 +1,124 @@
+//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through all types of metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF ||               \
+      defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF ||          \
+      defined HANDLE_MDNODE_LEAF_UNIQUABLE || defined HANDLE_MDNODE_BRANCH ||  \
+      defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE ||                      \
+      defined HANDLE_SPECIALIZED_MDNODE_LEAF ||                                \
+      defined HANDLE_SPECIALIZED_MDNODE_BRANCH)
+#error "Missing macro definition of HANDLE_METADATA*"
+#endif
+
+// Handler for all types of metadata.
+#ifndef HANDLE_METADATA
+#define HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_LEAF
+#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for non-leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_BRANCH
+#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for specialized and uniquable leaf nodes under MDNode.  Defers to
+// HANDLE_MDNODE_LEAF_UNIQUABLE if it's defined, otherwise to
+// HANDLE_SPECIALIZED_MDNODE_LEAF.
+#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE
+#ifdef HANDLE_MDNODE_LEAF_UNIQUABLE
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS)                        \
+  HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)
+#else
+#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS)                        \
+  HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS)
+#endif
+#endif
+
+// Handler for leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_LEAF_UNIQUABLE
+#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#endif
+
+// Handler for leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_LEAF
+#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS)
+#endif
+
+// Handler for non-leaf nodes under MDNode.
+#ifndef HANDLE_MDNODE_BRANCH
+#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS)
+#endif
+
+// Handler for specialized leaf nodes under MDNode.
+#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF
+#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#endif
+
+// Handler for specialized non-leaf nodes under MDNode.
+#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH
+#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS)
+#endif
+
+HANDLE_METADATA_LEAF(MDString)
+HANDLE_METADATA_BRANCH(ValueAsMetadata)
+HANDLE_METADATA_LEAF(ConstantAsMetadata)
+HANDLE_METADATA_LEAF(LocalAsMetadata)
+HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder)
+HANDLE_MDNODE_BRANCH(MDNode)
+HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrange)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIEnumerator)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIBasicType)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIDerivedType)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICompositeType)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubroutineType)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFile)
+HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlock)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlockFile)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DINamespace)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIModule)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateTypeParameter)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateValueParameter)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity)
+HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
+
+#undef HANDLE_METADATA
+#undef HANDLE_METADATA_LEAF
+#undef HANDLE_METADATA_BRANCH
+#undef HANDLE_MDNODE_LEAF
+#undef HANDLE_MDNODE_LEAF_UNIQUABLE
+#undef HANDLE_MDNODE_BRANCH
+#undef HANDLE_SPECIALIZED_MDNODE_LEAF
+#undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE
+#undef HANDLE_SPECIALIZED_MDNODE_BRANCH
diff --git a/third_party/llvm-subzero/include/llvm/IR/Metadata.h b/third_party/llvm-subzero/include/llvm/IR/Metadata.h
new file mode 100644
index 0000000..0ce8882
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Metadata.h
@@ -0,0 +1,1342 @@
+//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// This file contains the declarations for metadata subclasses.
+/// They represent the different flavors of metadata that live in LLVM.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_METADATA_H
+#define LLVM_IR_METADATA_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <type_traits>
+
+namespace llvm {
+
+class LLVMContext;
+class Module;
+class ModuleSlotTracker;
+
+enum LLVMConstants : uint32_t {
+  DEBUG_METADATA_VERSION = 3 // Current debug info version number.
+};
+
+/// \brief Root of the metadata hierarchy.
+///
+/// This is a root class for typeless data in the IR.
+class Metadata {
+  friend class ReplaceableMetadataImpl;
+
+  /// \brief RTTI.
+  const unsigned char SubclassID;
+
+protected:
+  /// \brief Active type of storage.
+  enum StorageType { Uniqued, Distinct, Temporary };
+
+  /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
+  unsigned char Storage;
+  // TODO: expose remaining bits to subclasses.
+
+  unsigned short SubclassData16;
+  unsigned SubclassData32;
+
+public:
+  enum MetadataKind {
+#define HANDLE_METADATA_LEAF(CLASS) CLASS##Kind,
+#include "llvm/IR/Metadata.def"
+  };
+
+protected:
+  Metadata(unsigned ID, StorageType Storage)
+      : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) {
+    static_assert(sizeof(*this) == 8, "Metdata fields poorly packed");
+  }
+  ~Metadata() = default;
+
+  /// \brief Default handling of a changed operand, which asserts.
+  ///
+  /// If subclasses pass themselves in as owners to a tracking node reference,
+  /// they must provide an implementation of this method.
+  void handleChangedOperand(void *, Metadata *) {
+    llvm_unreachable("Unimplemented in Metadata subclass");
+  }
+
+public:
+  unsigned getMetadataID() const { return SubclassID; }
+
+  /// \brief User-friendly dump.
+  ///
+  /// If \c M is provided, metadata nodes will be numbered canonically;
+  /// otherwise, pointer addresses are substituted.
+  ///
+  /// Note: this uses an explicit overload instead of default arguments so that
+  /// the nullptr version is easy to call from a debugger.
+  ///
+  /// @{
+  void dump() const;
+  void dump(const Module *M) const;
+  /// @}
+
+  /// \brief Print.
+  ///
+  /// Prints definition of \c this.
+  ///
+  /// If \c M is provided, metadata nodes will be numbered canonically;
+  /// otherwise, pointer addresses are substituted.
+  /// @{
+  void print(raw_ostream &OS, const Module *M = nullptr,
+             bool IsForDebug = false) const;
+  void print(raw_ostream &OS, ModuleSlotTracker &MST, const Module *M = nullptr,
+             bool IsForDebug = false) const;
+  /// @}
+
+  /// \brief Print as operand.
+  ///
+  /// Prints reference of \c this.
+  ///
+  /// If \c M is provided, metadata nodes will be numbered canonically;
+  /// otherwise, pointer addresses are substituted.
+  /// @{
+  void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const;
+  void printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST,
+                      const Module *M = nullptr) const;
+  /// @}
+};
+
+#define HANDLE_METADATA(CLASS) class CLASS;
+#include "llvm/IR/Metadata.def"
+
+// Provide specializations of isa so that we don't need definitions of
+// subclasses to see if the metadata is a subclass.
+#define HANDLE_METADATA_LEAF(CLASS)                                            \
+  template <> struct isa_impl<CLASS, Metadata> {                               \
+    static inline bool doit(const Metadata &MD) {                              \
+      return MD.getMetadataID() == Metadata::CLASS##Kind;                      \
+    }                                                                          \
+  };
+#include "llvm/IR/Metadata.def"
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) {
+  MD.print(OS);
+  return OS;
+}
+
+/// \brief Metadata wrapper in the Value hierarchy.
+///
+/// A member of the \a Value hierarchy to represent a reference to metadata.
+/// This allows, e.g., instrinsics to have metadata as operands.
+///
+/// Notably, this is the only thing in either hierarchy that is allowed to
+/// reference \a LocalAsMetadata.
+class MetadataAsValue : public Value {
+  friend class ReplaceableMetadataImpl;
+  friend class LLVMContextImpl;
+
+  Metadata *MD;
+
+  MetadataAsValue(Type *Ty, Metadata *MD);
+  ~MetadataAsValue() override;
+
+  /// \brief Drop use of metadata (during teardown).
+  void dropUse() { MD = nullptr; }
+
+public:
+  static MetadataAsValue *get(LLVMContext &Context, Metadata *MD);
+  static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD);
+  Metadata *getMetadata() const { return MD; }
+
+  static bool classof(const Value *V) {
+    return V->getValueID() == MetadataAsValueVal;
+  }
+
+private:
+  void handleChangedMetadata(Metadata *MD);
+  void track();
+  void untrack();
+};
+
+/// \brief API for tracking metadata references through RAUW and deletion.
+///
+/// Shared API for updating \a Metadata pointers in subclasses that support
+/// RAUW.
+///
+/// This API is not meant to be used directly.  See \a TrackingMDRef for a
+/// user-friendly tracking reference.
+class MetadataTracking {
+public:
+  /// \brief Track the reference to metadata.
+  ///
+  /// Register \c MD with \c *MD, if the subclass supports tracking.  If \c *MD
+  /// gets RAUW'ed, \c MD will be updated to the new address.  If \c *MD gets
+  /// deleted, \c MD will be set to \c nullptr.
+  ///
+  /// If tracking isn't supported, \c *MD will not change.
+  ///
+  /// \return true iff tracking is supported by \c MD.
+  static bool track(Metadata *&MD) {
+    return track(&MD, *MD, static_cast<Metadata *>(nullptr));
+  }
+
+  /// \brief Track the reference to metadata for \a Metadata.
+  ///
+  /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+  /// tell it that its operand changed.  This could trigger \c Owner being
+  /// re-uniqued.
+  static bool track(void *Ref, Metadata &MD, Metadata &Owner) {
+    return track(Ref, MD, &Owner);
+  }
+
+  /// \brief Track the reference to metadata for \a MetadataAsValue.
+  ///
+  /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+  /// tell it that its operand changed.  This could trigger \c Owner being
+  /// re-uniqued.
+  static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) {
+    return track(Ref, MD, &Owner);
+  }
+
+  /// \brief Stop tracking a reference to metadata.
+  ///
+  /// Stops \c *MD from tracking \c MD.
+  static void untrack(Metadata *&MD) { untrack(&MD, *MD); }
+  static void untrack(void *Ref, Metadata &MD);
+
+  /// \brief Move tracking from one reference to another.
+  ///
+  /// Semantically equivalent to \c untrack(MD) followed by \c track(New),
+  /// except that ownership callbacks are maintained.
+  ///
+  /// Note: it is an error if \c *MD does not equal \c New.
+  ///
+  /// \return true iff tracking is supported by \c MD.
+  static bool retrack(Metadata *&MD, Metadata *&New) {
+    return retrack(&MD, *MD, &New);
+  }
+  static bool retrack(void *Ref, Metadata &MD, void *New);
+
+  /// \brief Check whether metadata is replaceable.
+  static bool isReplaceable(const Metadata &MD);
+
+  typedef PointerUnion<MetadataAsValue *, Metadata *> OwnerTy;
+
+private:
+  /// \brief Track a reference to metadata for an owner.
+  ///
+  /// Generalized version of tracking.
+  static bool track(void *Ref, Metadata &MD, OwnerTy Owner);
+};
+
+/// \brief Shared implementation of use-lists for replaceable metadata.
+///
+/// Most metadata cannot be RAUW'ed.  This is a shared implementation of
+/// use-lists and associated API for the two that support it (\a ValueAsMetadata
+/// and \a TempMDNode).
+class ReplaceableMetadataImpl {
+  friend class MetadataTracking;
+
+public:
+  typedef MetadataTracking::OwnerTy OwnerTy;
+
+private:
+  LLVMContext &Context;
+  uint64_t NextIndex;
+  SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
+
+public:
+  ReplaceableMetadataImpl(LLVMContext &Context)
+      : Context(Context), NextIndex(0) {}
+  ~ReplaceableMetadataImpl() {
+    assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
+  }
+
+  LLVMContext &getContext() const { return Context; }
+
+  /// \brief Replace all uses of this with MD.
+  ///
+  /// Replace all uses of this with \c MD, which is allowed to be null.
+  void replaceAllUsesWith(Metadata *MD);
+
+  /// \brief Resolve all uses of this.
+  ///
+  /// Resolve all uses of this, turning off RAUW permanently.  If \c
+  /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand
+  /// is resolved.
+  void resolveAllUses(bool ResolveUsers = true);
+
+private:
+  void addRef(void *Ref, OwnerTy Owner);
+  void dropRef(void *Ref);
+  void moveRef(void *Ref, void *New, const Metadata &MD);
+
+  /// Lazily construct RAUW support on MD.
+  ///
+  /// If this is an unresolved MDNode, RAUW support will be created on-demand.
+  /// ValueAsMetadata always has RAUW support.
+  static ReplaceableMetadataImpl *getOrCreate(Metadata &MD);
+
+  /// Get RAUW support on MD, if it exists.
+  static ReplaceableMetadataImpl *getIfExists(Metadata &MD);
+
+  /// Check whether this node will support RAUW.
+  ///
+  /// Returns \c true unless getOrCreate() would return null.
+  static bool isReplaceable(const Metadata &MD);
+};
+
+/// \brief Value wrapper in the Metadata hierarchy.
+///
+/// This is a custom value handle that allows other metadata to refer to
+/// classes in the Value hierarchy.
+///
+/// Because of full uniquing support, each value is only wrapped by a single \a
+/// ValueAsMetadata object, so the lookup maps are far more efficient than
+/// those using ValueHandleBase.
+class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
+  friend class ReplaceableMetadataImpl;
+  friend class LLVMContextImpl;
+
+  Value *V;
+
+  /// \brief Drop users without RAUW (during teardown).
+  void dropUsers() {
+    ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);
+  }
+
+protected:
+  ValueAsMetadata(unsigned ID, Value *V)
+      : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) {
+    assert(V && "Expected valid value");
+  }
+  ~ValueAsMetadata() = default;
+
+public:
+  static ValueAsMetadata *get(Value *V);
+  static ConstantAsMetadata *getConstant(Value *C) {
+    return cast<ConstantAsMetadata>(get(C));
+  }
+  static LocalAsMetadata *getLocal(Value *Local) {
+    return cast<LocalAsMetadata>(get(Local));
+  }
+
+  static ValueAsMetadata *getIfExists(Value *V);
+  static ConstantAsMetadata *getConstantIfExists(Value *C) {
+    return cast_or_null<ConstantAsMetadata>(getIfExists(C));
+  }
+  static LocalAsMetadata *getLocalIfExists(Value *Local) {
+    return cast_or_null<LocalAsMetadata>(getIfExists(Local));
+  }
+
+  Value *getValue() const { return V; }
+  Type *getType() const { return V->getType(); }
+  LLVMContext &getContext() const { return V->getContext(); }
+
+  static void handleDeletion(Value *V);
+  static void handleRAUW(Value *From, Value *To);
+
+protected:
+  /// \brief Handle collisions after \a Value::replaceAllUsesWith().
+  ///
+  /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped
+  /// \a Value gets RAUW'ed and the target already exists, this is used to
+  /// merge the two metadata nodes.
+  void replaceAllUsesWith(Metadata *MD) {
+    ReplaceableMetadataImpl::replaceAllUsesWith(MD);
+  }
+
+public:
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == LocalAsMetadataKind ||
+           MD->getMetadataID() == ConstantAsMetadataKind;
+  }
+};
+
+class ConstantAsMetadata : public ValueAsMetadata {
+  friend class ValueAsMetadata;
+
+  ConstantAsMetadata(Constant *C)
+      : ValueAsMetadata(ConstantAsMetadataKind, C) {}
+
+public:
+  static ConstantAsMetadata *get(Constant *C) {
+    return ValueAsMetadata::getConstant(C);
+  }
+  static ConstantAsMetadata *getIfExists(Constant *C) {
+    return ValueAsMetadata::getConstantIfExists(C);
+  }
+
+  Constant *getValue() const {
+    return cast<Constant>(ValueAsMetadata::getValue());
+  }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == ConstantAsMetadataKind;
+  }
+};
+
+class LocalAsMetadata : public ValueAsMetadata {
+  friend class ValueAsMetadata;
+
+  LocalAsMetadata(Value *Local)
+      : ValueAsMetadata(LocalAsMetadataKind, Local) {
+    assert(!isa<Constant>(Local) && "Expected local value");
+  }
+
+public:
+  static LocalAsMetadata *get(Value *Local) {
+    return ValueAsMetadata::getLocal(Local);
+  }
+  static LocalAsMetadata *getIfExists(Value *Local) {
+    return ValueAsMetadata::getLocalIfExists(Local);
+  }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == LocalAsMetadataKind;
+  }
+};
+
+/// \brief Transitional API for extracting constants from Metadata.
+///
+/// This namespace contains transitional functions for metadata that points to
+/// \a Constants.
+///
+/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode
+/// operands could refer to any \a Value.  There's was a lot of code like this:
+///
+/// \code
+///     MDNode *N = ...;
+///     auto *CI = dyn_cast<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining
+/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three
+/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and
+/// cast in the \a Value hierarchy.  Besides creating boiler-plate, this
+/// requires subtle control flow changes.
+///
+/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt,
+/// so that metadata can refer to numbers without traversing a bridge to the \a
+/// Value hierarchy.  In this final state, the code above would look like this:
+///
+/// \code
+///     MDNode *N = ...;
+///     auto *MI = dyn_cast<MDInt>(N->getOperand(2));
+/// \endcode
+///
+/// The API in this namespace supports the transition.  \a MDInt doesn't exist
+/// yet, and even once it does, changing each metadata schema to use it is its
+/// own mini-project.  In the meantime this API prevents us from introducing
+/// complex and bug-prone control flow that will disappear in the end.  In
+/// particular, the above code looks like this:
+///
+/// \code
+///     MDNode *N = ...;
+///     auto *CI = mdconst::dyn_extract<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// The full set of provided functions includes:
+///
+///   mdconst::hasa                <=> isa
+///   mdconst::extract             <=> cast
+///   mdconst::extract_or_null     <=> cast_or_null
+///   mdconst::dyn_extract         <=> dyn_cast
+///   mdconst::dyn_extract_or_null <=> dyn_cast_or_null
+///
+/// The target of the cast must be a subclass of \a Constant.
+namespace mdconst {
+
+namespace detail {
+template <class T> T &make();
+template <class T, class Result> struct HasDereference {
+  typedef char Yes[1];
+  typedef char No[2];
+  template <size_t N> struct SFINAE {};
+
+  template <class U, class V>
+  static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0);
+  template <class U, class V> static No &hasDereference(...);
+
+  static const bool value =
+      sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes);
+};
+template <class V, class M> struct IsValidPointer {
+  static const bool value = std::is_base_of<Constant, V>::value &&
+                            HasDereference<M, const Metadata &>::value;
+};
+template <class V, class M> struct IsValidReference {
+  static const bool value = std::is_base_of<Constant, V>::value &&
+                            std::is_convertible<M, const Metadata &>::value;
+};
+} // end namespace detail
+
+/// \brief Check whether Metadata has a Value.
+///
+/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of
+/// type \c X.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type
+hasa(Y &&MD) {
+  assert(MD && "Null pointer sent into hasa");
+  if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+    return isa<X>(V->getValue());
+  return false;
+}
+template <class X, class Y>
+inline
+    typename std::enable_if<detail::IsValidReference<X, Y &>::value, bool>::type
+    hasa(Y &MD) {
+  return hasa(&MD);
+}
+
+/// \brief Extract a Value from Metadata.
+///
+/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract(Y &&MD) {
+  return cast<X>(cast<ConstantAsMetadata>(MD)->getValue());
+}
+template <class X, class Y>
+inline
+    typename std::enable_if<detail::IsValidReference<X, Y &>::value, X *>::type
+    extract(Y &MD) {
+  return extract(&MD);
+}
+
+/// \brief Extract a Value from Metadata, allowing null.
+///
+/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract_or_null(Y &&MD) {
+  if (auto *V = cast_or_null<ConstantAsMetadata>(MD))
+    return cast<X>(V->getValue());
+  return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract(Y &&MD) {
+  if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+    return dyn_cast<X>(V->getValue());
+  return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any, allowing null.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract_or_null(Y &&MD) {
+  if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD))
+    return dyn_cast<X>(V->getValue());
+  return nullptr;
+}
+
+} // end namespace mdconst
+
+//===----------------------------------------------------------------------===//
+/// \brief A single uniqued string.
+///
+/// These are used to efficiently contain a byte sequence for metadata.
+/// MDString is always unnamed.
+class MDString : public Metadata {
+  friend class StringMapEntry<MDString>;
+
+  MDString(const MDString &) = delete;
+  MDString &operator=(MDString &&) = delete;
+  MDString &operator=(const MDString &) = delete;
+
+  StringMapEntry<MDString> *Entry;
+  MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {}
+
+public:
+  static MDString *get(LLVMContext &Context, StringRef Str);
+  static MDString *get(LLVMContext &Context, const char *Str) {
+    return get(Context, Str ? StringRef(Str) : StringRef());
+  }
+
+  StringRef getString() const;
+
+  unsigned getLength() const { return (unsigned)getString().size(); }
+
+  typedef StringRef::iterator iterator;
+
+  /// \brief Pointer to the first byte of the string.
+  iterator begin() const { return getString().begin(); }
+
+  /// \brief Pointer to one byte past the end of the string.
+  iterator end() const { return getString().end(); }
+
+  const unsigned char *bytes_begin() const { return getString().bytes_begin(); }
+  const unsigned char *bytes_end() const { return getString().bytes_end(); }
+
+  /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDStringKind;
+  }
+};
+
+/// \brief A collection of metadata nodes that might be associated with a
+/// memory access used by the alias-analysis infrastructure.
+struct AAMDNodes {
+  explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr,
+                     MDNode *N = nullptr)
+      : TBAA(T), Scope(S), NoAlias(N) {}
+
+  bool operator==(const AAMDNodes &A) const {
+    return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias;
+  }
+
+  bool operator!=(const AAMDNodes &A) const { return !(*this == A); }
+
+  explicit operator bool() const { return TBAA || Scope || NoAlias; }
+
+  /// \brief The tag for type-based alias analysis.
+  MDNode *TBAA;
+
+  /// \brief The tag for alias scope specification (used with noalias).
+  MDNode *Scope;
+
+  /// \brief The tag specifying the noalias scope.
+  MDNode *NoAlias;
+};
+
+// Specialize DenseMapInfo for AAMDNodes.
+template<>
+struct DenseMapInfo<AAMDNodes> {
+  static inline AAMDNodes getEmptyKey() {
+    return AAMDNodes(DenseMapInfo<MDNode *>::getEmptyKey(),
+                     nullptr, nullptr);
+  }
+  static inline AAMDNodes getTombstoneKey() {
+    return AAMDNodes(DenseMapInfo<MDNode *>::getTombstoneKey(),
+                     nullptr, nullptr);
+  }
+  static unsigned getHashValue(const AAMDNodes &Val) {
+    return DenseMapInfo<MDNode *>::getHashValue(Val.TBAA) ^
+           DenseMapInfo<MDNode *>::getHashValue(Val.Scope) ^
+           DenseMapInfo<MDNode *>::getHashValue(Val.NoAlias);
+  }
+  static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) {
+    return LHS == RHS;
+  }
+};
+
+/// \brief Tracking metadata reference owned by Metadata.
+///
+/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance
+/// of \a Metadata, which has the option of registering itself for callbacks to
+/// re-unique itself.
+///
+/// In particular, this is used by \a MDNode.
+class MDOperand {
+  MDOperand(MDOperand &&) = delete;
+  MDOperand(const MDOperand &) = delete;
+  MDOperand &operator=(MDOperand &&) = delete;
+  MDOperand &operator=(const MDOperand &) = delete;
+
+  Metadata *MD;
+
+public:
+  MDOperand() : MD(nullptr) {}
+  ~MDOperand() { untrack(); }
+
+  Metadata *get() const { return MD; }
+  operator Metadata *() const { return get(); }
+  Metadata *operator->() const { return get(); }
+  Metadata &operator*() const { return *get(); }
+
+  void reset() {
+    untrack();
+    MD = nullptr;
+  }
+  void reset(Metadata *MD, Metadata *Owner) {
+    untrack();
+    this->MD = MD;
+    track(Owner);
+  }
+
+private:
+  void track(Metadata *Owner) {
+    if (MD) {
+      if (Owner)
+        MetadataTracking::track(this, *MD, *Owner);
+      else
+        MetadataTracking::track(MD);
+    }
+  }
+  void untrack() {
+    assert(static_cast<void *>(this) == &MD && "Expected same address");
+    if (MD)
+      MetadataTracking::untrack(MD);
+  }
+};
+
+template <> struct simplify_type<MDOperand> {
+  typedef Metadata *SimpleType;
+  static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const MDOperand> {
+  typedef Metadata *SimpleType;
+  static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
+};
+
+/// \brief Pointer to the context, with optional RAUW support.
+///
+/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer
+/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext).
+class ContextAndReplaceableUses {
+  PointerUnion<LLVMContext *, ReplaceableMetadataImpl *> Ptr;
+
+  ContextAndReplaceableUses() = delete;
+  ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete;
+  ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete;
+  ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete;
+  ContextAndReplaceableUses &
+  operator=(const ContextAndReplaceableUses &) = delete;
+
+public:
+  ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {}
+  ContextAndReplaceableUses(
+      std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses)
+      : Ptr(ReplaceableUses.release()) {
+    assert(getReplaceableUses() && "Expected non-null replaceable uses");
+  }
+  ~ContextAndReplaceableUses() { delete getReplaceableUses(); }
+
+  operator LLVMContext &() { return getContext(); }
+
+  /// \brief Whether this contains RAUW support.
+  bool hasReplaceableUses() const {
+    return Ptr.is<ReplaceableMetadataImpl *>();
+  }
+  LLVMContext &getContext() const {
+    if (hasReplaceableUses())
+      return getReplaceableUses()->getContext();
+    return *Ptr.get<LLVMContext *>();
+  }
+  ReplaceableMetadataImpl *getReplaceableUses() const {
+    if (hasReplaceableUses())
+      return Ptr.get<ReplaceableMetadataImpl *>();
+    return nullptr;
+  }
+
+  /// Ensure that this has RAUW support, and then return it.
+  ReplaceableMetadataImpl *getOrCreateReplaceableUses() {
+    if (!hasReplaceableUses())
+      makeReplaceable(llvm::make_unique<ReplaceableMetadataImpl>(getContext()));
+    return getReplaceableUses();
+  }
+
+  /// \brief Assign RAUW support to this.
+  ///
+  /// Make this replaceable, taking ownership of \c ReplaceableUses (which must
+  /// not be null).
+  void
+  makeReplaceable(std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) {
+    assert(ReplaceableUses && "Expected non-null replaceable uses");
+    assert(&ReplaceableUses->getContext() == &getContext() &&
+           "Expected same context");
+    delete getReplaceableUses();
+    Ptr = ReplaceableUses.release();
+  }
+
+  /// \brief Drop RAUW support.
+  ///
+  /// Cede ownership of RAUW support, returning it.
+  std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() {
+    assert(hasReplaceableUses() && "Expected to own replaceable uses");
+    std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses(
+        getReplaceableUses());
+    Ptr = &ReplaceableUses->getContext();
+    return ReplaceableUses;
+  }
+};
+
+struct TempMDNodeDeleter {
+  inline void operator()(MDNode *Node) const;
+};
+
+#define HANDLE_MDNODE_LEAF(CLASS)                                              \
+  typedef std::unique_ptr<CLASS, TempMDNodeDeleter> Temp##CLASS;
+#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS)
+#include "llvm/IR/Metadata.def"
+
+/// \brief Metadata node.
+///
+/// Metadata nodes can be uniqued, like constants, or distinct.  Temporary
+/// metadata nodes (with full support for RAUW) can be used to delay uniquing
+/// until forward references are known.  The basic metadata node is an \a
+/// MDTuple.
+///
+/// There is limited support for RAUW at construction time.  At construction
+/// time, if any operand is a temporary node (or an unresolved uniqued node,
+/// which indicates a transitive temporary operand), the node itself will be
+/// unresolved.  As soon as all operands become resolved, it will drop RAUW
+/// support permanently.
+///
+/// If an unresolved node is part of a cycle, \a resolveCycles() needs
+/// to be called on some member of the cycle once all temporary nodes have been
+/// replaced.
+class MDNode : public Metadata {
+  friend class ReplaceableMetadataImpl;
+  friend class LLVMContextImpl;
+
+  MDNode(const MDNode &) = delete;
+  void operator=(const MDNode &) = delete;
+  void *operator new(size_t) = delete;
+
+  unsigned NumOperands;
+  unsigned NumUnresolved;
+
+  ContextAndReplaceableUses Context;
+
+protected:
+  void *operator new(size_t Size, unsigned NumOps);
+  void operator delete(void *Mem);
+
+  /// \brief Required by std, but never called.
+  void operator delete(void *, unsigned) {
+    llvm_unreachable("Constructor throws?");
+  }
+
+  /// \brief Required by std, but never called.
+  void operator delete(void *, unsigned, bool) {
+    llvm_unreachable("Constructor throws?");
+  }
+
+  MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
+         ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None);
+  ~MDNode() = default;
+
+  void dropAllReferences();
+
+  MDOperand *mutable_begin() { return mutable_end() - NumOperands; }
+  MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); }
+
+  typedef iterator_range<MDOperand *> mutable_op_range;
+  mutable_op_range mutable_operands() {
+    return mutable_op_range(mutable_begin(), mutable_end());
+  }
+
+public:
+  static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+  static inline MDTuple *getIfExists(LLVMContext &Context,
+                                     ArrayRef<Metadata *> MDs);
+  static inline MDTuple *getDistinct(LLVMContext &Context,
+                                     ArrayRef<Metadata *> MDs);
+  static inline TempMDTuple getTemporary(LLVMContext &Context,
+                                         ArrayRef<Metadata *> MDs);
+
+  /// \brief Create a (temporary) clone of this.
+  TempMDNode clone() const;
+
+  /// \brief Deallocate a node created by getTemporary.
+  ///
+  /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining
+  /// references will be reset.
+  static void deleteTemporary(MDNode *N);
+
+  LLVMContext &getContext() const { return Context.getContext(); }
+
+  /// \brief Replace a specific operand.
+  void replaceOperandWith(unsigned I, Metadata *New);
+
+  /// \brief Check if node is fully resolved.
+  ///
+  /// If \a isTemporary(), this always returns \c false; if \a isDistinct(),
+  /// this always returns \c true.
+  ///
+  /// If \a isUniqued(), returns \c true if this has already dropped RAUW
+  /// support (because all operands are resolved).
+  ///
+  /// As forward declarations are resolved, their containers should get
+  /// resolved automatically.  However, if this (or one of its operands) is
+  /// involved in a cycle, \a resolveCycles() needs to be called explicitly.
+  bool isResolved() const { return !isTemporary() && !NumUnresolved; }
+
+  bool isUniqued() const { return Storage == Uniqued; }
+  bool isDistinct() const { return Storage == Distinct; }
+  bool isTemporary() const { return Storage == Temporary; }
+
+  /// \brief RAUW a temporary.
+  ///
+  /// \pre \a isTemporary() must be \c true.
+  void replaceAllUsesWith(Metadata *MD) {
+    assert(isTemporary() && "Expected temporary node");
+    if (Context.hasReplaceableUses())
+      Context.getReplaceableUses()->replaceAllUsesWith(MD);
+  }
+
+  /// \brief Resolve cycles.
+  ///
+  /// Once all forward declarations have been resolved, force cycles to be
+  /// resolved.
+  ///
+  /// \pre No operands (or operands' operands, etc.) have \a isTemporary().
+  void resolveCycles();
+
+  /// \brief Replace a temporary node with a permanent one.
+  ///
+  /// Try to create a uniqued version of \c N -- in place, if possible -- and
+  /// return it.  If \c N cannot be uniqued, return a distinct node instead.
+  template <class T>
+  static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+  replaceWithPermanent(std::unique_ptr<T, TempMDNodeDeleter> N) {
+    return cast<T>(N.release()->replaceWithPermanentImpl());
+  }
+
+  /// \brief Replace a temporary node with a uniqued one.
+  ///
+  /// Create a uniqued version of \c N -- in place, if possible -- and return
+  /// it.  Takes ownership of the temporary node.
+  ///
+  /// \pre N does not self-reference.
+  template <class T>
+  static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+  replaceWithUniqued(std::unique_ptr<T, TempMDNodeDeleter> N) {
+    return cast<T>(N.release()->replaceWithUniquedImpl());
+  }
+
+  /// \brief Replace a temporary node with a distinct one.
+  ///
+  /// Create a distinct version of \c N -- in place, if possible -- and return
+  /// it.  Takes ownership of the temporary node.
+  template <class T>
+  static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+  replaceWithDistinct(std::unique_ptr<T, TempMDNodeDeleter> N) {
+    return cast<T>(N.release()->replaceWithDistinctImpl());
+  }
+
+private:
+  MDNode *replaceWithPermanentImpl();
+  MDNode *replaceWithUniquedImpl();
+  MDNode *replaceWithDistinctImpl();
+
+protected:
+  /// \brief Set an operand.
+  ///
+  /// Sets the operand directly, without worrying about uniquing.
+  void setOperand(unsigned I, Metadata *New);
+
+  void storeDistinctInContext();
+  template <class T, class StoreT>
+  static T *storeImpl(T *N, StorageType Storage, StoreT &Store);
+  template <class T> static T *storeImpl(T *N, StorageType Storage);
+
+private:
+  void handleChangedOperand(void *Ref, Metadata *New);
+
+  /// Resolve a unique, unresolved node.
+  void resolve();
+
+  /// Drop RAUW support, if any.
+  void dropReplaceableUses();
+
+  void resolveAfterOperandChange(Metadata *Old, Metadata *New);
+  void decrementUnresolvedOperandCount();
+  void countUnresolvedOperands();
+
+  /// \brief Mutate this to be "uniqued".
+  ///
+  /// Mutate this so that \a isUniqued().
+  /// \pre \a isTemporary().
+  /// \pre already added to uniquing set.
+  void makeUniqued();
+
+  /// \brief Mutate this to be "distinct".
+  ///
+  /// Mutate this so that \a isDistinct().
+  /// \pre \a isTemporary().
+  void makeDistinct();
+
+  void deleteAsSubclass();
+  MDNode *uniquify();
+  void eraseFromStore();
+
+  template <class NodeTy> struct HasCachedHash;
+  template <class NodeTy>
+  static void dispatchRecalculateHash(NodeTy *N, std::true_type) {
+    N->recalculateHash();
+  }
+  template <class NodeTy>
+  static void dispatchRecalculateHash(NodeTy *, std::false_type) {}
+  template <class NodeTy>
+  static void dispatchResetHash(NodeTy *N, std::true_type) {
+    N->setHash(0);
+  }
+  template <class NodeTy>
+  static void dispatchResetHash(NodeTy *, std::false_type) {}
+
+public:
+  typedef const MDOperand *op_iterator;
+  typedef iterator_range<op_iterator> op_range;
+
+  op_iterator op_begin() const {
+    return const_cast<MDNode *>(this)->mutable_begin();
+  }
+  op_iterator op_end() const {
+    return const_cast<MDNode *>(this)->mutable_end();
+  }
+  op_range operands() const { return op_range(op_begin(), op_end()); }
+
+  const MDOperand &getOperand(unsigned I) const {
+    assert(I < NumOperands && "Out of range");
+    return op_begin()[I];
+  }
+
+  /// \brief Return number of MDNode operands.
+  unsigned getNumOperands() const { return NumOperands; }
+
+  /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
+  static bool classof(const Metadata *MD) {
+    switch (MD->getMetadataID()) {
+    default:
+      return false;
+#define HANDLE_MDNODE_LEAF(CLASS)                                              \
+  case CLASS##Kind:                                                            \
+    return true;
+#include "llvm/IR/Metadata.def"
+    }
+  }
+
+  /// \brief Check whether MDNode is a vtable access.
+  bool isTBAAVtableAccess() const;
+
+  /// \brief Methods for metadata merging.
+  static MDNode *concatenate(MDNode *A, MDNode *B);
+  static MDNode *intersect(MDNode *A, MDNode *B);
+  static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B);
+  static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
+  static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
+  static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B);
+  static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B);
+
+};
+
+/// \brief Tuple of metadata.
+///
+/// This is the simple \a MDNode arbitrary tuple.  Nodes are uniqued by
+/// default based on their operands.
+class MDTuple : public MDNode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash,
+          ArrayRef<Metadata *> Vals)
+      : MDNode(C, MDTupleKind, Storage, Vals) {
+    setHash(Hash);
+  }
+  ~MDTuple() { dropAllReferences(); }
+
+  void setHash(unsigned Hash) { SubclassData32 = Hash; }
+  void recalculateHash();
+
+  static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+                          StorageType Storage, bool ShouldCreate = true);
+
+  TempMDTuple cloneImpl() const {
+    return getTemporary(getContext(),
+                        SmallVector<Metadata *, 4>(op_begin(), op_end()));
+  }
+
+public:
+  /// \brief Get the hash, if any.
+  unsigned getHash() const { return SubclassData32; }
+
+  static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+    return getImpl(Context, MDs, Uniqued);
+  }
+  static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+    return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false);
+  }
+
+  /// \brief Return a distinct node.
+  ///
+  /// Return a distinct node -- i.e., a node that is not uniqued.
+  static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+    return getImpl(Context, MDs, Distinct);
+  }
+
+  /// \brief Return a temporary node.
+  ///
+  /// For use in constructing cyclic MDNode structures. A temporary MDNode is
+  /// not uniqued, may be RAUW'd, and must be manually deleted with
+  /// deleteTemporary.
+  static TempMDTuple getTemporary(LLVMContext &Context,
+                                  ArrayRef<Metadata *> MDs) {
+    return TempMDTuple(getImpl(Context, MDs, Temporary));
+  }
+
+  /// \brief Return a (temporary) clone of this.
+  TempMDTuple clone() const { return cloneImpl(); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == MDTupleKind;
+  }
+};
+
+MDTuple *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+  return MDTuple::get(Context, MDs);
+}
+MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+  return MDTuple::getIfExists(Context, MDs);
+}
+MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+  return MDTuple::getDistinct(Context, MDs);
+}
+TempMDTuple MDNode::getTemporary(LLVMContext &Context,
+                                 ArrayRef<Metadata *> MDs) {
+  return MDTuple::getTemporary(Context, MDs);
+}
+
+void TempMDNodeDeleter::operator()(MDNode *Node) const {
+  MDNode::deleteTemporary(Node);
+}
+
+/// \brief Typed iterator through MDNode operands.
+///
+/// An iterator that transforms an \a MDNode::iterator into an iterator over a
+/// particular Metadata subclass.
+template <class T>
+class TypedMDOperandIterator
+    : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> {
+  MDNode::op_iterator I = nullptr;
+
+public:
+  TypedMDOperandIterator() = default;
+  explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {}
+  T *operator*() const { return cast_or_null<T>(*I); }
+  TypedMDOperandIterator &operator++() {
+    ++I;
+    return *this;
+  }
+  TypedMDOperandIterator operator++(int) {
+    TypedMDOperandIterator Temp(*this);
+    ++I;
+    return Temp;
+  }
+  bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; }
+  bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; }
+};
+
+/// \brief Typed, array-like tuple of metadata.
+///
+/// This is a wrapper for \a MDTuple that makes it act like an array holding a
+/// particular type of metadata.
+template <class T> class MDTupleTypedArrayWrapper {
+  const MDTuple *N = nullptr;
+
+public:
+  MDTupleTypedArrayWrapper() = default;
+  MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {}
+
+  template <class U>
+  MDTupleTypedArrayWrapper(
+      const MDTupleTypedArrayWrapper<U> &Other,
+      typename std::enable_if<std::is_convertible<U *, T *>::value>::type * =
+          nullptr)
+      : N(Other.get()) {}
+
+  template <class U>
+  explicit MDTupleTypedArrayWrapper(
+      const MDTupleTypedArrayWrapper<U> &Other,
+      typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * =
+          nullptr)
+      : N(Other.get()) {}
+
+  explicit operator bool() const { return get(); }
+  explicit operator MDTuple *() const { return get(); }
+
+  MDTuple *get() const { return const_cast<MDTuple *>(N); }
+  MDTuple *operator->() const { return get(); }
+  MDTuple &operator*() const { return *get(); }
+
+  // FIXME: Fix callers and remove condition on N.
+  unsigned size() const { return N ? N->getNumOperands() : 0u; }
+  T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); }
+
+  // FIXME: Fix callers and remove condition on N.
+  typedef TypedMDOperandIterator<T> iterator;
+  iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); }
+  iterator end() const { return N ? iterator(N->op_end()) : iterator(); }
+};
+
+#define HANDLE_METADATA(CLASS)                                                 \
+  typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array;
+#include "llvm/IR/Metadata.def"
+
+/// Placeholder metadata for operands of distinct MDNodes.
+///
+/// This is a lightweight placeholder for an operand of a distinct node.  It's
+/// purpose is to help track forward references when creating a distinct node.
+/// This allows distinct nodes involved in a cycle to be constructed before
+/// their operands without requiring a heavyweight temporary node with
+/// full-blown RAUW support.
+///
+/// Each placeholder supports only a single MDNode user.  Clients should pass
+/// an ID, retrieved via \a getID(), to indicate the "real" operand that this
+/// should be replaced with.
+///
+/// While it would be possible to implement move operators, they would be
+/// fairly expensive.  Leave them unimplemented to discourage their use
+/// (clients can use std::deque, std::list, BumpPtrAllocator, etc.).
+class DistinctMDOperandPlaceholder : public Metadata {
+  friend class MetadataTracking;
+
+  Metadata **Use = nullptr;
+
+  DistinctMDOperandPlaceholder() = delete;
+  DistinctMDOperandPlaceholder(DistinctMDOperandPlaceholder &&) = delete;
+  DistinctMDOperandPlaceholder(const DistinctMDOperandPlaceholder &) = delete;
+
+public:
+  explicit DistinctMDOperandPlaceholder(unsigned ID)
+      : Metadata(DistinctMDOperandPlaceholderKind, Distinct) {
+    SubclassData32 = ID;
+  }
+
+  ~DistinctMDOperandPlaceholder() {
+    if (Use)
+      *Use = nullptr;
+  }
+
+  unsigned getID() const { return SubclassData32; }
+
+  /// Replace the use of this with MD.
+  void replaceUseWith(Metadata *MD) {
+    if (!Use)
+      return;
+    *Use = MD;
+    Use = nullptr;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// \brief A tuple of MDNodes.
+///
+/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong
+/// to modules, have names, and contain lists of MDNodes.
+///
+/// TODO: Inherit from Metadata.
+class NamedMDNode : public ilist_node<NamedMDNode> {
+  friend class LLVMContextImpl;
+  friend class Module;
+  NamedMDNode(const NamedMDNode &) = delete;
+
+  std::string Name;
+  Module *Parent;
+  void *Operands; // SmallVector<TrackingMDRef, 4>
+
+  void setParent(Module *M) { Parent = M; }
+
+  explicit NamedMDNode(const Twine &N);
+
+  template<class T1, class T2>
+  class op_iterator_impl :
+      public std::iterator<std::bidirectional_iterator_tag, T2> {
+    const NamedMDNode *Node;
+    unsigned Idx;
+    op_iterator_impl(const NamedMDNode *N, unsigned i) : Node(N), Idx(i) { }
+
+    friend class NamedMDNode;
+
+  public:
+    op_iterator_impl() : Node(nullptr), Idx(0) { }
+
+    bool operator==(const op_iterator_impl &o) const { return Idx == o.Idx; }
+    bool operator!=(const op_iterator_impl &o) const { return Idx != o.Idx; }
+    op_iterator_impl &operator++() {
+      ++Idx;
+      return *this;
+    }
+    op_iterator_impl operator++(int) {
+      op_iterator_impl tmp(*this);
+      operator++();
+      return tmp;
+    }
+    op_iterator_impl &operator--() {
+      --Idx;
+      return *this;
+    }
+    op_iterator_impl operator--(int) {
+      op_iterator_impl tmp(*this);
+      operator--();
+      return tmp;
+    }
+
+    T1 operator*() const { return Node->getOperand(Idx); }
+  };
+
+public:
+  /// \brief Drop all references and remove the node from parent module.
+  void eraseFromParent();
+
+  /// \brief Remove all uses and clear node vector.
+  void dropAllReferences();
+
+  ~NamedMDNode();
+
+  /// \brief Get the module that holds this named metadata collection.
+  inline Module *getParent() { return Parent; }
+  inline const Module *getParent() const { return Parent; }
+
+  MDNode *getOperand(unsigned i) const;
+  unsigned getNumOperands() const;
+  void addOperand(MDNode *M);
+  void setOperand(unsigned I, MDNode *New);
+  StringRef getName() const;
+  void print(raw_ostream &ROS, bool IsForDebug = false) const;
+  void print(raw_ostream &ROS, ModuleSlotTracker &MST,
+             bool IsForDebug = false) const;
+  void dump() const;
+
+  // ---------------------------------------------------------------------------
+  // Operand Iterator interface...
+  //
+  typedef op_iterator_impl<MDNode *, MDNode> op_iterator;
+  op_iterator op_begin() { return op_iterator(this, 0); }
+  op_iterator op_end()   { return op_iterator(this, getNumOperands()); }
+
+  typedef op_iterator_impl<const MDNode *, MDNode> const_op_iterator;
+  const_op_iterator op_begin() const { return const_op_iterator(this, 0); }
+  const_op_iterator op_end()   const { return const_op_iterator(this, getNumOperands()); }
+
+  inline iterator_range<op_iterator>  operands() {
+    return make_range(op_begin(), op_end());
+  }
+  inline iterator_range<const_op_iterator> operands() const {
+    return make_range(op_begin(), op_end());
+  }
+};
+
+} // end llvm namespace
+
+#endif // LLVM_IR_METADATA_H
diff --git a/third_party/llvm-subzero/include/llvm/IR/OperandTraits.h b/third_party/llvm-subzero/include/llvm/IR/OperandTraits.h
new file mode 100644
index 0000000..e97a800
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/OperandTraits.h
@@ -0,0 +1,160 @@
+//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the traits classes that are handy for enforcing the correct
+// layout of various User subclasses. It also provides the means for accessing
+// the operands in the most efficient manner.
+//
+
+#ifndef LLVM_IR_OPERANDTRAITS_H
+#define LLVM_IR_OPERANDTRAITS_H
+
+#include "llvm/IR/User.h"
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+//                          FixedNumOperand Trait Class
+//===----------------------------------------------------------------------===//
+
+/// FixedNumOperandTraits - determine the allocation regime of the Use array
+/// when it is a prefix to the User object, and the number of Use objects is
+/// known at compile time.
+
+template <typename SubClass, unsigned ARITY>
+struct FixedNumOperandTraits {
+  static Use *op_begin(SubClass* U) {
+    return reinterpret_cast<Use*>(U) - ARITY;
+  }
+  static Use *op_end(SubClass* U) {
+    return reinterpret_cast<Use*>(U);
+  }
+  static unsigned operands(const User*) {
+    return ARITY;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+//                          OptionalOperand Trait Class
+//===----------------------------------------------------------------------===//
+
+/// OptionalOperandTraits - when the number of operands may change at runtime.
+/// Naturally it may only decrease, because the allocations may not change.
+
+template <typename SubClass, unsigned ARITY = 1>
+struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
+  static unsigned operands(const User *U) {
+    return U->getNumOperands();
+  }
+};
+
+//===----------------------------------------------------------------------===//
+//                          VariadicOperand Trait Class
+//===----------------------------------------------------------------------===//
+
+/// VariadicOperandTraits - determine the allocation regime of the Use array
+/// when it is a prefix to the User object, and the number of Use objects is
+/// only known at allocation time.
+
+template <typename SubClass, unsigned MINARITY = 0>
+struct VariadicOperandTraits {
+  static Use *op_begin(SubClass* U) {
+    return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
+  }
+  static Use *op_end(SubClass* U) {
+    return reinterpret_cast<Use*>(U);
+  }
+  static unsigned operands(const User *U) {
+    return U->getNumOperands();
+  }
+};
+
+//===----------------------------------------------------------------------===//
+//                          HungoffOperand Trait Class
+//===----------------------------------------------------------------------===//
+
+/// HungoffOperandTraits - determine the allocation regime of the Use array
+/// when it is not a prefix to the User object, but allocated at an unrelated
+/// heap address.
+/// Assumes that the User subclass that is determined by this traits class
+/// has an OperandList member of type User::op_iterator. [Note: this is now
+/// trivially satisfied, because User has that member for historic reasons.]
+///
+/// This is the traits class that is needed when the Use array must be
+/// resizable.
+
+template <unsigned MINARITY = 1>
+struct HungoffOperandTraits {
+  static Use *op_begin(User* U) {
+    return U->getOperandList();
+  }
+  static Use *op_end(User* U) {
+    return U->getOperandList() + U->getNumOperands();
+  }
+  static unsigned operands(const User *U) {
+    return U->getNumOperands();
+  }
+};
+
+/// Macro for generating in-class operand accessor declarations.
+/// It should only be called in the public section of the interface.
+///
+#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \
+  public: \
+  inline VALUECLASS *getOperand(unsigned) const; \
+  inline void setOperand(unsigned, VALUECLASS*); \
+  inline op_iterator op_begin(); \
+  inline const_op_iterator op_begin() const; \
+  inline op_iterator op_end(); \
+  inline const_op_iterator op_end() const; \
+  protected: \
+  template <int> inline Use &Op(); \
+  template <int> inline const Use &Op() const; \
+  public: \
+  inline unsigned getNumOperands() const
+
+/// Macro for generating out-of-class operand accessor definitions
+#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
+CLASS::op_iterator CLASS::op_begin() { \
+  return OperandTraits<CLASS>::op_begin(this); \
+} \
+CLASS::const_op_iterator CLASS::op_begin() const { \
+  return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
+} \
+CLASS::op_iterator CLASS::op_end() { \
+  return OperandTraits<CLASS>::op_end(this); \
+} \
+CLASS::const_op_iterator CLASS::op_end() const { \
+  return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
+} \
+VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
+  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
+         && "getOperand() out of range!"); \
+  return cast_or_null<VALUECLASS>( \
+    OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \
+} \
+void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
+  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
+         && "setOperand() out of range!"); \
+  OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
+} \
+unsigned CLASS::getNumOperands() const { \
+  return OperandTraits<CLASS>::operands(this); \
+} \
+template <int Idx_nocapture> Use &CLASS::Op() { \
+  return this->OpFrom<Idx_nocapture>(this); \
+} \
+template <int Idx_nocapture> const Use &CLASS::Op() const { \
+  return this->OpFrom<Idx_nocapture>(this); \
+}
+
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/SymbolTableListTraits.h b/third_party/llvm-subzero/include/llvm/IR/SymbolTableListTraits.h
new file mode 100644
index 0000000..5c6d58a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/SymbolTableListTraits.h
@@ -0,0 +1,114 @@
+//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a generic class that is used to implement the automatic
+// symbol table manipulation that occurs when you put (for example) a named
+// instruction into a basic block.
+//
+// The way that this is implemented is by using a special traits class with the
+// intrusive list that makes up the list of instructions in a basic block.  When
+// a new element is added to the list of instructions, the traits class is
+// notified, allowing the symbol table to be updated.
+//
+// This generic class implements the traits class.  It must be generic so that
+// it can work for all uses it, which include lists of instructions, basic
+// blocks, arguments, functions, global variables, etc...
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_SYMBOLTABLELISTTRAITS_H
+#define LLVM_IR_SYMBOLTABLELISTTRAITS_H
+
+#include "llvm/ADT/ilist.h"
+
+namespace llvm {
+class ValueSymbolTable;
+
+/// Template metafunction to get the parent type for a symbol table list.
+///
+/// Implementations create a typedef called \c type so that we only need a
+/// single template parameter for the list and traits.
+template <typename NodeTy> struct SymbolTableListParentType {};
+class Argument;
+class BasicBlock;
+class Function;
+class Instruction;
+class GlobalVariable;
+class GlobalAlias;
+class GlobalIFunc;
+class Module;
+#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT)                          \
+  template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; };
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(BasicBlock, Function)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalIFunc, Module)
+#undef DEFINE_SYMBOL_TABLE_PARENT_TYPE
+
+template <typename NodeTy> class SymbolTableList;
+
+// ValueSubClass   - The type of objects that I hold, e.g. Instruction.
+// ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
+//
+template <typename ValueSubClass>
+class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> {
+  typedef SymbolTableList<ValueSubClass> ListTy;
+  typedef typename simple_ilist<ValueSubClass>::iterator iterator;
+  typedef
+      typename SymbolTableListParentType<ValueSubClass>::type ItemParentClass;
+
+public:
+  SymbolTableListTraits() {}
+
+private:
+  /// getListOwner - Return the object that owns this list.  If this is a list
+  /// of instructions, it returns the BasicBlock that owns them.
+  ItemParentClass *getListOwner() {
+    size_t Offset(size_t(&((ItemParentClass*)nullptr->*ItemParentClass::
+                           getSublistAccess(static_cast<ValueSubClass*>(nullptr)))));
+    ListTy *Anchor(static_cast<ListTy *>(this));
+    return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)-
+                                              Offset);
+  }
+
+  static ListTy &getList(ItemParentClass *Par) {
+    return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr));
+  }
+
+  static ValueSymbolTable *getSymTab(ItemParentClass *Par) {
+    return Par ? toPtr(Par->getValueSymbolTable()) : nullptr;
+  }
+
+public:
+  void addNodeToList(ValueSubClass *V);
+  void removeNodeFromList(ValueSubClass *V);
+  void transferNodesFromList(SymbolTableListTraits &L2, iterator first,
+                             iterator last);
+  // private:
+  template<typename TPtr>
+  void setSymTabObject(TPtr *, TPtr);
+  static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; }
+  static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; }
+};
+
+/// List that automatically updates parent links and symbol tables.
+///
+/// When nodes are inserted into and removed from this list, the associated
+/// symbol table will be automatically updated.  Similarly, parent links get
+/// updated automatically.
+template <class T>
+class SymbolTableList
+    : public iplist_impl<simple_ilist<T>, SymbolTableListTraits<T>> {};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/TrackingMDRef.h b/third_party/llvm-subzero/include/llvm/IR/TrackingMDRef.h
new file mode 100644
index 0000000..fe513a8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/TrackingMDRef.h
@@ -0,0 +1,165 @@
+//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// References to metadata that track RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_TRACKINGMDREF_H
+#define LLVM_IR_TRACKINGMDREF_H
+
+#include "llvm/IR/Metadata.h"
+
+namespace llvm {
+
+/// \brief Tracking metadata reference.
+///
+/// This class behaves like \a TrackingVH, but for metadata.
+class TrackingMDRef {
+  Metadata *MD;
+
+public:
+  TrackingMDRef() : MD(nullptr) {}
+  explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
+
+  TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
+  TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
+  TrackingMDRef &operator=(TrackingMDRef &&X) {
+    if (&X == this)
+      return *this;
+
+    untrack();
+    MD = X.MD;
+    retrack(X);
+    return *this;
+  }
+  TrackingMDRef &operator=(const TrackingMDRef &X) {
+    if (&X == this)
+      return *this;
+
+    untrack();
+    MD = X.MD;
+    track();
+    return *this;
+  }
+  ~TrackingMDRef() { untrack(); }
+
+  Metadata *get() const { return MD; }
+  operator Metadata *() const { return get(); }
+  Metadata *operator->() const { return get(); }
+  Metadata &operator*() const { return *get(); }
+
+  void reset() {
+    untrack();
+    MD = nullptr;
+  }
+  void reset(Metadata *MD) {
+    untrack();
+    this->MD = MD;
+    track();
+  }
+
+  /// \brief Check whether this has a trivial destructor.
+  ///
+  /// If \c MD isn't replaceable, the destructor will be a no-op.
+  bool hasTrivialDestructor() const {
+    return !MD || !MetadataTracking::isReplaceable(*MD);
+  }
+
+  bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
+  bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
+
+private:
+  void track() {
+    if (MD)
+      MetadataTracking::track(MD);
+  }
+  void untrack() {
+    if (MD)
+      MetadataTracking::untrack(MD);
+  }
+  void retrack(TrackingMDRef &X) {
+    assert(MD == X.MD && "Expected values to match");
+    if (X.MD) {
+      MetadataTracking::retrack(X.MD, MD);
+      X.MD = nullptr;
+    }
+  }
+};
+
+/// \brief Typed tracking ref.
+///
+/// Track refererences of a particular type.  It's useful to use this for \a
+/// MDNode and \a ValueAsMetadata.
+template <class T> class TypedTrackingMDRef {
+  TrackingMDRef Ref;
+
+public:
+  TypedTrackingMDRef() {}
+  explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
+
+  TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
+  TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
+  TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
+    Ref = std::move(X.Ref);
+    return *this;
+  }
+  TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
+    Ref = X.Ref;
+    return *this;
+  }
+
+  T *get() const { return (T *)Ref.get(); }
+  operator T *() const { return get(); }
+  T *operator->() const { return get(); }
+  T &operator*() const { return *get(); }
+
+  bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
+  bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
+
+  void reset() { Ref.reset(); }
+  void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
+
+  /// \brief Check whether this has a trivial destructor.
+  bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
+};
+
+typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
+typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
+
+// Expose the underlying metadata to casting.
+template <> struct simplify_type<TrackingMDRef> {
+  typedef Metadata *SimpleType;
+  static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const TrackingMDRef> {
+  typedef Metadata *SimpleType;
+  static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
+    return MD.get();
+  }
+};
+
+template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
+  typedef T *SimpleType;
+  static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
+    return MD.get();
+  }
+};
+
+template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
+  typedef T *SimpleType;
+  static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
+    return MD.get();
+  }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Type.h b/third_party/llvm-subzero/include/llvm/IR/Type.h
new file mode 100644
index 0000000..9cf03d8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Type.h
@@ -0,0 +1,464 @@
+//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the Type class.  For more "Type"
+// stuff, look in DerivedTypes.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_TYPE_H
+#define LLVM_IR_TYPE_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+class PointerType;
+class IntegerType;
+class raw_ostream;
+class Module;
+class LLVMContext;
+class LLVMContextImpl;
+class StringRef;
+template<class GraphType> struct GraphTraits;
+
+/// The instances of the Type class are immutable: once they are created,
+/// they are never changed.  Also note that only one instance of a particular
+/// type is ever created.  Thus seeing if two types are equal is a matter of
+/// doing a trivial pointer comparison. To enforce that no two equal instances
+/// are created, Type instances can only be created via static factory methods
+/// in class Type and in derived classes.  Once allocated, Types are never
+/// free'd.
+///
+class Type {
+public:
+  //===--------------------------------------------------------------------===//
+  /// Definitions of all of the base types for the Type system.  Based on this
+  /// value, you can cast to a class defined in DerivedTypes.h.
+  /// Note: If you add an element to this, you need to add an element to the
+  /// Type::getPrimitiveType function, or else things will break!
+  /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding.
+  ///
+  enum TypeID {
+    // PrimitiveTypes - make sure LastPrimitiveTyID stays up to date.
+    VoidTyID = 0,    ///<  0: type with no size
+    HalfTyID,        ///<  1: 16-bit floating point type
+    FloatTyID,       ///<  2: 32-bit floating point type
+    DoubleTyID,      ///<  3: 64-bit floating point type
+    X86_FP80TyID,    ///<  4: 80-bit floating point type (X87)
+    FP128TyID,       ///<  5: 128-bit floating point type (112-bit mantissa)
+    PPC_FP128TyID,   ///<  6: 128-bit floating point type (two 64-bits, PowerPC)
+    LabelTyID,       ///<  7: Labels
+    MetadataTyID,    ///<  8: Metadata
+    X86_MMXTyID,     ///<  9: MMX vectors (64 bits, X86 specific)
+    TokenTyID,       ///< 10: Tokens
+
+    // Derived types... see DerivedTypes.h file.
+    // Make sure FirstDerivedTyID stays up to date!
+    IntegerTyID,     ///< 11: Arbitrary bit width integers
+    FunctionTyID,    ///< 12: Functions
+    StructTyID,      ///< 13: Structures
+    ArrayTyID,       ///< 14: Arrays
+    PointerTyID,     ///< 15: Pointers
+    VectorTyID       ///< 16: SIMD 'packed' format, or other vector type
+  };
+
+private:
+  /// This refers to the LLVMContext in which this type was uniqued.
+  LLVMContext &Context;
+
+  TypeID   ID : 8;            // The current base type of this type.
+  unsigned SubclassData : 24; // Space for subclasses to store data.
+
+protected:
+  friend class LLVMContextImpl;
+  explicit Type(LLVMContext &C, TypeID tid)
+    : Context(C), ID(tid), SubclassData(0),
+      NumContainedTys(0), ContainedTys(nullptr) {}
+  ~Type() = default;
+
+  unsigned getSubclassData() const { return SubclassData; }
+
+  void setSubclassData(unsigned val) {
+    SubclassData = val;
+    // Ensure we don't have any accidental truncation.
+    assert(getSubclassData() == val && "Subclass data too large for field");
+  }
+
+  /// Keeps track of how many Type*'s there are in the ContainedTys list.
+  unsigned NumContainedTys;
+
+  /// A pointer to the array of Types contained by this Type. For example, this
+  /// includes the arguments of a function type, the elements of a structure,
+  /// the pointee of a pointer, the element type of an array, etc. This pointer
+  /// may be 0 for types that don't contain other types (Integer, Double,
+  /// Float).
+  Type * const *ContainedTys;
+
+  static bool isSequentialType(TypeID TyID) {
+    return TyID == ArrayTyID || TyID == PointerTyID || TyID == VectorTyID;
+  }
+
+public:
+  /// Print the current type.
+  /// Omit the type details if \p NoDetails == true.
+  /// E.g., let %st = type { i32, i16 }
+  /// When \p NoDetails is true, we only print %st.
+  /// Put differently, \p NoDetails prints the type as if
+  /// inlined with the operands when printing an instruction.
+  void print(raw_ostream &O, bool IsForDebug = false,
+             bool NoDetails = false) const;
+  void dump() const;
+
+  /// Return the LLVMContext in which this type was uniqued.
+  LLVMContext &getContext() const { return Context; }
+
+  //===--------------------------------------------------------------------===//
+  // Accessors for working with types.
+  //
+
+  /// Return the type id for the type. This will return one of the TypeID enum
+  /// elements defined above.
+  TypeID getTypeID() const { return ID; }
+
+  /// Return true if this is 'void'.
+  bool isVoidTy() const { return getTypeID() == VoidTyID; }
+
+  /// Return true if this is 'half', a 16-bit IEEE fp type.
+  bool isHalfTy() const { return getTypeID() == HalfTyID; }
+
+  /// Return true if this is 'float', a 32-bit IEEE fp type.
+  bool isFloatTy() const { return getTypeID() == FloatTyID; }
+
+  /// Return true if this is 'double', a 64-bit IEEE fp type.
+  bool isDoubleTy() const { return getTypeID() == DoubleTyID; }
+
+  /// Return true if this is x86 long double.
+  bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; }
+
+  /// Return true if this is 'fp128'.
+  bool isFP128Ty() const { return getTypeID() == FP128TyID; }
+
+  /// Return true if this is powerpc long double.
+  bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; }
+
+  /// Return true if this is one of the six floating-point types
+  bool isFloatingPointTy() const {
+    return getTypeID() == HalfTyID || getTypeID() == FloatTyID ||
+           getTypeID() == DoubleTyID ||
+           getTypeID() == X86_FP80TyID || getTypeID() == FP128TyID ||
+           getTypeID() == PPC_FP128TyID;
+  }
+
+  const fltSemantics &getFltSemantics() const {
+    switch (getTypeID()) {
+    case HalfTyID: return APFloat::IEEEhalf;
+    case FloatTyID: return APFloat::IEEEsingle;
+    case DoubleTyID: return APFloat::IEEEdouble;
+    case X86_FP80TyID: return APFloat::x87DoubleExtended;
+    case FP128TyID: return APFloat::IEEEquad;
+    case PPC_FP128TyID: return APFloat::PPCDoubleDouble;
+    default: llvm_unreachable("Invalid floating type");
+    }
+  }
+
+  /// Return true if this is X86 MMX.
+  bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; }
+
+  /// Return true if this is a FP type or a vector of FP.
+  bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
+
+  /// Return true if this is 'label'.
+  bool isLabelTy() const { return getTypeID() == LabelTyID; }
+
+  /// Return true if this is 'metadata'.
+  bool isMetadataTy() const { return getTypeID() == MetadataTyID; }
+
+  /// Return true if this is 'token'.
+  bool isTokenTy() const { return getTypeID() == TokenTyID; }
+
+  /// True if this is an instance of IntegerType.
+  bool isIntegerTy() const { return getTypeID() == IntegerTyID; }
+
+  /// Return true if this is an IntegerType of the given width.
+  bool isIntegerTy(unsigned Bitwidth) const;
+
+  /// Return true if this is an integer type or a vector of integer types.
+  bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); }
+
+  /// True if this is an instance of FunctionType.
+  bool isFunctionTy() const { return getTypeID() == FunctionTyID; }
+
+  /// True if this is an instance of StructType.
+  bool isStructTy() const { return getTypeID() == StructTyID; }
+
+  /// True if this is an instance of ArrayType.
+  bool isArrayTy() const { return getTypeID() == ArrayTyID; }
+
+  /// True if this is an instance of PointerType.
+  bool isPointerTy() const { return getTypeID() == PointerTyID; }
+
+  /// Return true if this is a pointer type or a vector of pointer types.
+  bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); }
+
+  /// True if this is an instance of VectorType.
+  bool isVectorTy() const { return getTypeID() == VectorTyID; }
+
+  /// Return true if this type could be converted with a lossless BitCast to
+  /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the
+  /// same size only where no re-interpretation of the bits is done.
+  /// @brief Determine if this type could be losslessly bitcast to Ty
+  bool canLosslesslyBitCastTo(Type *Ty) const;
+
+  /// Return true if this type is empty, that is, it has no elements or all of
+  /// its elements are empty.
+  bool isEmptyTy() const;
+
+  /// Return true if the type is "first class", meaning it is a valid type for a
+  /// Value.
+  bool isFirstClassType() const {
+    return getTypeID() != FunctionTyID && getTypeID() != VoidTyID;
+  }
+
+  /// Return true if the type is a valid type for a register in codegen. This
+  /// includes all first-class types except struct and array types.
+  bool isSingleValueType() const {
+    return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() ||
+           isPointerTy() || isVectorTy();
+  }
+
+  /// Return true if the type is an aggregate type. This means it is valid as
+  /// the first operand of an insertvalue or extractvalue instruction. This
+  /// includes struct and array types, but does not include vector types.
+  bool isAggregateType() const {
+    return getTypeID() == StructTyID || getTypeID() == ArrayTyID;
+  }
+
+  /// Return true if it makes sense to take the size of this type. To get the
+  /// actual size for a particular target, it is reasonable to use the
+  /// DataLayout subsystem to do this.
+  bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const {
+    // If it's a primitive, it is always sized.
+    if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
+        getTypeID() == PointerTyID ||
+        getTypeID() == X86_MMXTyID)
+      return true;
+    // If it is not something that can have a size (e.g. a function or label),
+    // it doesn't have a size.
+    if (getTypeID() != StructTyID && getTypeID() != ArrayTyID &&
+        getTypeID() != VectorTyID)
+      return false;
+    // Otherwise we have to try harder to decide.
+    return isSizedDerivedType(Visited);
+  }
+
+  /// Return the basic size of this type if it is a primitive type. These are
+  /// fixed by LLVM and are not target-dependent.
+  /// This will return zero if the type does not have a size or is not a
+  /// primitive type.
+  ///
+  /// Note that this may not reflect the size of memory allocated for an
+  /// instance of the type or the number of bytes that are written when an
+  /// instance of the type is stored to memory. The DataLayout class provides
+  /// additional query functions to provide this information.
+  ///
+  unsigned getPrimitiveSizeInBits() const LLVM_READONLY;
+
+  /// If this is a vector type, return the getPrimitiveSizeInBits value for the
+  /// element type. Otherwise return the getPrimitiveSizeInBits value for this
+  /// type.
+  unsigned getScalarSizeInBits() const LLVM_READONLY;
+
+  /// Return the width of the mantissa of this type. This is only valid on
+  /// floating-point types. If the FP type does not have a stable mantissa (e.g.
+  /// ppc long double), this method returns -1.
+  int getFPMantissaWidth() const;
+
+  /// If this is a vector type, return the element type, otherwise return
+  /// 'this'.
+  Type *getScalarType() const LLVM_READONLY;
+
+  //===--------------------------------------------------------------------===//
+  // Type Iteration support.
+  //
+  typedef Type * const *subtype_iterator;
+  subtype_iterator subtype_begin() const { return ContainedTys; }
+  subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];}
+  ArrayRef<Type*> subtypes() const {
+    return makeArrayRef(subtype_begin(), subtype_end());
+  }
+
+  typedef std::reverse_iterator<subtype_iterator> subtype_reverse_iterator;
+  subtype_reverse_iterator subtype_rbegin() const {
+    return subtype_reverse_iterator(subtype_end());
+  }
+  subtype_reverse_iterator subtype_rend() const {
+    return subtype_reverse_iterator(subtype_begin());
+  }
+
+  /// This method is used to implement the type iterator (defined at the end of
+  /// the file). For derived types, this returns the types 'contained' in the
+  /// derived type.
+  Type *getContainedType(unsigned i) const {
+    assert(i < NumContainedTys && "Index out of range!");
+    return ContainedTys[i];
+  }
+
+  /// Return the number of types in the derived type.
+  unsigned getNumContainedTypes() const { return NumContainedTys; }
+
+  //===--------------------------------------------------------------------===//
+  // Helper methods corresponding to subclass methods.  This forces a cast to
+  // the specified subclass and calls its accessor.  "getVectorNumElements" (for
+  // example) is shorthand for cast<VectorType>(Ty)->getNumElements().  This is
+  // only intended to cover the core methods that are frequently used, helper
+  // methods should not be added here.
+
+  inline unsigned getIntegerBitWidth() const;
+
+  inline Type *getFunctionParamType(unsigned i) const;
+  inline unsigned getFunctionNumParams() const;
+  inline bool isFunctionVarArg() const;
+
+  inline StringRef getStructName() const;
+  inline unsigned getStructNumElements() const;
+  inline Type *getStructElementType(unsigned N) const;
+
+  inline Type *getSequentialElementType() const {
+    assert(isSequentialType(getTypeID()) && "Not a sequential type!");
+    return ContainedTys[0];
+  }
+
+  inline uint64_t getArrayNumElements() const;
+  Type *getArrayElementType() const { return getSequentialElementType(); }
+
+  inline unsigned getVectorNumElements() const;
+  Type *getVectorElementType() const { return getSequentialElementType(); }
+
+  Type *getPointerElementType() const { return getSequentialElementType(); }
+
+  /// Get the address space of this pointer or pointer vector type.
+  inline unsigned getPointerAddressSpace() const;
+
+  //===--------------------------------------------------------------------===//
+  // Static members exported by the Type class itself.  Useful for getting
+  // instances of Type.
+  //
+
+  /// Return a type based on an identifier.
+  static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber);
+
+  //===--------------------------------------------------------------------===//
+  // These are the builtin types that are always available.
+  //
+  static Type *getVoidTy(LLVMContext &C);
+  static Type *getLabelTy(LLVMContext &C);
+  static Type *getHalfTy(LLVMContext &C);
+  static Type *getFloatTy(LLVMContext &C);
+  static Type *getDoubleTy(LLVMContext &C);
+  static Type *getMetadataTy(LLVMContext &C);
+  static Type *getX86_FP80Ty(LLVMContext &C);
+  static Type *getFP128Ty(LLVMContext &C);
+  static Type *getPPC_FP128Ty(LLVMContext &C);
+  static Type *getX86_MMXTy(LLVMContext &C);
+  static Type *getTokenTy(LLVMContext &C);
+  static IntegerType *getIntNTy(LLVMContext &C, unsigned N);
+  static IntegerType *getInt1Ty(LLVMContext &C);
+  static IntegerType *getInt8Ty(LLVMContext &C);
+  static IntegerType *getInt16Ty(LLVMContext &C);
+  static IntegerType *getInt32Ty(LLVMContext &C);
+  static IntegerType *getInt64Ty(LLVMContext &C);
+  static IntegerType *getInt128Ty(LLVMContext &C);
+
+  //===--------------------------------------------------------------------===//
+  // Convenience methods for getting pointer types with one of the above builtin
+  // types as pointee.
+  //
+  static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0);
+  static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0);
+  static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0);
+
+  /// Return a pointer to the current type. This is equivalent to
+  /// PointerType::get(Foo, AddrSpace).
+  PointerType *getPointerTo(unsigned AddrSpace = 0) const;
+
+private:
+  /// Derived types like structures and arrays are sized iff all of the members
+  /// of the type are sized as well. Since asking for their size is relatively
+  /// uncommon, move this operation out-of-line.
+  bool isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited = nullptr) const;
+};
+
+// Printing of types.
+static inline raw_ostream &operator<<(raw_ostream &OS, Type &T) {
+  T.print(OS);
+  return OS;
+}
+
+// allow isa<PointerType>(x) to work without DerivedTypes.h included.
+template <> struct isa_impl<PointerType, Type> {
+  static inline bool doit(const Type &Ty) {
+    return Ty.getTypeID() == Type::PointerTyID;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Provide specializations of GraphTraits to be able to treat a type as a
+// graph of sub types.
+
+template <> struct GraphTraits<Type *> {
+  typedef Type *NodeRef;
+  typedef Type::subtype_iterator ChildIteratorType;
+
+  static NodeRef getEntryNode(Type *T) { return T; }
+  static ChildIteratorType child_begin(NodeRef N) { return N->subtype_begin(); }
+  static ChildIteratorType child_end(NodeRef N) { return N->subtype_end(); }
+};
+
+template <> struct GraphTraits<const Type*> {
+  typedef const Type *NodeRef;
+  typedef Type::subtype_iterator ChildIteratorType;
+
+  static NodeRef getEntryNode(NodeRef T) { return T; }
+  static ChildIteratorType child_begin(NodeRef N) { return N->subtype_begin(); }
+  static ChildIteratorType child_end(NodeRef N) { return N->subtype_end(); }
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef)
+
+/* Specialized opaque type conversions.
+ */
+inline Type **unwrap(LLVMTypeRef* Tys) {
+  return reinterpret_cast<Type**>(Tys);
+}
+
+inline LLVMTypeRef *wrap(Type **Tys) {
+  return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys));
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Use.h b/third_party/llvm-subzero/include/llvm/IR/Use.h
new file mode 100644
index 0000000..e62eab5
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Use.h
@@ -0,0 +1,164 @@
+//===-- llvm/Use.h - Definition of the Use class ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This defines the Use class.  The Use class represents the operand of an
+/// instruction or some other User instance which refers to a Value.  The Use
+/// class keeps the "use list" of the referenced value up to date.
+///
+/// Pointer tagging is used to efficiently find the User corresponding to a Use
+/// without having to store a User pointer in every Use. A User is preceded in
+/// memory by all the Uses corresponding to its operands, and the low bits of
+/// one of the fields (Prev) of the Use class are used to encode offsets to be
+/// able to find that User given a pointer to any Use. For details, see:
+///
+///   http://www.llvm.org/docs/ProgrammersManual.html#UserLayout
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_USE_H
+#define LLVM_IR_USE_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include <cstddef>
+
+namespace llvm {
+
+class Value;
+class User;
+class Use;
+template <typename> struct simplify_type;
+
+// Use** is only 4-byte aligned.
+template <> class PointerLikeTypeTraits<Use **> {
+public:
+  static inline void *getAsVoidPointer(Use **P) { return P; }
+  static inline Use **getFromVoidPointer(void *P) {
+    return static_cast<Use **>(P);
+  }
+  enum { NumLowBitsAvailable = 2 };
+};
+
+/// \brief A Use represents the edge between a Value definition and its users.
+///
+/// This is notionally a two-dimensional linked list. It supports traversing
+/// all of the uses for a particular value definition. It also supports jumping
+/// directly to the used value when we arrive from the User's operands, and
+/// jumping directly to the User when we arrive from the Value's uses.
+///
+/// The pointer to the used Value is explicit, and the pointer to the User is
+/// implicit. The implicit pointer is found via a waymarking algorithm
+/// described in the programmer's manual:
+///
+///   http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
+///
+/// This is essentially the single most memory intensive object in LLVM because
+/// of the number of uses in the system. At the same time, the constant time
+/// operations it allows are essential to many optimizations having reasonable
+/// time complexity.
+class Use {
+public:
+  /// \brief Provide a fast substitute to std::swap<Use>
+  /// that also works with less standard-compliant compilers
+  void swap(Use &RHS);
+
+  // A type for the word following an array of hung-off Uses in memory, which is
+  // a pointer back to their User with the bottom bit set.
+  typedef PointerIntPair<User *, 1, unsigned> UserRef;
+
+private:
+  Use(const Use &U) = delete;
+
+  /// Destructor - Only for zap()
+  ~Use() {
+    if (Val)
+      removeFromList();
+  }
+
+  enum PrevPtrTag { zeroDigitTag, oneDigitTag, stopTag, fullStopTag };
+
+  /// Constructor
+  Use(PrevPtrTag tag) : Val(nullptr) { Prev.setInt(tag); }
+
+public:
+  operator Value *() const { return Val; }
+  Value *get() const { return Val; }
+
+  /// \brief Returns the User that contains this Use.
+  ///
+  /// For an instruction operand, for example, this will return the
+  /// instruction.
+  User *getUser() const;
+
+  inline void set(Value *Val);
+
+  inline Value *operator=(Value *RHS);
+  inline const Use &operator=(const Use &RHS);
+
+  Value *operator->() { return Val; }
+  const Value *operator->() const { return Val; }
+
+  Use *getNext() const { return Next; }
+
+  /// \brief Return the operand # of this use in its User.
+  unsigned getOperandNo() const;
+
+  /// \brief Initializes the waymarking tags on an array of Uses.
+  ///
+  /// This sets up the array of Uses such that getUser() can find the User from
+  /// any of those Uses.
+  static Use *initTags(Use *Start, Use *Stop);
+
+  /// \brief Destroys Use operands when the number of operands of
+  /// a User changes.
+  static void zap(Use *Start, const Use *Stop, bool del = false);
+
+private:
+  const Use *getImpliedUser() const;
+
+  Value *Val;
+  Use *Next;
+  PointerIntPair<Use **, 2, PrevPtrTag> Prev;
+
+  void setPrev(Use **NewPrev) { Prev.setPointer(NewPrev); }
+  void addToList(Use **List) {
+    Next = *List;
+    if (Next)
+      Next->setPrev(&Next);
+    setPrev(List);
+    *List = this;
+  }
+  void removeFromList() {
+    Use **StrippedPrev = Prev.getPointer();
+    *StrippedPrev = Next;
+    if (Next)
+      Next->setPrev(StrippedPrev);
+  }
+
+  friend class Value;
+};
+
+/// \brief Allow clients to treat uses just like values when using
+/// casting operators.
+template <> struct simplify_type<Use> {
+  typedef Value *SimpleType;
+  static SimpleType getSimplifiedValue(Use &Val) { return Val.get(); }
+};
+template <> struct simplify_type<const Use> {
+  typedef /*const*/ Value *SimpleType;
+  static SimpleType getSimplifiedValue(const Use &Val) { return Val.get(); }
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef)
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/User.h b/third_party/llvm-subzero/include/llvm/IR/User.h
new file mode 100644
index 0000000..4d6b30c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/User.h
@@ -0,0 +1,273 @@
+//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class defines the interface that one who uses a Value must implement.
+// Each instance of the Value class keeps track of what User's have handles
+// to it.
+//
+//  * Instructions are the largest class of Users.
+//  * Constants may be users of other constants (think arrays and stuff)
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_USER_H
+#define LLVM_IR_USER_H
+
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+template <typename T> class ArrayRef;
+template <typename T> class MutableArrayRef;
+
+/// \brief Compile-time customization of User operands.
+///
+/// Customizes operand-related allocators and accessors.
+template <class>
+struct OperandTraits;
+
+class User : public Value {
+  User(const User &) = delete;
+  template <unsigned>
+  friend struct HungoffOperandTraits;
+  virtual void anchor();
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void *
+  allocateFixedOperandUser(size_t, unsigned, unsigned);
+
+protected:
+  /// Allocate a User with an operand pointer co-allocated.
+  ///
+  /// This is used for subclasses which need to allocate a variable number
+  /// of operands, ie, 'hung off uses'.
+  void *operator new(size_t Size);
+
+  /// Allocate a User with the operands co-allocated.
+  ///
+  /// This is used for subclasses which have a fixed number of operands.
+  void *operator new(size_t Size, unsigned Us);
+
+  /// Allocate a User with the operands co-allocated.  If DescBytes is non-zero
+  /// then allocate an additional DescBytes bytes before the operands. These
+  /// bytes can be accessed by calling getDescriptor.
+  ///
+  /// DescBytes needs to be divisible by sizeof(void *).  The allocated
+  /// descriptor, if any, is aligned to sizeof(void *) bytes.
+  ///
+  /// This is used for subclasses which have a fixed number of operands.
+  void *operator new(size_t Size, unsigned Us, unsigned DescBytes);
+
+  User(Type *ty, unsigned vty, Use *, unsigned NumOps)
+      : Value(ty, vty) {
+    assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands");
+    NumUserOperands = NumOps;
+    // If we have hung off uses, then the operand list should initially be
+    // null.
+    assert((!HasHungOffUses || !getOperandList()) &&
+           "Error in initializing hung off uses for User");
+  }
+
+  /// \brief Allocate the array of Uses, followed by a pointer
+  /// (with bottom bit set) to the User.
+  /// \param IsPhi identifies callers which are phi nodes and which need
+  /// N BasicBlock* allocated along with N
+  void allocHungoffUses(unsigned N, bool IsPhi = false);
+
+  /// \brief Grow the number of hung off uses.  Note that allocHungoffUses
+  /// should be called if there are no uses.
+  void growHungoffUses(unsigned N, bool IsPhi = false);
+
+public:
+  ~User() override {
+  }
+  /// \brief Free memory allocated for User and Use objects.
+  void operator delete(void *Usr);
+  /// \brief Placement delete - required by std, but never called.
+  void operator delete(void*, unsigned) {
+    llvm_unreachable("Constructor throws?");
+  }
+  /// \brief Placement delete - required by std, but never called.
+  void operator delete(void*, unsigned, bool) {
+    llvm_unreachable("Constructor throws?");
+  }
+protected:
+  template <int Idx, typename U> static Use &OpFrom(const U *that) {
+    return Idx < 0
+      ? OperandTraits<U>::op_end(const_cast<U*>(that))[Idx]
+      : OperandTraits<U>::op_begin(const_cast<U*>(that))[Idx];
+  }
+  template <int Idx> Use &Op() {
+    return OpFrom<Idx>(this);
+  }
+  template <int Idx> const Use &Op() const {
+    return OpFrom<Idx>(this);
+  }
+private:
+  Use *&getHungOffOperands() { return *(reinterpret_cast<Use **>(this) - 1); }
+
+  Use *getIntrusiveOperands() {
+    return reinterpret_cast<Use *>(this) - NumUserOperands;
+  }
+
+  void setOperandList(Use *NewList) {
+    assert(HasHungOffUses &&
+           "Setting operand list only required for hung off uses");
+    getHungOffOperands() = NewList;
+  }
+public:
+  Use *getOperandList() {
+    return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands();
+  }
+  const Use *getOperandList() const {
+    return const_cast<User *>(this)->getOperandList();
+  }
+  Value *getOperand(unsigned i) const {
+    assert(i < NumUserOperands && "getOperand() out of range!");
+    return getOperandList()[i];
+  }
+  void setOperand(unsigned i, Value *Val) {
+    assert(i < NumUserOperands && "setOperand() out of range!");
+    assert((!isa<Constant>((const Value*)this) ||
+            isa<GlobalValue>((const Value*)this)) &&
+           "Cannot mutate a constant with setOperand!");
+    getOperandList()[i] = Val;
+  }
+  const Use &getOperandUse(unsigned i) const {
+    assert(i < NumUserOperands && "getOperandUse() out of range!");
+    return getOperandList()[i];
+  }
+  Use &getOperandUse(unsigned i) {
+    assert(i < NumUserOperands && "getOperandUse() out of range!");
+    return getOperandList()[i];
+  }
+
+  unsigned getNumOperands() const { return NumUserOperands; }
+
+  /// Returns the descriptor co-allocated with this User instance.
+  ArrayRef<const uint8_t> getDescriptor() const;
+
+  /// Returns the descriptor co-allocated with this User instance.
+  MutableArrayRef<uint8_t> getDescriptor();
+
+  /// Set the number of operands on a GlobalVariable.
+  ///
+  /// GlobalVariable always allocates space for a single operands, but
+  /// doesn't always use it.
+  ///
+  /// FIXME: As that the number of operands is used to find the start of
+  /// the allocated memory in operator delete, we need to always think we have
+  /// 1 operand before delete.
+  void setGlobalVariableNumOperands(unsigned NumOps) {
+    assert(NumOps <= 1 && "GlobalVariable can only have 0 or 1 operands");
+    NumUserOperands = NumOps;
+  }
+
+  /// \brief Subclasses with hung off uses need to manage the operand count
+  /// themselves.  In these instances, the operand count isn't used to find the
+  /// OperandList, so there's no issue in having the operand count change.
+  void setNumHungOffUseOperands(unsigned NumOps) {
+    assert(HasHungOffUses && "Must have hung off uses to use this method");
+    assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands");
+    NumUserOperands = NumOps;
+  }
+
+  // ---------------------------------------------------------------------------
+  // Operand Iterator interface...
+  //
+  typedef Use*       op_iterator;
+  typedef const Use* const_op_iterator;
+  typedef iterator_range<op_iterator> op_range;
+  typedef iterator_range<const_op_iterator> const_op_range;
+
+  op_iterator       op_begin()       { return getOperandList(); }
+  const_op_iterator op_begin() const { return getOperandList(); }
+  op_iterator       op_end()         {
+    return getOperandList() + NumUserOperands;
+  }
+  const_op_iterator op_end()   const {
+    return getOperandList() + NumUserOperands;
+  }
+  op_range operands() {
+    return op_range(op_begin(), op_end());
+  }
+  const_op_range operands() const {
+    return const_op_range(op_begin(), op_end());
+  }
+
+  /// \brief Iterator for directly iterating over the operand Values.
+  struct value_op_iterator
+      : iterator_adaptor_base<value_op_iterator, op_iterator,
+                              std::random_access_iterator_tag, Value *,
+                              ptrdiff_t, Value *, Value *> {
+    explicit value_op_iterator(Use *U = nullptr) : iterator_adaptor_base(U) {}
+
+    Value *operator*() const { return *I; }
+    Value *operator->() const { return operator*(); }
+  };
+
+  value_op_iterator value_op_begin() {
+    return value_op_iterator(op_begin());
+  }
+  value_op_iterator value_op_end() {
+    return value_op_iterator(op_end());
+  }
+  iterator_range<value_op_iterator> operand_values() {
+    return make_range(value_op_begin(), value_op_end());
+  }
+
+  /// \brief Drop all references to operands.
+  ///
+  /// This function is in charge of "letting go" of all objects that this User
+  /// refers to.  This allows one to 'delete' a whole class at a time, even
+  /// though there may be circular references...  First all references are
+  /// dropped, and all use counts go to zero.  Then everything is deleted for
+  /// real.  Note that no operations are valid on an object that has "dropped
+  /// all references", except operator delete.
+  void dropAllReferences() {
+    for (Use &U : operands())
+      U.set(nullptr);
+  }
+
+  /// \brief Replace uses of one Value with another.
+  ///
+  /// Replaces all references to the "From" definition with references to the
+  /// "To" definition.
+  void replaceUsesOfWith(Value *From, Value *To);
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Value *V) {
+    return isa<Instruction>(V) || isa<Constant>(V);
+  }
+};
+// Either Use objects, or a Use pointer can be prepended to User.
+static_assert(AlignOf<Use>::Alignment >= AlignOf<User>::Alignment,
+              "Alignment is insufficient after objects prepended to User");
+static_assert(AlignOf<Use *>::Alignment >= AlignOf<User>::Alignment,
+              "Alignment is insufficient after objects prepended to User");
+
+template<> struct simplify_type<User::op_iterator> {
+  typedef Value* SimpleType;
+  static SimpleType getSimplifiedValue(User::op_iterator &Val) {
+    return Val->get();
+  }
+};
+template<> struct simplify_type<User::const_op_iterator> {
+  typedef /*const*/ Value* SimpleType;
+  static SimpleType getSimplifiedValue(User::const_op_iterator &Val) {
+    return Val->get();
+  }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Value.def b/third_party/llvm-subzero/include/llvm/IR/Value.def
new file mode 100644
index 0000000..48842d7
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Value.def
@@ -0,0 +1,103 @@
+//===-------- llvm/IR/Value.def - File that describes Values ---v-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains descriptions of the various LLVM values.  This is
+// used as a central place for enumerating the different values.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+// Provide definitions of macros so that users of this file do not have to
+// define everything to use it...
+//
+#if !(defined HANDLE_GLOBAL_VALUE || defined HANDLE_CONSTANT ||                \
+      defined HANDLE_INSTRUCTION || defined HANDLE_INLINE_ASM_VALUE ||         \
+      defined HANDLE_METADATA_VALUE || defined HANDLE_VALUE ||                 \
+      defined HANDLE_CONSTANT_MARKER)
+#error "Missing macro definition of HANDLE_VALUE*"
+#endif
+
+#ifndef HANDLE_GLOBAL_VALUE
+#define HANDLE_GLOBAL_VALUE(ValueName) HANDLE_CONSTANT(ValueName)
+#endif
+
+#ifndef HANDLE_CONSTANT
+#define HANDLE_CONSTANT(ValueName) HANDLE_VALUE(ValueName)
+#endif
+
+#ifndef HANDLE_INSTRUCTION
+#define HANDLE_INSTRUCTION(ValueName) HANDLE_VALUE(ValueName)
+#endif
+
+#ifndef HANDLE_INLINE_ASM_VALUE
+#define HANDLE_INLINE_ASM_VALUE(ValueName) HANDLE_VALUE(ValueName)
+#endif
+
+#ifndef HANDLE_METADATA_VALUE
+#define HANDLE_METADATA_VALUE(ValueName) HANDLE_VALUE(ValueName)
+#endif
+
+#ifndef HANDLE_VALUE
+#define HANDLE_VALUE(ValueName)
+#endif
+
+#ifndef HANDLE_CONSTANT_MARKER
+#define HANDLE_CONSTANT_MARKER(MarkerName, ValueName)
+#endif
+
+HANDLE_VALUE(Argument)
+HANDLE_VALUE(BasicBlock)
+HANDLE_VALUE(MemoryUse)
+HANDLE_VALUE(MemoryDef)
+HANDLE_VALUE(MemoryPhi)
+
+HANDLE_GLOBAL_VALUE(Function)
+HANDLE_GLOBAL_VALUE(GlobalAlias)
+HANDLE_GLOBAL_VALUE(GlobalIFunc)
+HANDLE_GLOBAL_VALUE(GlobalVariable)
+HANDLE_CONSTANT(BlockAddress)
+HANDLE_CONSTANT(ConstantExpr)
+
+// ConstantAggregate.
+HANDLE_CONSTANT(ConstantArray)
+HANDLE_CONSTANT(ConstantStruct)
+HANDLE_CONSTANT(ConstantVector)
+
+// ConstantData.
+HANDLE_CONSTANT(UndefValue)
+HANDLE_CONSTANT(ConstantAggregateZero)
+HANDLE_CONSTANT(ConstantDataArray)
+HANDLE_CONSTANT(ConstantDataVector)
+HANDLE_CONSTANT(ConstantInt)
+HANDLE_CONSTANT(ConstantFP)
+HANDLE_CONSTANT(ConstantPointerNull)
+HANDLE_CONSTANT(ConstantTokenNone)
+
+HANDLE_METADATA_VALUE(MetadataAsValue)
+HANDLE_INLINE_ASM_VALUE(InlineAsm)
+
+HANDLE_INSTRUCTION(Instruction)
+// Enum values starting at InstructionVal are used for Instructions;
+// don't add new values here!
+
+HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function)
+HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone)
+HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue)
+HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone)
+HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray)
+HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector)
+
+#undef HANDLE_GLOBAL_VALUE
+#undef HANDLE_CONSTANT
+#undef HANDLE_INSTRUCTION
+#undef HANDLE_METADATA_VALUE
+#undef HANDLE_INLINE_ASM_VALUE
+#undef HANDLE_VALUE
+#undef HANDLE_CONSTANT_MARKER
diff --git a/third_party/llvm-subzero/include/llvm/IR/Value.h b/third_party/llvm-subzero/include/llvm/IR/Value.h
new file mode 100644
index 0000000..b3d318c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IR/Value.h
@@ -0,0 +1,817 @@
+//===-- llvm/Value.h - Definition of the Value class ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the Value class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_VALUE_H
+#define LLVM_IR_VALUE_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Use.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+
+class APInt;
+class Argument;
+class AssemblyAnnotationWriter;
+class BasicBlock;
+class Constant;
+class ConstantData;
+class ConstantAggregate;
+class DataLayout;
+class Function;
+class GlobalAlias;
+class GlobalIFunc;
+class GlobalIndirectSymbol;
+class GlobalObject;
+class GlobalValue;
+class GlobalVariable;
+class InlineAsm;
+class Instruction;
+class LLVMContext;
+class Module;
+class ModuleSlotTracker;
+class StringRef;
+class Twine;
+class Type;
+class ValueHandleBase;
+class ValueSymbolTable;
+class raw_ostream;
+
+template<typename ValueTy> class StringMapEntry;
+typedef StringMapEntry<Value*> ValueName;
+
+//===----------------------------------------------------------------------===//
+//                                 Value Class
+//===----------------------------------------------------------------------===//
+
+/// \brief LLVM Value Representation
+///
+/// This is a very important LLVM class. It is the base class of all values
+/// computed by a program that may be used as operands to other values. Value is
+/// the super class of other important classes such as Instruction and Function.
+/// All Values have a Type. Type is not a subclass of Value. Some values can
+/// have a name and they belong to some Module.  Setting the name on the Value
+/// automatically updates the module's symbol table.
+///
+/// Every value has a "use list" that keeps track of which other Values are
+/// using this Value.  A Value can also have an arbitrary number of ValueHandle
+/// objects that watch it and listen to RAUW and Destroy events.  See
+/// llvm/IR/ValueHandle.h for details.
+class Value {
+  Type *VTy;
+  Use *UseList;
+
+  friend class ValueAsMetadata; // Allow access to IsUsedByMD.
+  friend class ValueHandleBase;
+
+  const unsigned char SubclassID;   // Subclass identifier (for isa/dyn_cast)
+  unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?
+protected:
+  /// \brief Hold subclass data that can be dropped.
+  ///
+  /// This member is similar to SubclassData, however it is for holding
+  /// information which may be used to aid optimization, but which may be
+  /// cleared to zero without affecting conservative interpretation.
+  unsigned char SubclassOptionalData : 7;
+
+private:
+  /// \brief Hold arbitrary subclass data.
+  ///
+  /// This member is defined by this class, but is not used for anything.
+  /// Subclasses can use it to hold whatever state they find useful.  This
+  /// field is initialized to zero by the ctor.
+  unsigned short SubclassData;
+
+protected:
+  /// \brief The number of operands in the subclass.
+  ///
+  /// This member is defined by this class, but not used for anything.
+  /// Subclasses can use it to store their number of operands, if they have
+  /// any.
+  ///
+  /// This is stored here to save space in User on 64-bit hosts.  Since most
+  /// instances of Value have operands, 32-bit hosts aren't significantly
+  /// affected.
+  ///
+  /// Note, this should *NOT* be used directly by any class other than User.
+  /// User uses this value to find the Use list.
+  enum : unsigned { NumUserOperandsBits = 28 };
+  unsigned NumUserOperands : NumUserOperandsBits;
+
+  // Use the same type as the bitfield above so that MSVC will pack them.
+  unsigned IsUsedByMD : 1;
+  unsigned HasName : 1;
+  unsigned HasHungOffUses : 1;
+  unsigned HasDescriptor : 1;
+
+private:
+  template <typename UseT> // UseT == 'Use' or 'const Use'
+  class use_iterator_impl
+      : public std::iterator<std::forward_iterator_tag, UseT *> {
+    UseT *U;
+    explicit use_iterator_impl(UseT *u) : U(u) {}
+    friend class Value;
+
+  public:
+    use_iterator_impl() : U() {}
+
+    bool operator==(const use_iterator_impl &x) const { return U == x.U; }
+    bool operator!=(const use_iterator_impl &x) const { return !operator==(x); }
+
+    use_iterator_impl &operator++() { // Preincrement
+      assert(U && "Cannot increment end iterator!");
+      U = U->getNext();
+      return *this;
+    }
+    use_iterator_impl operator++(int) { // Postincrement
+      auto tmp = *this;
+      ++*this;
+      return tmp;
+    }
+
+    UseT &operator*() const {
+      assert(U && "Cannot dereference end iterator!");
+      return *U;
+    }
+
+    UseT *operator->() const { return &operator*(); }
+
+    operator use_iterator_impl<const UseT>() const {
+      return use_iterator_impl<const UseT>(U);
+    }
+  };
+
+  template <typename UserTy> // UserTy == 'User' or 'const User'
+  class user_iterator_impl
+      : public std::iterator<std::forward_iterator_tag, UserTy *> {
+    use_iterator_impl<Use> UI;
+    explicit user_iterator_impl(Use *U) : UI(U) {}
+    friend class Value;
+
+  public:
+    user_iterator_impl() {}
+
+    bool operator==(const user_iterator_impl &x) const { return UI == x.UI; }
+    bool operator!=(const user_iterator_impl &x) const { return !operator==(x); }
+
+    /// \brief Returns true if this iterator is equal to user_end() on the value.
+    bool atEnd() const { return *this == user_iterator_impl(); }
+
+    user_iterator_impl &operator++() { // Preincrement
+      ++UI;
+      return *this;
+    }
+    user_iterator_impl operator++(int) { // Postincrement
+      auto tmp = *this;
+      ++*this;
+      return tmp;
+    }
+
+    // Retrieve a pointer to the current User.
+    UserTy *operator*() const {
+      return UI->getUser();
+    }
+
+    UserTy *operator->() const { return operator*(); }
+
+    operator user_iterator_impl<const UserTy>() const {
+      return user_iterator_impl<const UserTy>(*UI);
+    }
+
+    Use &getUse() const { return *UI; }
+  };
+
+  void operator=(const Value &) = delete;
+  Value(const Value &) = delete;
+
+protected:
+  Value(Type *Ty, unsigned scid);
+public:
+  virtual ~Value();
+
+  /// \brief Support for debugging, callable in GDB: V->dump()
+  void dump() const;
+
+  /// \brief Implement operator<< on Value.
+  /// @{
+  void print(raw_ostream &O, bool IsForDebug = false) const;
+  void print(raw_ostream &O, ModuleSlotTracker &MST,
+             bool IsForDebug = false) const;
+  /// @}
+
+  /// \brief Print the name of this Value out to the specified raw_ostream.
+  ///
+  /// This is useful when you just want to print 'int %reg126', not the
+  /// instruction that generated it. If you specify a Module for context, then
+  /// even constanst get pretty-printed; for example, the type of a null
+  /// pointer is printed symbolically.
+  /// @{
+  void printAsOperand(raw_ostream &O, bool PrintType = true,
+                      const Module *M = nullptr) const;
+  void printAsOperand(raw_ostream &O, bool PrintType,
+                      ModuleSlotTracker &MST) const;
+  /// @}
+
+  /// \brief All values are typed, get the type of this value.
+  Type *getType() const { return VTy; }
+
+  /// \brief All values hold a context through their type.
+  LLVMContext &getContext() const;
+
+  // \brief All values can potentially be named.
+  bool hasName() const { return HasName; }
+  ValueName *getValueName() const;
+  void setValueName(ValueName *VN);
+
+private:
+  void destroyValueName();
+  void setNameImpl(const Twine &Name);
+
+public:
+  /// \brief Return a constant reference to the value's name.
+  ///
+  /// This is cheap and guaranteed to return the same reference as long as the
+  /// value is not modified.
+  StringRef getName() const;
+
+  /// \brief Change the name of the value.
+  ///
+  /// Choose a new unique name if the provided name is taken.
+  ///
+  /// \param Name The new name; or "" if the value's name should be removed.
+  void setName(const Twine &Name);
+
+
+  /// \brief Transfer the name from V to this value.
+  ///
+  /// After taking V's name, sets V's name to empty.
+  ///
+  /// \note It is an error to call V->takeName(V).
+  void takeName(Value *V);
+
+  /// \brief Change all uses of this to point to a new Value.
+  ///
+  /// Go through the uses list for this definition and make each use point to
+  /// "V" instead of "this".  After this completes, 'this's use list is
+  /// guaranteed to be empty.
+  void replaceAllUsesWith(Value *V);
+
+  /// replaceUsesOutsideBlock - Go through the uses list for this definition and
+  /// make each use point to "V" instead of "this" when the use is outside the
+  /// block. 'This's use list is expected to have at least one element.
+  /// Unlike replaceAllUsesWith this function does not support basic block
+  /// values or constant users.
+  void replaceUsesOutsideBlock(Value *V, BasicBlock *BB);
+
+  //----------------------------------------------------------------------
+  // Methods for handling the chain of uses of this Value.
+  //
+  // Materializing a function can introduce new uses, so these methods come in
+  // two variants:
+  // The methods that start with materialized_ check the uses that are
+  // currently known given which functions are materialized. Be very careful
+  // when using them since you might not get all uses.
+  // The methods that don't start with materialized_ assert that modules is
+  // fully materialized.
+  void assertModuleIsMaterialized() const;
+
+  bool use_empty() const {
+    assertModuleIsMaterialized();
+    return UseList == nullptr;
+  }
+
+  typedef use_iterator_impl<Use> use_iterator;
+  typedef use_iterator_impl<const Use> const_use_iterator;
+  use_iterator materialized_use_begin() { return use_iterator(UseList); }
+  const_use_iterator materialized_use_begin() const {
+    return const_use_iterator(UseList);
+  }
+  use_iterator use_begin() {
+    assertModuleIsMaterialized();
+    return materialized_use_begin();
+  }
+  const_use_iterator use_begin() const {
+    assertModuleIsMaterialized();
+    return materialized_use_begin();
+  }
+  use_iterator use_end() { return use_iterator(); }
+  const_use_iterator use_end() const { return const_use_iterator(); }
+  iterator_range<use_iterator> materialized_uses() {
+    return make_range(materialized_use_begin(), use_end());
+  }
+  iterator_range<const_use_iterator> materialized_uses() const {
+    return make_range(materialized_use_begin(), use_end());
+  }
+  iterator_range<use_iterator> uses() {
+    assertModuleIsMaterialized();
+    return materialized_uses();
+  }
+  iterator_range<const_use_iterator> uses() const {
+    assertModuleIsMaterialized();
+    return materialized_uses();
+  }
+
+  bool user_empty() const {
+    assertModuleIsMaterialized();
+    return UseList == nullptr;
+  }
+
+  typedef user_iterator_impl<User> user_iterator;
+  typedef user_iterator_impl<const User> const_user_iterator;
+  user_iterator materialized_user_begin() { return user_iterator(UseList); }
+  const_user_iterator materialized_user_begin() const {
+    return const_user_iterator(UseList);
+  }
+  user_iterator user_begin() {
+    assertModuleIsMaterialized();
+    return materialized_user_begin();
+  }
+  const_user_iterator user_begin() const {
+    assertModuleIsMaterialized();
+    return materialized_user_begin();
+  }
+  user_iterator user_end() { return user_iterator(); }
+  const_user_iterator user_end() const { return const_user_iterator(); }
+  User *user_back() {
+    assertModuleIsMaterialized();
+    return *materialized_user_begin();
+  }
+  const User *user_back() const {
+    assertModuleIsMaterialized();
+    return *materialized_user_begin();
+  }
+  iterator_range<user_iterator> materialized_users() {
+    return make_range(materialized_user_begin(), user_end());
+  }
+  iterator_range<const_user_iterator> materialized_users() const {
+    return make_range(materialized_user_begin(), user_end());
+  }
+  iterator_range<user_iterator> users() {
+    assertModuleIsMaterialized();
+    return materialized_users();
+  }
+  iterator_range<const_user_iterator> users() const {
+    assertModuleIsMaterialized();
+    return materialized_users();
+  }
+
+  /// \brief Return true if there is exactly one user of this value.
+  ///
+  /// This is specialized because it is a common request and does not require
+  /// traversing the whole use list.
+  bool hasOneUse() const {
+    const_use_iterator I = use_begin(), E = use_end();
+    if (I == E) return false;
+    return ++I == E;
+  }
+
+  /// \brief Return true if this Value has exactly N users.
+  bool hasNUses(unsigned N) const;
+
+  /// \brief Return true if this value has N users or more.
+  ///
+  /// This is logically equivalent to getNumUses() >= N.
+  bool hasNUsesOrMore(unsigned N) const;
+
+  /// \brief Check if this value is used in the specified basic block.
+  bool isUsedInBasicBlock(const BasicBlock *BB) const;
+
+  /// \brief This method computes the number of uses of this Value.
+  ///
+  /// This is a linear time operation.  Use hasOneUse, hasNUses, or
+  /// hasNUsesOrMore to check for specific values.
+  unsigned getNumUses() const;
+
+  /// \brief This method should only be used by the Use class.
+  void addUse(Use &U) { U.addToList(&UseList); }
+
+  /// \brief Concrete subclass of this.
+  ///
+  /// An enumeration for keeping track of the concrete subclass of Value that
+  /// is actually instantiated. Values of this enumeration are kept in the
+  /// Value classes SubclassID field. They are used for concrete type
+  /// identification.
+  enum ValueTy {
+#define HANDLE_VALUE(Name) Name##Val,
+#include "llvm/IR/Value.def"
+
+    // Markers:
+#define HANDLE_CONSTANT_MARKER(Marker, Constant) Marker = Constant##Val,
+#include "llvm/IR/Value.def"
+  };
+
+  /// \brief Return an ID for the concrete type of this object.
+  ///
+  /// This is used to implement the classof checks.  This should not be used
+  /// for any other purpose, as the values may change as LLVM evolves.  Also,
+  /// note that for instructions, the Instruction's opcode is added to
+  /// InstructionVal. So this means three things:
+  /// # there is no value with code InstructionVal (no opcode==0).
+  /// # there are more possible values for the value type than in ValueTy enum.
+  /// # the InstructionVal enumerator must be the highest valued enumerator in
+  ///   the ValueTy enum.
+  unsigned getValueID() const {
+    return SubclassID;
+  }
+
+  /// \brief Return the raw optional flags value contained in this value.
+  ///
+  /// This should only be used when testing two Values for equivalence.
+  unsigned getRawSubclassOptionalData() const {
+    return SubclassOptionalData;
+  }
+
+  /// \brief Clear the optional flags contained in this value.
+  void clearSubclassOptionalData() {
+    SubclassOptionalData = 0;
+  }
+
+  /// \brief Check the optional flags for equality.
+  bool hasSameSubclassOptionalData(const Value *V) const {
+    return SubclassOptionalData == V->SubclassOptionalData;
+  }
+
+  /// \brief Return true if there is a value handle associated with this value.
+  bool hasValueHandle() const { return HasValueHandle; }
+
+  /// \brief Return true if there is metadata referencing this value.
+  bool isUsedByMetadata() const { return IsUsedByMD; }
+
+  /// \brief Strip off pointer casts, all-zero GEPs, and aliases.
+  ///
+  /// Returns the original uncasted value.  If this is called on a non-pointer
+  /// value, it returns 'this'.
+  Value *stripPointerCasts();
+  const Value *stripPointerCasts() const {
+    return const_cast<Value*>(this)->stripPointerCasts();
+  }
+
+  /// \brief Strip off pointer casts and all-zero GEPs.
+  ///
+  /// Returns the original uncasted value.  If this is called on a non-pointer
+  /// value, it returns 'this'.
+  Value *stripPointerCastsNoFollowAliases();
+  const Value *stripPointerCastsNoFollowAliases() const {
+    return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases();
+  }
+
+  /// \brief Strip off pointer casts and all-constant inbounds GEPs.
+  ///
+  /// Returns the original pointer value.  If this is called on a non-pointer
+  /// value, it returns 'this'.
+  Value *stripInBoundsConstantOffsets();
+  const Value *stripInBoundsConstantOffsets() const {
+    return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
+  }
+
+  /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets().
+  ///
+  /// Stores the resulting constant offset stripped into the APInt provided.
+  /// The provided APInt will be extended or truncated as needed to be the
+  /// correct bitwidth for an offset of this pointer type.
+  ///
+  /// If this is called on a non-pointer value, it returns 'this'.
+  Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
+                                                   APInt &Offset);
+  const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
+                                                         APInt &Offset) const {
+    return const_cast<Value *>(this)
+        ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
+  }
+
+  /// \brief Strip off pointer casts and inbounds GEPs.
+  ///
+  /// Returns the original pointer value.  If this is called on a non-pointer
+  /// value, it returns 'this'.
+  Value *stripInBoundsOffsets();
+  const Value *stripInBoundsOffsets() const {
+    return const_cast<Value*>(this)->stripInBoundsOffsets();
+  }
+
+  /// \brief Returns the number of bytes known to be dereferenceable for the
+  /// pointer value.
+  ///
+  /// If CanBeNull is set by this function the pointer can either be null or be
+  /// dereferenceable up to the returned number of bytes.
+  unsigned getPointerDereferenceableBytes(const DataLayout &DL,
+                                          bool &CanBeNull) const;
+
+  /// \brief Returns an alignment of the pointer value.
+  ///
+  /// Returns an alignment which is either specified explicitly, e.g. via
+  /// align attribute of a function argument, or guaranteed by DataLayout.
+  unsigned getPointerAlignment(const DataLayout &DL) const;
+
+  /// \brief Translate PHI node to its predecessor from the given basic block.
+  ///
+  /// If this value is a PHI node with CurBB as its parent, return the value in
+  /// the PHI node corresponding to PredBB.  If not, return ourself.  This is
+  /// useful if you want to know the value something has in a predecessor
+  /// block.
+  Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB);
+
+  const Value *DoPHITranslation(const BasicBlock *CurBB,
+                                const BasicBlock *PredBB) const{
+    return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB);
+  }
+
+  /// \brief The maximum alignment for instructions.
+  ///
+  /// This is the greatest alignment value supported by load, store, and alloca
+  /// instructions, and global values.
+  static const unsigned MaxAlignmentExponent = 29;
+  static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent;
+
+  /// \brief Mutate the type of this Value to be of the specified type.
+  ///
+  /// Note that this is an extremely dangerous operation which can create
+  /// completely invalid IR very easily.  It is strongly recommended that you
+  /// recreate IR objects with the right types instead of mutating them in
+  /// place.
+  void mutateType(Type *Ty) {
+    VTy = Ty;
+  }
+
+  /// \brief Sort the use-list.
+  ///
+  /// Sorts the Value's use-list by Cmp using a stable mergesort.  Cmp is
+  /// expected to compare two \a Use references.
+  template <class Compare> void sortUseList(Compare Cmp);
+
+  /// \brief Reverse the use-list.
+  void reverseUseList();
+
+private:
+  /// \brief Merge two lists together.
+  ///
+  /// Merges \c L and \c R using \c Cmp.  To enable stable sorts, always pushes
+  /// "equal" items from L before items from R.
+  ///
+  /// \return the first element in the list.
+  ///
+  /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update).
+  template <class Compare>
+  static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) {
+    Use *Merged;
+    Use **Next = &Merged;
+
+    for (;;) {
+      if (!L) {
+        *Next = R;
+        break;
+      }
+      if (!R) {
+        *Next = L;
+        break;
+      }
+      if (Cmp(*R, *L)) {
+        *Next = R;
+        Next = &R->Next;
+        R = R->Next;
+      } else {
+        *Next = L;
+        Next = &L->Next;
+        L = L->Next;
+      }
+    }
+
+    return Merged;
+  }
+
+  /// \brief Tail-recursive helper for \a mergeUseLists().
+  ///
+  /// \param[out] Next the first element in the list.
+  template <class Compare>
+  static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp);
+
+protected:
+  unsigned short getSubclassDataFromValue() const { return SubclassData; }
+  void setValueSubclassData(unsigned short D) { SubclassData = D; }
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
+  V.print(OS);
+  return OS;
+}
+
+void Use::set(Value *V) {
+  if (Val) removeFromList();
+  Val = V;
+  if (V) V->addUse(*this);
+}
+
+Value *Use::operator=(Value *RHS) {
+  set(RHS);
+  return RHS;
+}
+
+const Use &Use::operator=(const Use &RHS) {
+  set(RHS.Val);
+  return *this;
+}
+
+template <class Compare> void Value::sortUseList(Compare Cmp) {
+  if (!UseList || !UseList->Next)
+    // No need to sort 0 or 1 uses.
+    return;
+
+  // Note: this function completely ignores Prev pointers until the end when
+  // they're fixed en masse.
+
+  // Create a binomial vector of sorted lists, visiting uses one at a time and
+  // merging lists as necessary.
+  const unsigned MaxSlots = 32;
+  Use *Slots[MaxSlots];
+
+  // Collect the first use, turning it into a single-item list.
+  Use *Next = UseList->Next;
+  UseList->Next = nullptr;
+  unsigned NumSlots = 1;
+  Slots[0] = UseList;
+
+  // Collect all but the last use.
+  while (Next->Next) {
+    Use *Current = Next;
+    Next = Current->Next;
+
+    // Turn Current into a single-item list.
+    Current->Next = nullptr;
+
+    // Save Current in the first available slot, merging on collisions.
+    unsigned I;
+    for (I = 0; I < NumSlots; ++I) {
+      if (!Slots[I])
+        break;
+
+      // Merge two lists, doubling the size of Current and emptying slot I.
+      //
+      // Since the uses in Slots[I] originally preceded those in Current, send
+      // Slots[I] in as the left parameter to maintain a stable sort.
+      Current = mergeUseLists(Slots[I], Current, Cmp);
+      Slots[I] = nullptr;
+    }
+    // Check if this is a new slot.
+    if (I == NumSlots) {
+      ++NumSlots;
+      assert(NumSlots <= MaxSlots && "Use list bigger than 2^32");
+    }
+
+    // Found an open slot.
+    Slots[I] = Current;
+  }
+
+  // Merge all the lists together.
+  assert(Next && "Expected one more Use");
+  assert(!Next->Next && "Expected only one Use");
+  UseList = Next;
+  for (unsigned I = 0; I < NumSlots; ++I)
+    if (Slots[I])
+      // Since the uses in Slots[I] originally preceded those in UseList, send
+      // Slots[I] in as the left parameter to maintain a stable sort.
+      UseList = mergeUseLists(Slots[I], UseList, Cmp);
+
+  // Fix the Prev pointers.
+  for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) {
+    I->setPrev(Prev);
+    Prev = &I->Next;
+  }
+}
+
+// isa - Provide some specializations of isa so that we don't have to include
+// the subtype header files to test to see if the value is a subclass...
+//
+template <> struct isa_impl<Constant, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() >= Value::ConstantFirstVal &&
+      Val.getValueID() <= Value::ConstantLastVal;
+  }
+};
+
+template <> struct isa_impl<ConstantData, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() >= Value::ConstantDataFirstVal &&
+           Val.getValueID() <= Value::ConstantDataLastVal;
+  }
+};
+
+template <> struct isa_impl<ConstantAggregate, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() >= Value::ConstantAggregateFirstVal &&
+           Val.getValueID() <= Value::ConstantAggregateLastVal;
+  }
+};
+
+template <> struct isa_impl<Argument, Value> {
+  static inline bool doit (const Value &Val) {
+    return Val.getValueID() == Value::ArgumentVal;
+  }
+};
+
+template <> struct isa_impl<InlineAsm, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() == Value::InlineAsmVal;
+  }
+};
+
+template <> struct isa_impl<Instruction, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() >= Value::InstructionVal;
+  }
+};
+
+template <> struct isa_impl<BasicBlock, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() == Value::BasicBlockVal;
+  }
+};
+
+template <> struct isa_impl<Function, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() == Value::FunctionVal;
+  }
+};
+
+template <> struct isa_impl<GlobalVariable, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() == Value::GlobalVariableVal;
+  }
+};
+
+template <> struct isa_impl<GlobalAlias, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() == Value::GlobalAliasVal;
+  }
+};
+
+template <> struct isa_impl<GlobalIFunc, Value> {
+  static inline bool doit(const Value &Val) {
+    return Val.getValueID() == Value::GlobalIFuncVal;
+  }
+};
+
+template <> struct isa_impl<GlobalIndirectSymbol, Value> {
+  static inline bool doit(const Value &Val) {
+    return isa<GlobalAlias>(Val) || isa<GlobalIFunc>(Val);
+  }
+};
+
+template <> struct isa_impl<GlobalValue, Value> {
+  static inline bool doit(const Value &Val) {
+    return isa<GlobalObject>(Val) || isa<GlobalIndirectSymbol>(Val);
+  }
+};
+
+template <> struct isa_impl<GlobalObject, Value> {
+  static inline bool doit(const Value &Val) {
+    return isa<GlobalVariable>(Val) || isa<Function>(Val);
+  }
+};
+
+// Value* is only 4-byte aligned.
+template<>
+class PointerLikeTypeTraits<Value*> {
+  typedef Value* PT;
+public:
+  static inline void *getAsVoidPointer(PT P) { return P; }
+  static inline PT getFromVoidPointer(void *P) {
+    return static_cast<PT>(P);
+  }
+  enum { NumLowBitsAvailable = 2 };
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef)
+
+// Specialized opaque value conversions.
+inline Value **unwrap(LLVMValueRef *Vals) {
+  return reinterpret_cast<Value**>(Vals);
+}
+
+template<typename T>
+inline T **unwrap(LLVMValueRef *Vals, unsigned Length) {
+#ifndef NDEBUG
+  for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I)
+    unwrap<T>(*I); // For side effect of calling assert on invalid usage.
+#endif
+  (void)Length;
+  return reinterpret_cast<T**>(Vals);
+}
+
+inline LLVMValueRef *wrap(const Value **Vals) {
+  return reinterpret_cast<LLVMValueRef*>(const_cast<Value**>(Vals));
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/IRReader/IRReader.h b/third_party/llvm-subzero/include/llvm/IRReader/IRReader.h
new file mode 100644
index 0000000..7b24ec1
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/IRReader/IRReader.h
@@ -0,0 +1,50 @@
+//===---- llvm/IRReader/IRReader.h - Reader for LLVM IR files ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions for reading LLVM IR. They support both
+// Bitcode and Assembly, automatically detecting the input format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IRREADER_IRREADER_H
+#define LLVM_IRREADER_IRREADER_H
+
+#include <memory>
+
+namespace llvm {
+
+class StringRef;
+class MemoryBufferRef;
+class Module;
+class SMDiagnostic;
+class LLVMContext;
+
+/// If the given file holds a bitcode image, return a Module
+/// for it which does lazy deserialization of function bodies.  Otherwise,
+/// attempt to parse it as LLVM Assembly and return a fully populated
+/// Module. The ShouldLazyLoadMetadata flag is passed down to the bitcode
+/// reader to optionally enable lazy metadata loading.
+std::unique_ptr<Module>
+getLazyIRFileModule(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
+                    bool ShouldLazyLoadMetadata = false);
+
+/// If the given MemoryBuffer holds a bitcode image, return a Module
+/// for it.  Otherwise, attempt to parse it as LLVM Assembly and return
+/// a Module for it.
+std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err,
+                                LLVMContext &Context);
+
+/// If the given file holds a bitcode image, return a Module for it.
+/// Otherwise, attempt to parse it as LLVM Assembly and return a Module
+/// for it.
+std::unique_ptr<Module> parseIRFile(StringRef Filename, SMDiagnostic &Err,
+                                    LLVMContext &Context);
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/AArch64TargetParser.def b/third_party/llvm-subzero/include/llvm/Support/AArch64TargetParser.def
new file mode 100644
index 0000000..a2e30e7
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/AArch64TargetParser.def
@@ -0,0 +1,75 @@
+//===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides defines to build up the AARCH64 target parser's logic.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef AARCH64_ARCH
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
+#endif
+AARCH64_ARCH("invalid", AK_INVALID, nullptr, nullptr,
+             ARMBuildAttrs::CPUArch::v8_A, FK_NONE, AArch64::AEK_NONE)
+AARCH64_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
+             FK_CRYPTO_NEON_FP_ARMV8,
+             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+              AArch64::AEK_SIMD))
+AARCH64_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a",
+             ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+              AArch64::AEK_SIMD))
+AARCH64_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a",
+             ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+             (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+              AArch64::AEK_SIMD | AArch64::AEK_RAS))
+#undef AARCH64_ARCH
+
+#ifndef AARCH64_ARCH_EXT_NAME
+#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
+#endif
+// FIXME: This would be nicer were it tablegen
+AARCH64_ARCH_EXT_NAME("invalid",  AArch64::AEK_INVALID,  nullptr,  nullptr)
+AARCH64_ARCH_EXT_NAME("none",     AArch64::AEK_NONE,     nullptr,  nullptr)
+AARCH64_ARCH_EXT_NAME("crc",      AArch64::AEK_CRC,      "+crc",   "-crc")
+AARCH64_ARCH_EXT_NAME("crypto",   AArch64::AEK_CRYPTO,   "+crypto","-crypto")
+AARCH64_ARCH_EXT_NAME("fp",       AArch64::AEK_FP,       "+fp-armv8",  "-fp-armv8")
+AARCH64_ARCH_EXT_NAME("simd",     AArch64::AEK_SIMD,     "+neon",  "-neon")
+AARCH64_ARCH_EXT_NAME("fp16",     AArch64::AEK_FP16,     "+fullfp16",  "-fullfp16")
+AARCH64_ARCH_EXT_NAME("profile",     AArch64::AEK_PROFILE,     "+spe",  "-spe")
+AARCH64_ARCH_EXT_NAME("ras",     AArch64::AEK_RAS,     "+ras",  "-ras")
+#undef AARCH64_ARCH_EXT_NAME
+
+#ifndef AARCH64_CPU_NAME
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
+#endif
+AARCH64_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
+                ( AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("vulcan", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
+                (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+// Invalid CPU
+AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
+#undef AARCH64_CPU_NAME
diff --git a/third_party/llvm-subzero/include/llvm/Support/ARMBuildAttributes.h b/third_party/llvm-subzero/include/llvm/Support/ARMBuildAttributes.h
new file mode 100644
index 0000000..f447cd0
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ARMBuildAttributes.h
@@ -0,0 +1,233 @@
+//===-- ARMBuildAttributes.h - ARM Build Attributes -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations and support routines for ARM build attributes
+// as defined in ARM ABI addenda document (ABI release 2.08).
+//
+// ELF for the ARM Architecture r2.09 - November 30, 2012
+//
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
+#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
+
+namespace llvm {
+class StringRef;
+
+namespace ARMBuildAttrs {
+
+enum SpecialAttr {
+  // This is for the .cpu asm attr. It translates into one or more
+  // AttrType (below) entries in the .ARM.attributes section in the ELF.
+  SEL_CPU
+};
+
+enum AttrType {
+  // Rest correspond to ELF/.ARM.attributes
+  File                      = 1,
+  CPU_raw_name              = 4,
+  CPU_name                  = 5,
+  CPU_arch                  = 6,
+  CPU_arch_profile          = 7,
+  ARM_ISA_use               = 8,
+  THUMB_ISA_use             = 9,
+  FP_arch                   = 10,
+  WMMX_arch                 = 11,
+  Advanced_SIMD_arch        = 12,
+  PCS_config                = 13,
+  ABI_PCS_R9_use            = 14,
+  ABI_PCS_RW_data           = 15,
+  ABI_PCS_RO_data           = 16,
+  ABI_PCS_GOT_use           = 17,
+  ABI_PCS_wchar_t           = 18,
+  ABI_FP_rounding           = 19,
+  ABI_FP_denormal           = 20,
+  ABI_FP_exceptions         = 21,
+  ABI_FP_user_exceptions    = 22,
+  ABI_FP_number_model       = 23,
+  ABI_align_needed          = 24,
+  ABI_align_preserved       = 25,
+  ABI_enum_size             = 26,
+  ABI_HardFP_use            = 27,
+  ABI_VFP_args              = 28,
+  ABI_WMMX_args             = 29,
+  ABI_optimization_goals    = 30,
+  ABI_FP_optimization_goals = 31,
+  compatibility             = 32,
+  CPU_unaligned_access      = 34,
+  FP_HP_extension           = 36,
+  ABI_FP_16bit_format       = 38,
+  MPextension_use           = 42, // recoded from 70 (ABI r2.08)
+  DIV_use                   = 44,
+  DSP_extension             = 46,
+  also_compatible_with      = 65,
+  conformance               = 67,
+  Virtualization_use        = 68,
+
+  /// Legacy Tags
+  Section                   = 2,  // deprecated (ABI r2.09)
+  Symbol                    = 3,  // deprecated (ABI r2.09)
+  ABI_align8_needed         = 24, // renamed to ABI_align_needed (ABI r2.09)
+  ABI_align8_preserved      = 25, // renamed to ABI_align_preserved (ABI r2.09)
+  nodefaults                = 64, // deprecated (ABI r2.09)
+  T2EE_use                  = 66, // deprecated (ABI r2.09)
+  MPextension_use_old       = 70  // recoded to MPextension_use (ABI r2.08)
+};
+
+StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true);
+StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
+int AttrTypeFromString(StringRef Tag);
+
+// Magic numbers for .ARM.attributes
+enum AttrMagic {
+  Format_Version  = 0x41
+};
+
+// Legal Values for CPU_arch, (=6), uleb128
+enum CPUArch {
+  Pre_v4   = 0,
+  v4       = 1,   // e.g. SA110
+  v4T      = 2,   // e.g. ARM7TDMI
+  v5T      = 3,   // e.g. ARM9TDMI
+  v5TE     = 4,   // e.g. ARM946E_S
+  v5TEJ    = 5,   // e.g. ARM926EJ_S
+  v6       = 6,   // e.g. ARM1136J_S
+  v6KZ     = 7,   // e.g. ARM1176JZ_S
+  v6T2     = 8,   // e.g. ARM1156T2_S
+  v6K      = 9,   // e.g. ARM1176JZ_S
+  v7       = 10,  // e.g. Cortex A8, Cortex M3
+  v6_M     = 11,  // e.g. Cortex M1
+  v6S_M    = 12,  // v6_M with the System extensions
+  v7E_M    = 13,  // v7_M with DSP extensions
+  v8_A     = 14,  // v8_A AArch32
+  v8_M_Base= 16,  // v8_M_Base AArch32
+  v8_M_Main= 17,  // v8_M_Main AArch32
+};
+
+enum CPUArchProfile {               // (=7), uleb128
+  Not_Applicable          = 0,      // pre v7, or cross-profile code
+  ApplicationProfile      = (0x41), // 'A' (e.g. for Cortex A8)
+  RealTimeProfile         = (0x52), // 'R' (e.g. for Cortex R4)
+  MicroControllerProfile  = (0x4D), // 'M' (e.g. for Cortex M3)
+  SystemProfile           = (0x53)  // 'S' Application or real-time profile
+};
+
+// The following have a lot of common use cases
+enum {
+  Not_Allowed = 0,
+  Allowed = 1,
+
+  // Tag_ARM_ISA_use (=8), uleb128
+
+  // Tag_THUMB_ISA_use, (=9), uleb128
+  AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions)
+  AllowThumbDerived = 3, // Thumb allowed, derived from arch/profile
+
+  // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10)
+  AllowFPv2  = 2,     // v2 FP ISA permitted (implies use of the v1 FP ISA)
+  AllowFPv3A = 3,     // v3 FP ISA permitted (implies use of the v2 FP ISA)
+  AllowFPv3B = 4,     // v3 FP ISA permitted, but only D0-D15, S0-S31
+  AllowFPv4A = 5,     // v4 FP ISA permitted (implies use of v3 FP ISA)
+  AllowFPv4B = 6,     // v4 FP ISA was permitted, but only D0-D15, S0-S31
+  AllowFPARMv8A = 7,  // Use of the ARM v8-A FP ISA was permitted
+  AllowFPARMv8B = 8,  // Use of the ARM v8-A FP ISA was permitted, but only
+                      // D0-D15, S0-S31
+
+  // Tag_WMMX_arch, (=11), uleb128
+  AllowWMMXv1 = 1,  // The user permitted this entity to use WMMX v1
+  AllowWMMXv2 = 2,  // The user permitted this entity to use WMMX v2
+
+  // Tag_Advanced_SIMD_arch, (=12), uleb128
+  AllowNeon = 1,      // SIMDv1 was permitted
+  AllowNeon2 = 2,     // SIMDv2 was permitted (Half-precision FP, MAC operations)
+  AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
+  AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA)
+
+  // Tag_ABI_PCS_R9_use, (=14), uleb128
+  R9IsGPR = 0,        // R9 used as v6 (just another callee-saved register)
+  R9IsSB = 1,         // R9 used as a global static base rgister
+  R9IsTLSPointer = 2, // R9 used as a thread local storage pointer
+  R9Reserved = 3,     // R9 not used by code associated with attributed entity
+
+  // Tag_ABI_PCS_RW_data, (=15), uleb128
+  AddressRWPCRel = 1, // Address RW static data PC-relative
+  AddressRWSBRel = 2, // Address RW static data SB-relative
+  AddressRWNone = 3, // No RW static data permitted
+
+  // Tag_ABI_PCS_RO_data, (=14), uleb128
+  AddressROPCRel = 1, // Address RO static data PC-relative
+  AddressRONone = 2, // No RO static data permitted
+
+  // Tag_ABI_PCS_GOT_use, (=17), uleb128
+  AddressDirect = 1, // Address imported data directly
+  AddressGOT = 2, // Address imported data indirectly (via GOT)
+
+  // Tag_ABI_PCS_wchar_t, (=18), uleb128
+  WCharProhibited = 0,  // wchar_t is not used
+  WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2
+  WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4
+
+  // Tag_ABI_FP_denormal, (=20), uleb128
+  PositiveZero = 0,
+  IEEEDenormals = 1,
+  PreserveFPSign = 2, // sign when flushed-to-zero is preserved
+
+  // Tag_ABI_FP_number_model, (=23), uleb128
+  AllowRTABI = 2,  // numbers, infinities, and one quiet NaN (see [RTABI])
+  AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
+
+  // Tag_ABI_enum_size, (=26), uleb128
+  EnumProhibited = 0, // The user prohibited the use of enums when building
+                      // this entity.
+  EnumSmallest = 1,   // Enum is smallest container big enough to hold all
+                      // values.
+  Enum32Bit = 2,      // Enum is at least 32 bits.
+  Enum32BitABI = 3,   // Every enumeration visible across an ABI-complying
+                      // interface contains a value needing 32 bits to encode
+                      // it; other enums can be containerized.
+
+  // Tag_ABI_HardFP_use, (=27), uleb128
+  HardFPImplied = 0,          // FP use should be implied by Tag_FP_arch
+  HardFPSinglePrecision = 1,  // Single-precision only
+
+  // Tag_ABI_VFP_args, (=28), uleb128
+  BaseAAPCS = 0,
+  HardFPAAPCS = 1,
+
+  // Tag_FP_HP_extension, (=36), uleb128
+  AllowHPFP = 1, // Allow use of Half Precision FP
+
+  // Tag_FP_16bit_format, (=38), uleb128
+  FP16FormatIEEE = 1,
+
+  // Tag_MPextension_use, (=42), uleb128
+  AllowMP = 1, // Allow use of MP extensions
+
+  // Tag_DIV_use, (=44), uleb128
+  // Note: AllowDIVExt must be emitted if and only if the permission to use
+  // hardware divide cannot be conveyed using AllowDIVIfExists or DisallowDIV
+  AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no
+                        // info exists.
+  DisallowDIV = 1,      // Hardware divide explicitly disallowed.
+  AllowDIVExt = 2,      // Allow hardware divide as optional architecture
+                        // extension above the base arch specified by
+                        // Tag_CPU_arch and Tag_CPU_arch_profile.
+
+  // Tag_Virtualization_use, (=68), uleb128
+  AllowTZ = 1,
+  AllowVirtualization = 2,
+  AllowTZVirtualization = 3
+};
+
+} // namespace ARMBuildAttrs
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ARMTargetParser.def b/third_party/llvm-subzero/include/llvm/Support/ARMTargetParser.def
new file mode 100644
index 0000000..49e6860
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ARMTargetParser.def
@@ -0,0 +1,243 @@
+//===- ARMTargetParser.def - ARM target parsing defines ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides defines to build up the ARM target parser's logic.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef ARM_FPU
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION)
+#endif
+ARM_FPU("invalid", FK_INVALID, FV_NONE, NS_None, FR_None)
+ARM_FPU("none", FK_NONE, FV_NONE, NS_None, FR_None)
+ARM_FPU("vfp", FK_VFP, FV_VFPV2, NS_None, FR_None)
+ARM_FPU("vfpv2", FK_VFPV2, FV_VFPV2, NS_None, FR_None)
+ARM_FPU("vfpv3", FK_VFPV3, FV_VFPV3, NS_None, FR_None)
+ARM_FPU("vfpv3-fp16", FK_VFPV3_FP16, FV_VFPV3_FP16, NS_None, FR_None)
+ARM_FPU("vfpv3-d16", FK_VFPV3_D16, FV_VFPV3, NS_None, FR_D16)
+ARM_FPU("vfpv3-d16-fp16", FK_VFPV3_D16_FP16, FV_VFPV3_FP16, NS_None, FR_D16)
+ARM_FPU("vfpv3xd", FK_VFPV3XD, FV_VFPV3, NS_None, FR_SP_D16)
+ARM_FPU("vfpv3xd-fp16", FK_VFPV3XD_FP16, FV_VFPV3_FP16, NS_None, FR_SP_D16)
+ARM_FPU("vfpv4", FK_VFPV4, FV_VFPV4, NS_None, FR_None)
+ARM_FPU("vfpv4-d16", FK_VFPV4_D16, FV_VFPV4, NS_None, FR_D16)
+ARM_FPU("fpv4-sp-d16", FK_FPV4_SP_D16, FV_VFPV4, NS_None, FR_SP_D16)
+ARM_FPU("fpv5-d16", FK_FPV5_D16, FV_VFPV5, NS_None, FR_D16)
+ARM_FPU("fpv5-sp-d16", FK_FPV5_SP_D16, FV_VFPV5, NS_None, FR_SP_D16)
+ARM_FPU("fp-armv8", FK_FP_ARMV8, FV_VFPV5, NS_None, FR_None)
+ARM_FPU("neon", FK_NEON, FV_VFPV3, NS_Neon, FR_None)
+ARM_FPU("neon-fp16", FK_NEON_FP16, FV_VFPV3_FP16, NS_Neon, FR_None)
+ARM_FPU("neon-vfpv4", FK_NEON_VFPV4, FV_VFPV4, NS_Neon, FR_None)
+ARM_FPU("neon-fp-armv8", FK_NEON_FP_ARMV8, FV_VFPV5, NS_Neon, FR_None)
+ARM_FPU("crypto-neon-fp-armv8", FK_CRYPTO_NEON_FP_ARMV8, FV_VFPV5, NS_Crypto,
+        FR_None)
+ARM_FPU("softvfp", FK_SOFTVFP, FV_NONE, NS_None, FR_None)
+#undef ARM_FPU
+
+#ifndef ARM_ARCH
+#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
+#endif
+ARM_ARCH("invalid", AK_INVALID, nullptr, nullptr,
+          ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv2", AK_ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv2a", AK_ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv3", AK_ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv3m", AK_ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv4", AK_ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv4t", AK_ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv5t", AK_ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv5te", AK_ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE,
+          FK_NONE, ARM::AEK_DSP)
+ARM_ARCH("armv5tej", AK_ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ,
+          FK_NONE, ARM::AEK_DSP)
+ARM_ARCH("armv6", AK_ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6,
+          FK_VFPV2, ARM::AEK_DSP)
+ARM_ARCH("armv6k", AK_ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K,
+          FK_VFPV2, ARM::AEK_DSP)
+ARM_ARCH("armv6t2", AK_ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2,
+          FK_NONE, ARM::AEK_DSP)
+ARM_ARCH("armv6kz", AK_ARMV6KZ, "6KZ", "v6kz", ARMBuildAttrs::CPUArch::v6KZ,
+          FK_VFPV2, (ARM::AEK_SEC | ARM::AEK_DSP))
+ARM_ARCH("armv6-m", AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv7-a", AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7,
+          FK_NEON, ARM::AEK_DSP)
+ARM_ARCH("armv7-r", AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7,
+          FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
+ARM_ARCH("armv7-m", AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7,
+          FK_NONE, ARM::AEK_HWDIV)
+ARM_ARCH("armv7e-m", AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M,
+          FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
+ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
+         FK_CRYPTO_NEON_FP_ARMV8,
+         (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+          ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a",
+         ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+         (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+          ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a",
+         ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+         (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+          ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
+ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base",
+          ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIV)
+ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main",
+          ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIV)
+// Non-standard Arch names.
+ARM_ARCH("iwmmxt", AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("iwmmxt2", AK_IWMMXT2, "iwmmxt2", "", ARMBuildAttrs::CPUArch::v5TE,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("xscale", AK_XSCALE, "xscale", "v5e", ARMBuildAttrs::CPUArch::v5TE,
+          FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv7s", AK_ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7,
+          FK_NEON_VFPV4, ARM::AEK_DSP)
+ARM_ARCH("armv7k", AK_ARMV7K, "7-K", "v7k", ARMBuildAttrs::CPUArch::v7,
+          FK_NONE, ARM::AEK_DSP)
+#undef ARM_ARCH
+
+#ifndef ARM_ARCH_EXT_NAME
+#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
+#endif
+// FIXME: This would be nicer were it tablegen
+ARM_ARCH_EXT_NAME("invalid",  ARM::AEK_INVALID,  nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("none",     ARM::AEK_NONE,     nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("crc",      ARM::AEK_CRC,      "+crc",   "-crc")
+ARM_ARCH_EXT_NAME("crypto",   ARM::AEK_CRYPTO,   "+crypto","-crypto")
+ARM_ARCH_EXT_NAME("dsp",      ARM::AEK_DSP,      "+dsp",   "-dsp")
+ARM_ARCH_EXT_NAME("fp",       ARM::AEK_FP,       nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("idiv",     (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV), nullptr, nullptr)
+ARM_ARCH_EXT_NAME("mp",       ARM::AEK_MP,       nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("simd",     ARM::AEK_SIMD,     nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("sec",      ARM::AEK_SEC,      nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("virt",     ARM::AEK_VIRT,     nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("fp16",     ARM::AEK_FP16,     "+fullfp16",  "-fullfp16")
+ARM_ARCH_EXT_NAME("ras",      ARM::AEK_RAS,      "+ras", "-ras")
+ARM_ARCH_EXT_NAME("os",       ARM::AEK_OS,       nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("iwmmxt",   ARM::AEK_IWMMXT,   nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("iwmmxt2",  ARM::AEK_IWMMXT2,  nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr,  nullptr)
+ARM_ARCH_EXT_NAME("xscale",   ARM::AEK_XSCALE,   nullptr,  nullptr)
+#undef ARM_ARCH_EXT_NAME
+
+#ifndef ARM_HW_DIV_NAME
+#define ARM_HW_DIV_NAME(NAME, ID)
+#endif
+ARM_HW_DIV_NAME("invalid", ARM::AEK_INVALID)
+ARM_HW_DIV_NAME("none", ARM::AEK_NONE)
+ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIV)
+ARM_HW_DIV_NAME("arm", ARM::AEK_HWDIVARM)
+ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
+#undef ARM_HW_DIV_NAME
+
+#ifndef ARM_CPU_NAME
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
+#endif
+ARM_CPU_NAME("arm2", AK_ARMV2, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm3", AK_ARMV2A, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm6", AK_ARMV3, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7m", AK_ARMV3M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm8", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm810", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm", AK_ARMV4, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm1100", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm1110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7tdmi", AK_ARMV4T, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7tdmi-s", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm710t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm720t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9tdmi", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm920", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm920t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm922t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm940t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("ep9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm10tdmi", AK_ARMV5T, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1020t", AK_ARMV5T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm946e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm966e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm968e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm10e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1020e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1022e", AK_ARMV5TE, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm926ej-s", AK_ARMV5TEJ, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136j-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136jf-s", AK_ARMV6, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136jz-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176j-s", AK_ARMV6K, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176jz-s", AK_ARMV6KZ, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("mpcore", AK_ARMV6K, FK_VFPV2, false, ARM::AEK_NONE)
+ARM_CPU_NAME("mpcorenovfp", AK_ARMV6K, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176jzf-s", AK_ARMV6KZ, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1156t2-s", AK_ARMV6T2, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1156t2f-s", AK_ARMV6T2, FK_VFPV2, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m0", AK_ARMV6M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m0plus", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m1", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("sc000", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false,
+             (ARM::AEK_SEC | ARM::AEK_MP))
+ARM_CPU_NAME("cortex-a7", AK_ARMV7A, FK_NEON_VFPV4, false,
+             (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+              ARM::AEK_HWDIV))
+ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, ARM::AEK_SEC)
+ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP))
+ARM_CPU_NAME("cortex-a12", AK_ARMV7A, FK_NEON_VFPV4, false,
+             (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+              ARM::AEK_HWDIV))
+ARM_CPU_NAME("cortex-a15", AK_ARMV7A, FK_NEON_VFPV4, false,
+             (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+              ARM::AEK_HWDIV))
+ARM_CPU_NAME("cortex-a17", AK_ARMV7A, FK_NEON_VFPV4, false,
+             (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+              ARM::AEK_HWDIV))
+ARM_CPU_NAME("krait", AK_ARMV7A, FK_NEON_VFPV4, false,
+             (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
+ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-r5", AK_ARMV7R, FK_VFPV3_D16, false,
+             (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("cortex-r7", AK_ARMV7R, FK_VFPV3_D16_FP16, false,
+             (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("cortex-r8", AK_ARMV7R, FK_VFPV3_D16_FP16, false,
+             (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+// Non-standard Arch names.
+ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("swift", AK_ARMV7S, FK_NEON_VFPV4, true,
+             (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
+// Invalid CPU
+ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, ARM::AEK_INVALID)
+#undef ARM_CPU_NAME
diff --git a/third_party/llvm-subzero/include/llvm/Support/AlignOf.h b/third_party/llvm-subzero/include/llvm/Support/AlignOf.h
new file mode 100644
index 0000000..333bf16
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/AlignOf.h
@@ -0,0 +1,259 @@
+//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AlignOf function that computes alignments for
+// arbitrary types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALIGNOF_H
+#define LLVM_SUPPORT_ALIGNOF_H
+
+#include "llvm/Support/Compiler.h"
+#include <cstddef>
+#include <type_traits>
+
+namespace llvm {
+
+namespace detail {
+
+// For everything other than an abstract class we can calulate alignment by
+// building a class with a single character and a member of the given type.
+template <typename T, bool = std::is_abstract<T>::value>
+struct AlignmentCalcImpl {
+  char x;
+#if defined(_MSC_VER)
+// Disables "structure was padded due to __declspec(align())" warnings that are
+// generated by any class using AlignOf<T> with a manually specified alignment.
+// Although the warning is disabled in the LLVM project we need this pragma
+// as AlignOf.h is a published support header that's available for use
+// out-of-tree, and we would like that to compile cleanly at /W4.
+#pragma warning(suppress : 4324)
+#endif
+  T t;
+private:
+  AlignmentCalcImpl() = delete;
+};
+
+// Abstract base class helper, this will have the minimal alignment and size
+// for any abstract class. We don't even define its destructor because this
+// type should never be used in a way that requires it.
+struct AlignmentCalcImplBase {
+  virtual ~AlignmentCalcImplBase() = 0;
+};
+
+// When we have an abstract class type, specialize the alignment computation
+// engine to create another abstract class that derives from both an empty
+// abstract base class and the provided type. This has the same effect as the
+// above except that it handles the fact that we can't actually create a member
+// of type T.
+template <typename T>
+struct AlignmentCalcImpl<T, true> : AlignmentCalcImplBase, T {
+  ~AlignmentCalcImpl() override = 0;
+};
+
+} // End detail namespace.
+
+/// AlignOf - A templated class that contains an enum value representing
+///  the alignment of the template argument.  For example,
+///  AlignOf<int>::Alignment represents the alignment of type "int".  The
+///  alignment calculated is the minimum alignment, and not necessarily
+///  the "desired" alignment returned by GCC's __alignof__ (for example).  Note
+///  that because the alignment is an enum value, it can be used as a
+///  compile-time constant (e.g., for template instantiation).
+template <typename T>
+struct AlignOf {
+#ifndef _MSC_VER
+  // Avoid warnings from GCC like:
+  //   comparison between 'enum llvm::AlignOf<X>::<anonymous>' and 'enum
+  //   llvm::AlignOf<Y>::<anonymous>' [-Wenum-compare]
+  // by using constexpr instead of enum.
+  // (except on MSVC, since it doesn't support constexpr yet).
+  static constexpr unsigned Alignment = static_cast<unsigned int>(
+      sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T));
+#else
+  enum {
+    Alignment = static_cast<unsigned int>(
+        sizeof(::llvm::detail::AlignmentCalcImpl<T>) - sizeof(T))
+  };
+#endif
+  enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
+  enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
+  enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
+  enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 };
+
+  enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 };
+  enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 };
+  enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 };
+  enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
+};
+
+#ifndef _MSC_VER
+template <typename T> constexpr unsigned AlignOf<T>::Alignment;
+#endif
+
+/// alignOf - A templated function that returns the minimum alignment of
+///  of a type.  This provides no extra functionality beyond the AlignOf
+///  class besides some cosmetic cleanliness.  Example usage:
+///  alignOf<int>() returns the alignment of an int.
+template <typename T>
+LLVM_CONSTEXPR inline unsigned alignOf() { return AlignOf<T>::Alignment; }
+
+/// \struct AlignedCharArray
+/// \brief Helper for building an aligned character array type.
+///
+/// This template is used to explicitly build up a collection of aligned
+/// character array types. We have to build these up using a macro and explicit
+/// specialization to cope with old versions of MSVC and GCC where only an
+/// integer literal can be used to specify an alignment constraint. Once built
+/// up here, we can then begin to indirect between these using normal C++
+/// template parameters.
+
+// MSVC requires special handling here.
+#ifndef _MSC_VER
+
+#if __has_feature(cxx_alignas)
+template<std::size_t Alignment, std::size_t Size>
+struct AlignedCharArray {
+  alignas(Alignment) char buffer[Size];
+};
+
+#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES)
+/// \brief Create a type with an aligned char buffer.
+template<std::size_t Alignment, std::size_t Size>
+struct AlignedCharArray;
+
+#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+  template<std::size_t Size> \
+  struct AlignedCharArray<x, Size> { \
+    __attribute__((aligned(x))) char buffer[Size]; \
+  };
+
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
+
+#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+
+#else
+# error No supported align as directive.
+#endif
+
+#else // _MSC_VER
+
+/// \brief Create a type with an aligned char buffer.
+template<std::size_t Alignment, std::size_t Size>
+struct AlignedCharArray;
+
+// We provide special variations of this template for the most common
+// alignments because __declspec(align(...)) doesn't actually work when it is
+// a member of a by-value function argument in MSVC, even if the alignment
+// request is something reasonably like 8-byte or 16-byte. Note that we can't
+// even include the declspec with the union that forces the alignment because
+// MSVC warns on the existence of the declspec despite the union member forcing
+// proper alignment.
+
+template<std::size_t Size>
+struct AlignedCharArray<1, Size> {
+  union {
+    char aligned;
+    char buffer[Size];
+  };
+};
+
+template<std::size_t Size>
+struct AlignedCharArray<2, Size> {
+  union {
+    short aligned;
+    char buffer[Size];
+  };
+};
+
+template<std::size_t Size>
+struct AlignedCharArray<4, Size> {
+  union {
+    int aligned;
+    char buffer[Size];
+  };
+};
+
+template<std::size_t Size>
+struct AlignedCharArray<8, Size> {
+  union {
+    double aligned;
+    char buffer[Size];
+  };
+};
+
+
+// The rest of these are provided with a __declspec(align(...)) and we simply
+// can't pass them by-value as function arguments on MSVC.
+
+#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+  template<std::size_t Size> \
+  struct AlignedCharArray<x, Size> { \
+    __declspec(align(x)) char buffer[Size]; \
+  };
+
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
+LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
+
+#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+
+#endif // _MSC_VER
+
+namespace detail {
+template <typename T1,
+          typename T2 = char, typename T3 = char, typename T4 = char,
+          typename T5 = char, typename T6 = char, typename T7 = char,
+          typename T8 = char, typename T9 = char, typename T10 = char>
+class AlignerImpl {
+  T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
+
+  AlignerImpl() = delete;
+};
+
+template <typename T1,
+          typename T2 = char, typename T3 = char, typename T4 = char,
+          typename T5 = char, typename T6 = char, typename T7 = char,
+          typename T8 = char, typename T9 = char, typename T10 = char>
+union SizerImpl {
+  char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
+       arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
+       arr9[sizeof(T9)], arr10[sizeof(T10)];
+};
+} // end namespace detail
+
+/// \brief This union template exposes a suitably aligned and sized character
+/// array member which can hold elements of any of up to ten types.
+///
+/// These types may be arrays, structs, or any other types. The goal is to
+/// expose a char array buffer member which can be used as suitable storage for
+/// a placement new of any of these types. Support for more than ten types can
+/// be added at the cost of more boilerplate.
+template <typename T1,
+          typename T2 = char, typename T3 = char, typename T4 = char,
+          typename T5 = char, typename T6 = char, typename T7 = char,
+          typename T8 = char, typename T9 = char, typename T10 = char>
+struct AlignedCharArrayUnion : llvm::AlignedCharArray<
+    AlignOf<llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
+                                      T6, T7, T8, T9, T10> >::Alignment,
+    sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
+                                     T6, T7, T8, T9, T10>)> {
+};
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Allocator.h b/third_party/llvm-subzero/include/llvm/Support/Allocator.h
new file mode 100644
index 0000000..1c95086
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Allocator.h
@@ -0,0 +1,437 @@
+//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both
+/// of these conform to an LLVM "Allocator" concept which consists of an
+/// Allocate method accepting a size and alignment, and a Deallocate accepting
+/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of
+/// Allocate and Deallocate for setting size and alignment based on the final
+/// type. These overloads are typically provided by a base class template \c
+/// AllocatorBase.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALLOCATOR_H
+#define LLVM_SUPPORT_ALLOCATOR_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Memory.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+
+namespace llvm {
+
+/// \brief CRTP base class providing obvious overloads for the core \c
+/// Allocate() methods of LLVM-style allocators.
+///
+/// This base class both documents the full public interface exposed by all
+/// LLVM-style allocators, and redirects all of the overloads to a single core
+/// set of methods which the derived class must define.
+template <typename DerivedT> class AllocatorBase {
+public:
+  /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method
+  /// must be implemented by \c DerivedT.
+  void *Allocate(size_t Size, size_t Alignment) {
+#ifdef __clang__
+    static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
+                      &AllocatorBase::Allocate) !=
+                      static_cast<void *(DerivedT::*)(size_t, size_t)>(
+                          &DerivedT::Allocate),
+                  "Class derives from AllocatorBase without implementing the "
+                  "core Allocate(size_t, size_t) overload!");
+#endif
+    return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
+  }
+
+  /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this
+  /// allocator.
+  void Deallocate(const void *Ptr, size_t Size) {
+#ifdef __clang__
+    static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>(
+                      &AllocatorBase::Deallocate) !=
+                      static_cast<void (DerivedT::*)(const void *, size_t)>(
+                          &DerivedT::Deallocate),
+                  "Class derives from AllocatorBase without implementing the "
+                  "core Deallocate(void *) overload!");
+#endif
+    return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size);
+  }
+
+  // The rest of these methods are helpers that redirect to one of the above
+  // core methods.
+
+  /// \brief Allocate space for a sequence of objects without constructing them.
+  template <typename T> T *Allocate(size_t Num = 1) {
+    return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment));
+  }
+
+  /// \brief Deallocate space for a sequence of objects without constructing them.
+  template <typename T>
+  typename std::enable_if<
+      !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type
+  Deallocate(T *Ptr, size_t Num = 1) {
+    Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T));
+  }
+};
+
+class MallocAllocator : public AllocatorBase<MallocAllocator> {
+public:
+  void Reset() {}
+
+  LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
+                                                size_t /*Alignment*/) {
+    return malloc(Size);
+  }
+
+  // Pull in base class overloads.
+  using AllocatorBase<MallocAllocator>::Allocate;
+
+  void Deallocate(const void *Ptr, size_t /*Size*/) {
+    free(const_cast<void *>(Ptr));
+  }
+
+  // Pull in base class overloads.
+  using AllocatorBase<MallocAllocator>::Deallocate;
+
+  void PrintStats() const {}
+};
+
+namespace detail {
+
+// We call out to an external function to actually print the message as the
+// printing code uses Allocator.h in its implementation.
+void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
+                                size_t TotalMemory);
+} // End namespace detail.
+
+/// \brief Allocate memory in an ever growing pool, as if by bump-pointer.
+///
+/// This isn't strictly a bump-pointer allocator as it uses backing slabs of
+/// memory rather than relying on a boundless contiguous heap. However, it has
+/// bump-pointer semantics in that it is a monotonically growing pool of memory
+/// where every allocation is found by merely allocating the next N bytes in
+/// the slab, or the next N bytes in the next slab.
+///
+/// Note that this also has a threshold for forcing allocations above a certain
+/// size into their own slab.
+///
+/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
+/// object, which wraps malloc, to allocate memory, but it can be changed to
+/// use a custom allocator.
+template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
+          size_t SizeThreshold = SlabSize>
+class BumpPtrAllocatorImpl
+    : public AllocatorBase<
+          BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> {
+public:
+  static_assert(SizeThreshold <= SlabSize,
+                "The SizeThreshold must be at most the SlabSize to ensure "
+                "that objects larger than a slab go into their own memory "
+                "allocation.");
+
+  BumpPtrAllocatorImpl()
+      : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {}
+  template <typename T>
+  BumpPtrAllocatorImpl(T &&Allocator)
+      : CurPtr(nullptr), End(nullptr), BytesAllocated(0),
+        Allocator(std::forward<T &&>(Allocator)) {}
+
+  // Manually implement a move constructor as we must clear the old allocator's
+  // slabs as a matter of correctness.
+  BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
+      : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)),
+        CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
+        BytesAllocated(Old.BytesAllocated),
+        Allocator(std::move(Old.Allocator)) {
+    Old.CurPtr = Old.End = nullptr;
+    Old.BytesAllocated = 0;
+    Old.Slabs.clear();
+    Old.CustomSizedSlabs.clear();
+  }
+
+  ~BumpPtrAllocatorImpl() {
+    DeallocateSlabs(Slabs.begin(), Slabs.end());
+    DeallocateCustomSizedSlabs();
+  }
+
+  BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) {
+    DeallocateSlabs(Slabs.begin(), Slabs.end());
+    DeallocateCustomSizedSlabs();
+
+    CurPtr = RHS.CurPtr;
+    End = RHS.End;
+    BytesAllocated = RHS.BytesAllocated;
+    Slabs = std::move(RHS.Slabs);
+    CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
+    Allocator = std::move(RHS.Allocator);
+
+    RHS.CurPtr = RHS.End = nullptr;
+    RHS.BytesAllocated = 0;
+    RHS.Slabs.clear();
+    RHS.CustomSizedSlabs.clear();
+    return *this;
+  }
+
+  /// \brief Deallocate all but the current slab and reset the current pointer
+  /// to the beginning of it, freeing all memory allocated so far.
+  void Reset() {
+    // Deallocate all but the first slab, and deallocate all custom-sized slabs.
+    DeallocateCustomSizedSlabs();
+    CustomSizedSlabs.clear();
+
+    if (Slabs.empty())
+      return;
+
+    // Reset the state.
+    BytesAllocated = 0;
+    CurPtr = (char *)Slabs.front();
+    End = CurPtr + SlabSize;
+
+    __asan_poison_memory_region(*Slabs.begin(), computeSlabSize(0));
+    DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
+    Slabs.erase(std::next(Slabs.begin()), Slabs.end());
+  }
+
+  /// \brief Allocate space at the specified alignment.
+  LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+  Allocate(size_t Size, size_t Alignment) {
+    assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
+
+    // Keep track of how many bytes we've allocated.
+    BytesAllocated += Size;
+
+    size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
+    assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
+
+    // Check if we have enough space.
+    if (Adjustment + Size <= size_t(End - CurPtr)) {
+      char *AlignedPtr = CurPtr + Adjustment;
+      CurPtr = AlignedPtr + Size;
+      // Update the allocation point of this memory block in MemorySanitizer.
+      // Without this, MemorySanitizer messages for values originated from here
+      // will point to the allocation of the entire slab.
+      __msan_allocated_memory(AlignedPtr, Size);
+      // Similarly, tell ASan about this space.
+      __asan_unpoison_memory_region(AlignedPtr, Size);
+      return AlignedPtr;
+    }
+
+    // If Size is really big, allocate a separate slab for it.
+    size_t PaddedSize = Size + Alignment - 1;
+    if (PaddedSize > SizeThreshold) {
+      void *NewSlab = Allocator.Allocate(PaddedSize, 0);
+      // We own the new slab and don't want anyone reading anyting other than
+      // pieces returned from this method.  So poison the whole slab.
+      __asan_poison_memory_region(NewSlab, PaddedSize);
+      CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
+
+      uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
+      assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize);
+      char *AlignedPtr = (char*)AlignedAddr;
+      __msan_allocated_memory(AlignedPtr, Size);
+      __asan_unpoison_memory_region(AlignedPtr, Size);
+      return AlignedPtr;
+    }
+
+    // Otherwise, start a new slab and try again.
+    StartNewSlab();
+    uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
+    assert(AlignedAddr + Size <= (uintptr_t)End &&
+           "Unable to allocate memory!");
+    char *AlignedPtr = (char*)AlignedAddr;
+    CurPtr = AlignedPtr + Size;
+    __msan_allocated_memory(AlignedPtr, Size);
+    __asan_unpoison_memory_region(AlignedPtr, Size);
+    return AlignedPtr;
+  }
+
+  // Pull in base class overloads.
+  using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
+
+  void Deallocate(const void *Ptr, size_t Size) {
+    __asan_poison_memory_region(Ptr, Size);
+  }
+
+  // Pull in base class overloads.
+  using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate;
+
+  size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); }
+
+  size_t getTotalMemory() const {
+    size_t TotalMemory = 0;
+    for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I)
+      TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I));
+    for (auto &PtrAndSize : CustomSizedSlabs)
+      TotalMemory += PtrAndSize.second;
+    return TotalMemory;
+  }
+
+  size_t getBytesAllocated() const { return BytesAllocated; }
+
+  void PrintStats() const {
+    detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
+                                       getTotalMemory());
+  }
+
+private:
+  /// \brief The current pointer into the current slab.
+  ///
+  /// This points to the next free byte in the slab.
+  char *CurPtr;
+
+  /// \brief The end of the current slab.
+  char *End;
+
+  /// \brief The slabs allocated so far.
+  SmallVector<void *, 4> Slabs;
+
+  /// \brief Custom-sized slabs allocated for too-large allocation requests.
+  SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
+
+  /// \brief How many bytes we've allocated.
+  ///
+  /// Used so that we can compute how much space was wasted.
+  size_t BytesAllocated;
+
+  /// \brief The allocator instance we use to get slabs of memory.
+  AllocatorT Allocator;
+
+  static size_t computeSlabSize(unsigned SlabIdx) {
+    // Scale the actual allocated slab size based on the number of slabs
+    // allocated. Every 128 slabs allocated, we double the allocated size to
+    // reduce allocation frequency, but saturate at multiplying the slab size by
+    // 2^30.
+    return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128));
+  }
+
+  /// \brief Allocate a new slab and move the bump pointers over into the new
+  /// slab, modifying CurPtr and End.
+  void StartNewSlab() {
+    size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
+
+    void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
+    // We own the new slab and don't want anyone reading anything other than
+    // pieces returned from this method.  So poison the whole slab.
+    __asan_poison_memory_region(NewSlab, AllocatedSlabSize);
+
+    Slabs.push_back(NewSlab);
+    CurPtr = (char *)(NewSlab);
+    End = ((char *)NewSlab) + AllocatedSlabSize;
+  }
+
+  /// \brief Deallocate a sequence of slabs.
+  void DeallocateSlabs(SmallVectorImpl<void *>::iterator I,
+                       SmallVectorImpl<void *>::iterator E) {
+    for (; I != E; ++I) {
+      size_t AllocatedSlabSize =
+          computeSlabSize(std::distance(Slabs.begin(), I));
+      Allocator.Deallocate(*I, AllocatedSlabSize);
+    }
+  }
+
+  /// \brief Deallocate all memory for custom sized slabs.
+  void DeallocateCustomSizedSlabs() {
+    for (auto &PtrAndSize : CustomSizedSlabs) {
+      void *Ptr = PtrAndSize.first;
+      size_t Size = PtrAndSize.second;
+      Allocator.Deallocate(Ptr, Size);
+    }
+  }
+
+  template <typename T> friend class SpecificBumpPtrAllocator;
+};
+
+/// \brief The standard BumpPtrAllocator which just uses the default template
+/// paramaters.
+typedef BumpPtrAllocatorImpl<> BumpPtrAllocator;
+
+/// \brief A BumpPtrAllocator that allows only elements of a specific type to be
+/// allocated.
+///
+/// This allows calling the destructor in DestroyAll() and when the allocator is
+/// destroyed.
+template <typename T> class SpecificBumpPtrAllocator {
+  BumpPtrAllocator Allocator;
+
+public:
+  SpecificBumpPtrAllocator() : Allocator() {}
+  SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
+      : Allocator(std::move(Old.Allocator)) {}
+  ~SpecificBumpPtrAllocator() { DestroyAll(); }
+
+  SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) {
+    Allocator = std::move(RHS.Allocator);
+    return *this;
+  }
+
+  /// Call the destructor of each allocated object and deallocate all but the
+  /// current slab and reset the current pointer to the beginning of it, freeing
+  /// all memory allocated so far.
+  void DestroyAll() {
+    auto DestroyElements = [](char *Begin, char *End) {
+      assert(Begin == (char*)alignAddr(Begin, alignOf<T>()));
+      for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
+        reinterpret_cast<T *>(Ptr)->~T();
+    };
+
+    for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E;
+         ++I) {
+      size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize(
+          std::distance(Allocator.Slabs.begin(), I));
+      char *Begin = (char*)alignAddr(*I, alignOf<T>());
+      char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
+                                               : (char *)*I + AllocatedSlabSize;
+
+      DestroyElements(Begin, End);
+    }
+
+    for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
+      void *Ptr = PtrAndSize.first;
+      size_t Size = PtrAndSize.second;
+      DestroyElements((char*)alignAddr(Ptr, alignOf<T>()), (char *)Ptr + Size);
+    }
+
+    Allocator.Reset();
+  }
+
+  /// \brief Allocate space for an array of objects without constructing them.
+  T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); }
+};
+
+}  // end namespace llvm
+
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
+void *operator new(size_t Size,
+                   llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
+                                              SizeThreshold> &Allocator) {
+  struct S {
+    char c;
+    union {
+      double D;
+      long double LD;
+      long long L;
+      void *P;
+    } x;
+  };
+  return Allocator.Allocate(
+      Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x)));
+}
+
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
+void operator delete(
+    void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) {
+}
+
+#endif // LLVM_SUPPORT_ALLOCATOR_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Atomic.h b/third_party/llvm-subzero/include/llvm/Support/Atomic.h
new file mode 100644
index 0000000..d03714b
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Atomic.h
@@ -0,0 +1,38 @@
+//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys atomic operations.
+//
+// DO NOT USE IN NEW CODE!
+//
+// New code should always rely on the std::atomic facilities in C++11.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ATOMIC_H
+#define LLVM_SUPPORT_ATOMIC_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+  namespace sys {
+    void MemoryFence();
+
+#ifdef _MSC_VER
+    typedef long cas_flag;
+#else
+    typedef uint32_t cas_flag;
+#endif
+    cas_flag CompareAndSwap(volatile cas_flag* ptr,
+                            cas_flag new_value,
+                            cas_flag old_value);
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/CBindingWrapping.h b/third_party/llvm-subzero/include/llvm/Support/CBindingWrapping.h
new file mode 100644
index 0000000..d4633aa
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/CBindingWrapping.h
@@ -0,0 +1,47 @@
+//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the wrapping macros for the C interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H
+#define LLVM_SUPPORT_CBINDINGWRAPPING_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm-c/Types.h"
+
+#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)     \
+  inline ty *unwrap(ref P) {                            \
+    return reinterpret_cast<ty*>(P);                    \
+  }                                                     \
+                                                        \
+  inline ref wrap(const ty *P) {                        \
+    return reinterpret_cast<ref>(const_cast<ty*>(P));   \
+  }
+
+#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref)        \
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)           \
+                                                        \
+  template<typename T>                                  \
+  inline T *unwrap(ref P) {                             \
+    return cast<T>(unwrap(P));                          \
+  }
+
+#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref)     \
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)           \
+                                                        \
+  template<typename T>                                  \
+  inline T *unwrap(ref P) {                             \
+    T *Q = (T*)unwrap(P);                               \
+    assert(Q && "Invalid cast!");                       \
+    return Q;                                           \
+  }
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/COFF.h b/third_party/llvm-subzero/include/llvm/Support/COFF.h
new file mode 100644
index 0000000..7dad3e8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/COFF.h
@@ -0,0 +1,675 @@
+//===-- llvm/Support/COFF.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains an definitions used in Windows COFF Files.
+//
+// Structures and enums defined within this file where created using
+// information from Microsoft's publicly available PE/COFF format document:
+//
+// Microsoft Portable Executable and Common Object File Format Specification
+// Revision 8.1 - February 15, 2008
+//
+// As of 5/2/2010, hosted by Microsoft at:
+// http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_COFF_H
+#define LLVM_SUPPORT_COFF_H
+
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstring>
+
+namespace llvm {
+namespace COFF {
+
+  // The maximum number of sections that a COFF object can have (inclusive).
+  const int32_t MaxNumberOfSections16 = 65279;
+
+  // The PE signature bytes that follows the DOS stub header.
+  static const char PEMagic[] = { 'P', 'E', '\0', '\0' };
+
+  static const char BigObjMagic[] = {
+      '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b',
+      '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8',
+  };
+
+  // Sizes in bytes of various things in the COFF format.
+  enum {
+    Header16Size   = 20,
+    Header32Size   = 56,
+    NameSize       = 8,
+    Symbol16Size   = 18,
+    Symbol32Size   = 20,
+    SectionSize    = 40,
+    RelocationSize = 10
+  };
+
+  struct header {
+    uint16_t Machine;
+    int32_t  NumberOfSections;
+    uint32_t TimeDateStamp;
+    uint32_t PointerToSymbolTable;
+    uint32_t NumberOfSymbols;
+    uint16_t SizeOfOptionalHeader;
+    uint16_t Characteristics;
+  };
+
+  struct BigObjHeader {
+    enum : uint16_t { MinBigObjectVersion = 2 };
+
+    uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0).
+    uint16_t Sig2; ///< Must be 0xFFFF.
+    uint16_t Version;
+    uint16_t Machine;
+    uint32_t TimeDateStamp;
+    uint8_t  UUID[16];
+    uint32_t unused1;
+    uint32_t unused2;
+    uint32_t unused3;
+    uint32_t unused4;
+    uint32_t NumberOfSections;
+    uint32_t PointerToSymbolTable;
+    uint32_t NumberOfSymbols;
+  };
+
+  enum MachineTypes {
+    MT_Invalid = 0xffff,
+
+    IMAGE_FILE_MACHINE_UNKNOWN   = 0x0,
+    IMAGE_FILE_MACHINE_AM33      = 0x13,
+    IMAGE_FILE_MACHINE_AMD64     = 0x8664,
+    IMAGE_FILE_MACHINE_ARM       = 0x1C0,
+    IMAGE_FILE_MACHINE_ARMNT     = 0x1C4,
+    IMAGE_FILE_MACHINE_ARM64     = 0xAA64,
+    IMAGE_FILE_MACHINE_EBC       = 0xEBC,
+    IMAGE_FILE_MACHINE_I386      = 0x14C,
+    IMAGE_FILE_MACHINE_IA64      = 0x200,
+    IMAGE_FILE_MACHINE_M32R      = 0x9041,
+    IMAGE_FILE_MACHINE_MIPS16    = 0x266,
+    IMAGE_FILE_MACHINE_MIPSFPU   = 0x366,
+    IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
+    IMAGE_FILE_MACHINE_POWERPC   = 0x1F0,
+    IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1,
+    IMAGE_FILE_MACHINE_R4000     = 0x166,
+    IMAGE_FILE_MACHINE_SH3       = 0x1A2,
+    IMAGE_FILE_MACHINE_SH3DSP    = 0x1A3,
+    IMAGE_FILE_MACHINE_SH4       = 0x1A6,
+    IMAGE_FILE_MACHINE_SH5       = 0x1A8,
+    IMAGE_FILE_MACHINE_THUMB     = 0x1C2,
+    IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
+  };
+
+  enum Characteristics {
+    C_Invalid = 0,
+
+    /// The file does not contain base relocations and must be loaded at its
+    /// preferred base. If this cannot be done, the loader will error.
+    IMAGE_FILE_RELOCS_STRIPPED         = 0x0001,
+    /// The file is valid and can be run.
+    IMAGE_FILE_EXECUTABLE_IMAGE        = 0x0002,
+    /// COFF line numbers have been stripped. This is deprecated and should be
+    /// 0.
+    IMAGE_FILE_LINE_NUMS_STRIPPED      = 0x0004,
+    /// COFF symbol table entries for local symbols have been removed. This is
+    /// deprecated and should be 0.
+    IMAGE_FILE_LOCAL_SYMS_STRIPPED     = 0x0008,
+    /// Aggressively trim working set. This is deprecated and must be 0.
+    IMAGE_FILE_AGGRESSIVE_WS_TRIM      = 0x0010,
+    /// Image can handle > 2GiB addresses.
+    IMAGE_FILE_LARGE_ADDRESS_AWARE     = 0x0020,
+    /// Little endian: the LSB precedes the MSB in memory. This is deprecated
+    /// and should be 0.
+    IMAGE_FILE_BYTES_REVERSED_LO       = 0x0080,
+    /// Machine is based on a 32bit word architecture.
+    IMAGE_FILE_32BIT_MACHINE           = 0x0100,
+    /// Debugging info has been removed.
+    IMAGE_FILE_DEBUG_STRIPPED          = 0x0200,
+    /// If the image is on removable media, fully load it and copy it to swap.
+    IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
+    /// If the image is on network media, fully load it and copy it to swap.
+    IMAGE_FILE_NET_RUN_FROM_SWAP       = 0x0800,
+    /// The image file is a system file, not a user program.
+    IMAGE_FILE_SYSTEM                  = 0x1000,
+    /// The image file is a DLL.
+    IMAGE_FILE_DLL                     = 0x2000,
+    /// This file should only be run on a uniprocessor machine.
+    IMAGE_FILE_UP_SYSTEM_ONLY          = 0x4000,
+    /// Big endian: the MSB precedes the LSB in memory. This is deprecated
+    /// and should be 0.
+    IMAGE_FILE_BYTES_REVERSED_HI       = 0x8000
+  };
+
+  struct symbol {
+    char     Name[NameSize];
+    uint32_t Value;
+    int32_t  SectionNumber;
+    uint16_t Type;
+    uint8_t  StorageClass;
+    uint8_t  NumberOfAuxSymbols;
+  };
+
+  enum SymbolSectionNumber : int32_t {
+    IMAGE_SYM_DEBUG     = -2,
+    IMAGE_SYM_ABSOLUTE  = -1,
+    IMAGE_SYM_UNDEFINED = 0
+  };
+
+  /// Storage class tells where and what the symbol represents
+  enum SymbolStorageClass {
+    SSC_Invalid = 0xff,
+
+    IMAGE_SYM_CLASS_END_OF_FUNCTION  = -1,  ///< Physical end of function
+    IMAGE_SYM_CLASS_NULL             = 0,   ///< No symbol
+    IMAGE_SYM_CLASS_AUTOMATIC        = 1,   ///< Stack variable
+    IMAGE_SYM_CLASS_EXTERNAL         = 2,   ///< External symbol
+    IMAGE_SYM_CLASS_STATIC           = 3,   ///< Static
+    IMAGE_SYM_CLASS_REGISTER         = 4,   ///< Register variable
+    IMAGE_SYM_CLASS_EXTERNAL_DEF     = 5,   ///< External definition
+    IMAGE_SYM_CLASS_LABEL            = 6,   ///< Label
+    IMAGE_SYM_CLASS_UNDEFINED_LABEL  = 7,   ///< Undefined label
+    IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8,   ///< Member of structure
+    IMAGE_SYM_CLASS_ARGUMENT         = 9,   ///< Function argument
+    IMAGE_SYM_CLASS_STRUCT_TAG       = 10,  ///< Structure tag
+    IMAGE_SYM_CLASS_MEMBER_OF_UNION  = 11,  ///< Member of union
+    IMAGE_SYM_CLASS_UNION_TAG        = 12,  ///< Union tag
+    IMAGE_SYM_CLASS_TYPE_DEFINITION  = 13,  ///< Type definition
+    IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14,  ///< Undefined static
+    IMAGE_SYM_CLASS_ENUM_TAG         = 15,  ///< Enumeration tag
+    IMAGE_SYM_CLASS_MEMBER_OF_ENUM   = 16,  ///< Member of enumeration
+    IMAGE_SYM_CLASS_REGISTER_PARAM   = 17,  ///< Register parameter
+    IMAGE_SYM_CLASS_BIT_FIELD        = 18,  ///< Bit field
+    /// ".bb" or ".eb" - beginning or end of block
+    IMAGE_SYM_CLASS_BLOCK            = 100,
+    /// ".bf" or ".ef" - beginning or end of function
+    IMAGE_SYM_CLASS_FUNCTION         = 101,
+    IMAGE_SYM_CLASS_END_OF_STRUCT    = 102, ///< End of structure
+    IMAGE_SYM_CLASS_FILE             = 103, ///< File name
+    /// Line number, reformatted as symbol
+    IMAGE_SYM_CLASS_SECTION          = 104,
+    IMAGE_SYM_CLASS_WEAK_EXTERNAL    = 105, ///< Duplicate tag
+    /// External symbol in dmert public lib
+    IMAGE_SYM_CLASS_CLR_TOKEN        = 107
+  };
+
+  enum SymbolBaseType {
+    IMAGE_SYM_TYPE_NULL   = 0,  ///< No type information or unknown base type.
+    IMAGE_SYM_TYPE_VOID   = 1,  ///< Used with void pointers and functions.
+    IMAGE_SYM_TYPE_CHAR   = 2,  ///< A character (signed byte).
+    IMAGE_SYM_TYPE_SHORT  = 3,  ///< A 2-byte signed integer.
+    IMAGE_SYM_TYPE_INT    = 4,  ///< A natural integer type on the target.
+    IMAGE_SYM_TYPE_LONG   = 5,  ///< A 4-byte signed integer.
+    IMAGE_SYM_TYPE_FLOAT  = 6,  ///< A 4-byte floating-point number.
+    IMAGE_SYM_TYPE_DOUBLE = 7,  ///< An 8-byte floating-point number.
+    IMAGE_SYM_TYPE_STRUCT = 8,  ///< A structure.
+    IMAGE_SYM_TYPE_UNION  = 9,  ///< An union.
+    IMAGE_SYM_TYPE_ENUM   = 10, ///< An enumerated type.
+    IMAGE_SYM_TYPE_MOE    = 11, ///< A member of enumeration (a specific value).
+    IMAGE_SYM_TYPE_BYTE   = 12, ///< A byte; unsigned 1-byte integer.
+    IMAGE_SYM_TYPE_WORD   = 13, ///< A word; unsigned 2-byte integer.
+    IMAGE_SYM_TYPE_UINT   = 14, ///< An unsigned integer of natural size.
+    IMAGE_SYM_TYPE_DWORD  = 15  ///< An unsigned 4-byte integer.
+  };
+
+  enum SymbolComplexType {
+    IMAGE_SYM_DTYPE_NULL     = 0, ///< No complex type; simple scalar variable.
+    IMAGE_SYM_DTYPE_POINTER  = 1, ///< A pointer to base type.
+    IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type.
+    IMAGE_SYM_DTYPE_ARRAY    = 3, ///< An array of base type.
+
+    /// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
+    SCT_COMPLEX_TYPE_SHIFT   = 4
+  };
+
+  enum AuxSymbolType {
+    IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1
+  };
+
+  struct section {
+    char     Name[NameSize];
+    uint32_t VirtualSize;
+    uint32_t VirtualAddress;
+    uint32_t SizeOfRawData;
+    uint32_t PointerToRawData;
+    uint32_t PointerToRelocations;
+    uint32_t PointerToLineNumbers;
+    uint16_t NumberOfRelocations;
+    uint16_t NumberOfLineNumbers;
+    uint32_t Characteristics;
+  };
+
+  enum SectionCharacteristics : uint32_t {
+    SC_Invalid = 0xffffffff,
+
+    IMAGE_SCN_TYPE_NOLOAD            = 0x00000002,
+    IMAGE_SCN_TYPE_NO_PAD            = 0x00000008,
+    IMAGE_SCN_CNT_CODE               = 0x00000020,
+    IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040,
+    IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
+    IMAGE_SCN_LNK_OTHER              = 0x00000100,
+    IMAGE_SCN_LNK_INFO               = 0x00000200,
+    IMAGE_SCN_LNK_REMOVE             = 0x00000800,
+    IMAGE_SCN_LNK_COMDAT             = 0x00001000,
+    IMAGE_SCN_GPREL                  = 0x00008000,
+    IMAGE_SCN_MEM_PURGEABLE          = 0x00020000,
+    IMAGE_SCN_MEM_16BIT              = 0x00020000,
+    IMAGE_SCN_MEM_LOCKED             = 0x00040000,
+    IMAGE_SCN_MEM_PRELOAD            = 0x00080000,
+    IMAGE_SCN_ALIGN_1BYTES           = 0x00100000,
+    IMAGE_SCN_ALIGN_2BYTES           = 0x00200000,
+    IMAGE_SCN_ALIGN_4BYTES           = 0x00300000,
+    IMAGE_SCN_ALIGN_8BYTES           = 0x00400000,
+    IMAGE_SCN_ALIGN_16BYTES          = 0x00500000,
+    IMAGE_SCN_ALIGN_32BYTES          = 0x00600000,
+    IMAGE_SCN_ALIGN_64BYTES          = 0x00700000,
+    IMAGE_SCN_ALIGN_128BYTES         = 0x00800000,
+    IMAGE_SCN_ALIGN_256BYTES         = 0x00900000,
+    IMAGE_SCN_ALIGN_512BYTES         = 0x00A00000,
+    IMAGE_SCN_ALIGN_1024BYTES        = 0x00B00000,
+    IMAGE_SCN_ALIGN_2048BYTES        = 0x00C00000,
+    IMAGE_SCN_ALIGN_4096BYTES        = 0x00D00000,
+    IMAGE_SCN_ALIGN_8192BYTES        = 0x00E00000,
+    IMAGE_SCN_LNK_NRELOC_OVFL        = 0x01000000,
+    IMAGE_SCN_MEM_DISCARDABLE        = 0x02000000,
+    IMAGE_SCN_MEM_NOT_CACHED         = 0x04000000,
+    IMAGE_SCN_MEM_NOT_PAGED          = 0x08000000,
+    IMAGE_SCN_MEM_SHARED             = 0x10000000,
+    IMAGE_SCN_MEM_EXECUTE            = 0x20000000,
+    IMAGE_SCN_MEM_READ               = 0x40000000,
+    IMAGE_SCN_MEM_WRITE              = 0x80000000
+  };
+
+  struct relocation {
+    uint32_t VirtualAddress;
+    uint32_t SymbolTableIndex;
+    uint16_t Type;
+  };
+
+  enum RelocationTypeI386 {
+    IMAGE_REL_I386_ABSOLUTE = 0x0000,
+    IMAGE_REL_I386_DIR16    = 0x0001,
+    IMAGE_REL_I386_REL16    = 0x0002,
+    IMAGE_REL_I386_DIR32    = 0x0006,
+    IMAGE_REL_I386_DIR32NB  = 0x0007,
+    IMAGE_REL_I386_SEG12    = 0x0009,
+    IMAGE_REL_I386_SECTION  = 0x000A,
+    IMAGE_REL_I386_SECREL   = 0x000B,
+    IMAGE_REL_I386_TOKEN    = 0x000C,
+    IMAGE_REL_I386_SECREL7  = 0x000D,
+    IMAGE_REL_I386_REL32    = 0x0014
+  };
+
+  enum RelocationTypeAMD64 {
+    IMAGE_REL_AMD64_ABSOLUTE  = 0x0000,
+    IMAGE_REL_AMD64_ADDR64    = 0x0001,
+    IMAGE_REL_AMD64_ADDR32    = 0x0002,
+    IMAGE_REL_AMD64_ADDR32NB  = 0x0003,
+    IMAGE_REL_AMD64_REL32     = 0x0004,
+    IMAGE_REL_AMD64_REL32_1   = 0x0005,
+    IMAGE_REL_AMD64_REL32_2   = 0x0006,
+    IMAGE_REL_AMD64_REL32_3   = 0x0007,
+    IMAGE_REL_AMD64_REL32_4   = 0x0008,
+    IMAGE_REL_AMD64_REL32_5   = 0x0009,
+    IMAGE_REL_AMD64_SECTION   = 0x000A,
+    IMAGE_REL_AMD64_SECREL    = 0x000B,
+    IMAGE_REL_AMD64_SECREL7   = 0x000C,
+    IMAGE_REL_AMD64_TOKEN     = 0x000D,
+    IMAGE_REL_AMD64_SREL32    = 0x000E,
+    IMAGE_REL_AMD64_PAIR      = 0x000F,
+    IMAGE_REL_AMD64_SSPAN32   = 0x0010
+  };
+
+  enum RelocationTypesARM {
+    IMAGE_REL_ARM_ABSOLUTE  = 0x0000,
+    IMAGE_REL_ARM_ADDR32    = 0x0001,
+    IMAGE_REL_ARM_ADDR32NB  = 0x0002,
+    IMAGE_REL_ARM_BRANCH24  = 0x0003,
+    IMAGE_REL_ARM_BRANCH11  = 0x0004,
+    IMAGE_REL_ARM_TOKEN     = 0x0005,
+    IMAGE_REL_ARM_BLX24     = 0x0008,
+    IMAGE_REL_ARM_BLX11     = 0x0009,
+    IMAGE_REL_ARM_SECTION   = 0x000E,
+    IMAGE_REL_ARM_SECREL    = 0x000F,
+    IMAGE_REL_ARM_MOV32A    = 0x0010,
+    IMAGE_REL_ARM_MOV32T    = 0x0011,
+    IMAGE_REL_ARM_BRANCH20T = 0x0012,
+    IMAGE_REL_ARM_BRANCH24T = 0x0014,
+    IMAGE_REL_ARM_BLX23T    = 0x0015
+  };
+
+  enum COMDATType {
+    IMAGE_COMDAT_SELECT_NODUPLICATES = 1,
+    IMAGE_COMDAT_SELECT_ANY,
+    IMAGE_COMDAT_SELECT_SAME_SIZE,
+    IMAGE_COMDAT_SELECT_EXACT_MATCH,
+    IMAGE_COMDAT_SELECT_ASSOCIATIVE,
+    IMAGE_COMDAT_SELECT_LARGEST,
+    IMAGE_COMDAT_SELECT_NEWEST
+  };
+
+  // Auxiliary Symbol Formats
+  struct AuxiliaryFunctionDefinition {
+    uint32_t TagIndex;
+    uint32_t TotalSize;
+    uint32_t PointerToLinenumber;
+    uint32_t PointerToNextFunction;
+    char     unused[2];
+  };
+
+  struct AuxiliarybfAndefSymbol {
+    uint8_t  unused1[4];
+    uint16_t Linenumber;
+    uint8_t  unused2[6];
+    uint32_t PointerToNextFunction;
+    uint8_t  unused3[2];
+  };
+
+  struct AuxiliaryWeakExternal {
+    uint32_t TagIndex;
+    uint32_t Characteristics;
+    uint8_t  unused[10];
+  };
+
+  enum WeakExternalCharacteristics {
+    IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1,
+    IMAGE_WEAK_EXTERN_SEARCH_LIBRARY   = 2,
+    IMAGE_WEAK_EXTERN_SEARCH_ALIAS     = 3
+  };
+
+  struct AuxiliarySectionDefinition {
+    uint32_t Length;
+    uint16_t NumberOfRelocations;
+    uint16_t NumberOfLinenumbers;
+    uint32_t CheckSum;
+    uint32_t Number;
+    uint8_t  Selection;
+    char     unused;
+  };
+
+  struct AuxiliaryCLRToken {
+    uint8_t  AuxType;
+    uint8_t  unused1;
+    uint32_t SymbolTableIndex;
+    char     unused2[12];
+  };
+
+  union Auxiliary {
+    AuxiliaryFunctionDefinition FunctionDefinition;
+    AuxiliarybfAndefSymbol      bfAndefSymbol;
+    AuxiliaryWeakExternal       WeakExternal;
+    AuxiliarySectionDefinition  SectionDefinition;
+  };
+
+  /// @brief The Import Directory Table.
+  ///
+  /// There is a single array of these and one entry per imported DLL.
+  struct ImportDirectoryTableEntry {
+    uint32_t ImportLookupTableRVA;
+    uint32_t TimeDateStamp;
+    uint32_t ForwarderChain;
+    uint32_t NameRVA;
+    uint32_t ImportAddressTableRVA;
+  };
+
+  /// @brief The PE32 Import Lookup Table.
+  ///
+  /// There is an array of these for each imported DLL. It represents either
+  /// the ordinal to import from the target DLL, or a name to lookup and import
+  /// from the target DLL.
+  ///
+  /// This also happens to be the same format used by the Import Address Table
+  /// when it is initially written out to the image.
+  struct ImportLookupTableEntry32 {
+    uint32_t data;
+
+    /// @brief Is this entry specified by ordinal, or name?
+    bool isOrdinal() const { return data & 0x80000000; }
+
+    /// @brief Get the ordinal value of this entry. isOrdinal must be true.
+    uint16_t getOrdinal() const {
+      assert(isOrdinal() && "ILT entry is not an ordinal!");
+      return data & 0xFFFF;
+    }
+
+    /// @brief Set the ordinal value and set isOrdinal to true.
+    void setOrdinal(uint16_t o) {
+      data = o;
+      data |= 0x80000000;
+    }
+
+    /// @brief Get the Hint/Name entry RVA. isOrdinal must be false.
+    uint32_t getHintNameRVA() const {
+      assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
+      return data;
+    }
+
+    /// @brief Set the Hint/Name entry RVA and set isOrdinal to false.
+    void setHintNameRVA(uint32_t rva) { data = rva; }
+  };
+
+  /// @brief The DOS compatible header at the front of all PEs.
+  struct DOSHeader {
+    uint16_t Magic;
+    uint16_t UsedBytesInTheLastPage;
+    uint16_t FileSizeInPages;
+    uint16_t NumberOfRelocationItems;
+    uint16_t HeaderSizeInParagraphs;
+    uint16_t MinimumExtraParagraphs;
+    uint16_t MaximumExtraParagraphs;
+    uint16_t InitialRelativeSS;
+    uint16_t InitialSP;
+    uint16_t Checksum;
+    uint16_t InitialIP;
+    uint16_t InitialRelativeCS;
+    uint16_t AddressOfRelocationTable;
+    uint16_t OverlayNumber;
+    uint16_t Reserved[4];
+    uint16_t OEMid;
+    uint16_t OEMinfo;
+    uint16_t Reserved2[10];
+    uint32_t AddressOfNewExeHeader;
+  };
+
+  struct PE32Header {
+    enum {
+      PE32 = 0x10b,
+      PE32_PLUS = 0x20b
+    };
+
+    uint16_t Magic;
+    uint8_t  MajorLinkerVersion;
+    uint8_t  MinorLinkerVersion;
+    uint32_t SizeOfCode;
+    uint32_t SizeOfInitializedData;
+    uint32_t SizeOfUninitializedData;
+    uint32_t AddressOfEntryPoint; // RVA
+    uint32_t BaseOfCode; // RVA
+    uint32_t BaseOfData; // RVA
+    uint32_t ImageBase;
+    uint32_t SectionAlignment;
+    uint32_t FileAlignment;
+    uint16_t MajorOperatingSystemVersion;
+    uint16_t MinorOperatingSystemVersion;
+    uint16_t MajorImageVersion;
+    uint16_t MinorImageVersion;
+    uint16_t MajorSubsystemVersion;
+    uint16_t MinorSubsystemVersion;
+    uint32_t Win32VersionValue;
+    uint32_t SizeOfImage;
+    uint32_t SizeOfHeaders;
+    uint32_t CheckSum;
+    uint16_t Subsystem;
+    // FIXME: This should be DllCharacteristics to match the COFF spec.
+    uint16_t DLLCharacteristics;
+    uint32_t SizeOfStackReserve;
+    uint32_t SizeOfStackCommit;
+    uint32_t SizeOfHeapReserve;
+    uint32_t SizeOfHeapCommit;
+    uint32_t LoaderFlags;
+    // FIXME: This should be NumberOfRvaAndSizes to match the COFF spec.
+    uint32_t NumberOfRvaAndSize;
+  };
+
+  struct DataDirectory {
+    uint32_t RelativeVirtualAddress;
+    uint32_t Size;
+  };
+
+  enum DataDirectoryIndex {
+    EXPORT_TABLE = 0,
+    IMPORT_TABLE,
+    RESOURCE_TABLE,
+    EXCEPTION_TABLE,
+    CERTIFICATE_TABLE,
+    BASE_RELOCATION_TABLE,
+    DEBUG_DIRECTORY,
+    ARCHITECTURE,
+    GLOBAL_PTR,
+    TLS_TABLE,
+    LOAD_CONFIG_TABLE,
+    BOUND_IMPORT,
+    IAT,
+    DELAY_IMPORT_DESCRIPTOR,
+    CLR_RUNTIME_HEADER,
+
+    NUM_DATA_DIRECTORIES
+  };
+
+  enum WindowsSubsystem {
+    IMAGE_SUBSYSTEM_UNKNOWN = 0, ///< An unknown subsystem.
+    IMAGE_SUBSYSTEM_NATIVE = 1, ///< Device drivers and native Windows processes
+    IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, ///< The Windows GUI subsystem.
+    IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, ///< The Windows character subsystem.
+    IMAGE_SUBSYSTEM_OS2_CUI = 5, ///< The OS/2 character subsytem.
+    IMAGE_SUBSYSTEM_POSIX_CUI = 7, ///< The POSIX character subsystem.
+    IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, ///< Native Windows 9x driver.
+    IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, ///< Windows CE.
+    IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, ///< An EFI application.
+    IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, ///< An EFI driver with boot
+                                                  ///  services.
+    IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, ///< An EFI driver with run-time
+                                             ///  services.
+    IMAGE_SUBSYSTEM_EFI_ROM = 13, ///< An EFI ROM image.
+    IMAGE_SUBSYSTEM_XBOX = 14, ///< XBOX.
+    IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 ///< A BCD application.
+  };
+
+  enum DLLCharacteristics {
+    /// ASLR with 64 bit address space.
+    IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020,
+    /// DLL can be relocated at load time.
+    IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040,
+    /// Code integrity checks are enforced.
+    IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
+    ///< Image is NX compatible.
+    IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100,
+    /// Isolation aware, but do not isolate the image.
+    IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200,
+    /// Does not use structured exception handling (SEH). No SEH handler may be
+    /// called in this image.
+    IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400,
+    /// Do not bind the image.
+    IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800,
+    ///< Image should execute in an AppContainer.
+    IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000,
+    ///< A WDM driver.
+    IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000,
+    ///< Image supports Control Flow Guard.
+    IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000,
+    /// Terminal Server aware.
+    IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
+  };
+
+  enum DebugType {
+    IMAGE_DEBUG_TYPE_UNKNOWN       = 0,
+    IMAGE_DEBUG_TYPE_COFF          = 1,
+    IMAGE_DEBUG_TYPE_CODEVIEW      = 2,
+    IMAGE_DEBUG_TYPE_FPO           = 3,
+    IMAGE_DEBUG_TYPE_MISC          = 4,
+    IMAGE_DEBUG_TYPE_EXCEPTION     = 5,
+    IMAGE_DEBUG_TYPE_FIXUP         = 6,
+    IMAGE_DEBUG_TYPE_OMAP_TO_SRC   = 7,
+    IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8,
+    IMAGE_DEBUG_TYPE_BORLAND       = 9,
+    IMAGE_DEBUG_TYPE_RESERVED10    = 10,
+    IMAGE_DEBUG_TYPE_CLSID         = 11,
+    IMAGE_DEBUG_TYPE_VC_FEATURE    = 12,
+    IMAGE_DEBUG_TYPE_POGO          = 13,
+    IMAGE_DEBUG_TYPE_ILTCG         = 14,
+    IMAGE_DEBUG_TYPE_MPX           = 15,
+    IMAGE_DEBUG_TYPE_REPRO         = 16,
+  };
+
+  enum BaseRelocationType {
+    IMAGE_REL_BASED_ABSOLUTE       = 0,
+    IMAGE_REL_BASED_HIGH           = 1,
+    IMAGE_REL_BASED_LOW            = 2,
+    IMAGE_REL_BASED_HIGHLOW        = 3,
+    IMAGE_REL_BASED_HIGHADJ        = 4,
+    IMAGE_REL_BASED_MIPS_JMPADDR   = 5,
+    IMAGE_REL_BASED_ARM_MOV32A     = 5,
+    IMAGE_REL_BASED_ARM_MOV32T     = 7,
+    IMAGE_REL_BASED_MIPS_JMPADDR16 = 9,
+    IMAGE_REL_BASED_DIR64          = 10
+  };
+
+  enum ImportType {
+    IMPORT_CODE  = 0,
+    IMPORT_DATA  = 1,
+    IMPORT_CONST = 2
+  };
+
+  enum ImportNameType {
+    /// Import is by ordinal. This indicates that the value in the Ordinal/Hint
+    /// field of the import header is the import's ordinal. If this constant is
+    /// not specified, then the Ordinal/Hint field should always be interpreted
+    /// as the import's hint.
+    IMPORT_ORDINAL         = 0,
+    /// The import name is identical to the public symbol name
+    IMPORT_NAME            = 1,
+    /// The import name is the public symbol name, but skipping the leading ?,
+    /// @, or optionally _.
+    IMPORT_NAME_NOPREFIX   = 2,
+    /// The import name is the public symbol name, but skipping the leading ?,
+    /// @, or optionally _, and truncating at the first @.
+    IMPORT_NAME_UNDECORATE = 3
+  };
+
+  struct ImportHeader {
+    uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0).
+    uint16_t Sig2; ///< Must be 0xFFFF.
+    uint16_t Version;
+    uint16_t Machine;
+    uint32_t TimeDateStamp;
+    uint32_t SizeOfData;
+    uint16_t OrdinalHint;
+    uint16_t TypeInfo;
+
+    ImportType getType() const {
+      return static_cast<ImportType>(TypeInfo & 0x3);
+    }
+
+    ImportNameType getNameType() const {
+      return static_cast<ImportNameType>((TypeInfo & 0x1C) >> 3);
+    }
+  };
+
+  enum CodeViewIdentifiers {
+    DEBUG_SECTION_MAGIC = 0x4,
+  };
+
+  inline bool isReservedSectionNumber(int32_t SectionNumber) {
+    return SectionNumber <= 0;
+  }
+
+} // End namespace COFF.
+} // End namespace llvm.
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Casting.h b/third_party/llvm-subzero/include/llvm/Support/Casting.h
new file mode 100644
index 0000000..6ba5efa
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Casting.h
@@ -0,0 +1,326 @@
+//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(),
+// and dyn_cast_or_null<X>() templates.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CASTING_H
+#define LLVM_SUPPORT_CASTING_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+//                          isa<x> Support Templates
+//===----------------------------------------------------------------------===//
+
+// Define a template that can be specialized by smart pointers to reflect the
+// fact that they are automatically dereferenced, and are not involved with the
+// template selection process...  the default implementation is a noop.
+//
+template<typename From> struct simplify_type {
+  typedef       From SimpleType;        // The real type this represents...
+
+  // An accessor to get the real value...
+  static SimpleType &getSimplifiedValue(From &Val) { return Val; }
+};
+
+template<typename From> struct simplify_type<const From> {
+  typedef typename simplify_type<From>::SimpleType NonConstSimpleType;
+  typedef typename add_const_past_pointer<NonConstSimpleType>::type
+    SimpleType;
+  typedef typename add_lvalue_reference_if_not_pointer<SimpleType>::type
+    RetType;
+  static RetType getSimplifiedValue(const From& Val) {
+    return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val));
+  }
+};
+
+// The core of the implementation of isa<X> is here; To and From should be
+// the names of classes.  This template can be specialized to customize the
+// implementation of isa<> without rewriting it from scratch.
+template <typename To, typename From, typename Enabler = void>
+struct isa_impl {
+  static inline bool doit(const From &Val) {
+    return To::classof(&Val);
+  }
+};
+
+/// \brief Always allow upcasts, and perform no dynamic check for them.
+template <typename To, typename From>
+struct isa_impl<
+    To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> {
+  static inline bool doit(const From &) { return true; }
+};
+
+template <typename To, typename From> struct isa_impl_cl {
+  static inline bool doit(const From &Val) {
+    return isa_impl<To, From>::doit(Val);
+  }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, const From> {
+  static inline bool doit(const From &Val) {
+    return isa_impl<To, From>::doit(Val);
+  }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, From*> {
+  static inline bool doit(const From *Val) {
+    assert(Val && "isa<> used on a null pointer");
+    return isa_impl<To, From>::doit(*Val);
+  }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, From*const> {
+  static inline bool doit(const From *Val) {
+    assert(Val && "isa<> used on a null pointer");
+    return isa_impl<To, From>::doit(*Val);
+  }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, const From*> {
+  static inline bool doit(const From *Val) {
+    assert(Val && "isa<> used on a null pointer");
+    return isa_impl<To, From>::doit(*Val);
+  }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, const From*const> {
+  static inline bool doit(const From *Val) {
+    assert(Val && "isa<> used on a null pointer");
+    return isa_impl<To, From>::doit(*Val);
+  }
+};
+
+template<typename To, typename From, typename SimpleFrom>
+struct isa_impl_wrap {
+  // When From != SimplifiedType, we can simplify the type some more by using
+  // the simplify_type template.
+  static bool doit(const From &Val) {
+    return isa_impl_wrap<To, SimpleFrom,
+      typename simplify_type<SimpleFrom>::SimpleType>::doit(
+                          simplify_type<const From>::getSimplifiedValue(Val));
+  }
+};
+
+template<typename To, typename FromTy>
+struct isa_impl_wrap<To, FromTy, FromTy> {
+  // When From == SimpleType, we are as simple as we are going to get.
+  static bool doit(const FromTy &Val) {
+    return isa_impl_cl<To,FromTy>::doit(Val);
+  }
+};
+
+// isa<X> - Return true if the parameter to the template is an instance of the
+// template type argument.  Used like this:
+//
+//  if (isa<Type>(myVal)) { ... }
+//
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) {
+  return isa_impl_wrap<X, const Y,
+                       typename simplify_type<const Y>::SimpleType>::doit(Val);
+}
+
+//===----------------------------------------------------------------------===//
+//                          cast<x> Support Templates
+//===----------------------------------------------------------------------===//
+
+template<class To, class From> struct cast_retty;
+
+
+// Calculate what type the 'cast' function should return, based on a requested
+// type of To and a source type of From.
+template<class To, class From> struct cast_retty_impl {
+  typedef To& ret_type;         // Normal case, return Ty&
+};
+template<class To, class From> struct cast_retty_impl<To, const From> {
+  typedef const To &ret_type;   // Normal case, return Ty&
+};
+
+template<class To, class From> struct cast_retty_impl<To, From*> {
+  typedef To* ret_type;         // Pointer arg case, return Ty*
+};
+
+template<class To, class From> struct cast_retty_impl<To, const From*> {
+  typedef const To* ret_type;   // Constant pointer arg case, return const Ty*
+};
+
+template<class To, class From> struct cast_retty_impl<To, const From*const> {
+  typedef const To* ret_type;   // Constant pointer arg case, return const Ty*
+};
+
+
+template<class To, class From, class SimpleFrom>
+struct cast_retty_wrap {
+  // When the simplified type and the from type are not the same, use the type
+  // simplifier to reduce the type, then reuse cast_retty_impl to get the
+  // resultant type.
+  typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type;
+};
+
+template<class To, class FromTy>
+struct cast_retty_wrap<To, FromTy, FromTy> {
+  // When the simplified type is equal to the from type, use it directly.
+  typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type;
+};
+
+template<class To, class From>
+struct cast_retty {
+  typedef typename cast_retty_wrap<To, From,
+                   typename simplify_type<From>::SimpleType>::ret_type ret_type;
+};
+
+// Ensure the non-simple values are converted using the simplify_type template
+// that may be specialized by smart pointers...
+//
+template<class To, class From, class SimpleFrom> struct cast_convert_val {
+  // This is not a simple type, use the template to simplify it...
+  static typename cast_retty<To, From>::ret_type doit(From &Val) {
+    return cast_convert_val<To, SimpleFrom,
+      typename simplify_type<SimpleFrom>::SimpleType>::doit(
+                          simplify_type<From>::getSimplifiedValue(Val));
+  }
+};
+
+template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> {
+  // This _is_ a simple type, just cast it.
+  static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
+    typename cast_retty<To, FromTy>::ret_type Res2
+     = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val);
+    return Res2;
+  }
+};
+
+template <class X> struct is_simple_type {
+  static const bool value =
+      std::is_same<X, typename simplify_type<X>::SimpleType>::value;
+};
+
+// cast<X> - Return the argument parameter cast to the specified type.  This
+// casting operator asserts that the type is correct, so it does not return null
+// on failure.  It does not allow a null argument (use cast_or_null for that).
+// It is typically used like this:
+//
+//  cast<Instruction>(myVal)->getParent()
+//
+template <class X, class Y>
+inline typename std::enable_if<!is_simple_type<Y>::value,
+                               typename cast_retty<X, const Y>::ret_type>::type
+cast(const Y &Val) {
+  assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
+  return cast_convert_val<
+      X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val);
+}
+
+template <class X, class Y>
+inline typename cast_retty<X, Y>::ret_type cast(Y &Val) {
+  assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
+  return cast_convert_val<X, Y,
+                          typename simplify_type<Y>::SimpleType>::doit(Val);
+}
+
+template <class X, class Y>
+inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) {
+  assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
+  return cast_convert_val<X, Y*,
+                          typename simplify_type<Y*>::SimpleType>::doit(Val);
+}
+
+// cast_or_null<X> - Functionally identical to cast, except that a null value is
+// accepted.
+//
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+    !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+cast_or_null(const Y &Val) {
+  if (!Val)
+    return nullptr;
+  assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+  return cast<X>(Val);
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+    !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
+cast_or_null(Y &Val) {
+  if (!Val)
+    return nullptr;
+  assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+  return cast<X>(Val);
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
+cast_or_null(Y *Val) {
+  if (!Val) return nullptr;
+  assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+  return cast<X>(Val);
+}
+
+
+// dyn_cast<X> - Return the argument parameter cast to the specified type.  This
+// casting operator returns null if the argument is of the wrong type, so it can
+// be used to test for a type as well as cast if successful.  This should be
+// used in the context of an if statement like this:
+//
+//  if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
+//
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+    !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+dyn_cast(const Y &Val) {
+  return isa<X>(Val) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type
+dyn_cast(Y &Val) {
+  return isa<X>(Val) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
+dyn_cast(Y *Val) {
+  return isa<X>(Val) ? cast<X>(Val) : nullptr;
+}
+
+// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null
+// value is accepted.
+//
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+    !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+dyn_cast_or_null(const Y &Val) {
+  return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+    !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
+dyn_cast_or_null(Y &Val) {
+  return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
+dyn_cast_or_null(Y *Val) {
+  return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/CommandLine.h b/third_party/llvm-subzero/include/llvm/Support/CommandLine.h
new file mode 100644
index 0000000..a0ec262
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/CommandLine.h
@@ -0,0 +1,1833 @@
+//===- llvm/Support/CommandLine.h - Command line handler --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements a command line argument processor that is useful when
+// creating a tool.  It provides a simple, minimalistic interface that is easily
+// extensible and supports nonlocal (library) command line options.
+//
+// Note that rather than trying to figure out what this code does, you should
+// read the library documentation located in docs/CommandLine.html or looks at
+// the many example usages in tools/*/*.cpp
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_COMMANDLINE_H
+#define LLVM_SUPPORT_COMMANDLINE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ManagedStatic.h"
+#include <cassert>
+#include <climits>
+#include <cstdarg>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class StringSaver;
+
+/// cl Namespace - This namespace contains all of the command line option
+/// processing machinery.  It is intentionally a short name to make qualified
+/// usage concise.
+namespace cl {
+
+//===----------------------------------------------------------------------===//
+// ParseCommandLineOptions - Command line option processing entry point.
+//
+bool ParseCommandLineOptions(int argc, const char *const *argv,
+                             const char *Overview = nullptr,
+                             bool IgnoreErrors = false);
+
+//===----------------------------------------------------------------------===//
+// ParseEnvironmentOptions - Environment variable option processing alternate
+//                           entry point.
+//
+void ParseEnvironmentOptions(const char *progName, const char *envvar,
+                             const char *Overview = nullptr);
+
+///===---------------------------------------------------------------------===//
+/// SetVersionPrinter - Override the default (LLVM specific) version printer
+///                     used to print out the version when --version is given
+///                     on the command line. This allows other systems using the
+///                     CommandLine utilities to print their own version string.
+void SetVersionPrinter(void (*func)());
+
+///===---------------------------------------------------------------------===//
+/// AddExtraVersionPrinter - Add an extra printer to use in addition to the
+///                          default one. This can be called multiple times,
+///                          and each time it adds a new function to the list
+///                          which will be called after the basic LLVM version
+///                          printing is complete. Each can then add additional
+///                          information specific to the tool.
+void AddExtraVersionPrinter(void (*func)());
+
+// PrintOptionValues - Print option values.
+// With -print-options print the difference between option values and defaults.
+// With -print-all-options print all option values.
+// (Currently not perfect, but best-effort.)
+void PrintOptionValues();
+
+// Forward declaration - AddLiteralOption needs to be up here to make gcc happy.
+class Option;
+
+/// \brief Adds a new option for parsing and provides the option it refers to.
+///
+/// \param O pointer to the option
+/// \param Name the string name for the option to handle during parsing
+///
+/// Literal options are used by some parsers to register special option values.
+/// This is how the PassNameParser registers pass names for opt.
+void AddLiteralOption(Option &O, const char *Name);
+
+//===----------------------------------------------------------------------===//
+// Flags permitted to be passed to command line arguments
+//
+
+enum NumOccurrencesFlag { // Flags for the number of occurrences allowed
+  Optional = 0x00,        // Zero or One occurrence
+  ZeroOrMore = 0x01,      // Zero or more occurrences allowed
+  Required = 0x02,        // One occurrence required
+  OneOrMore = 0x03,       // One or more occurrences required
+
+  // ConsumeAfter - Indicates that this option is fed anything that follows the
+  // last positional argument required by the application (it is an error if
+  // there are zero positional arguments, and a ConsumeAfter option is used).
+  // Thus, for example, all arguments to LLI are processed until a filename is
+  // found.  Once a filename is found, all of the succeeding arguments are
+  // passed, unprocessed, to the ConsumeAfter option.
+  //
+  ConsumeAfter = 0x04
+};
+
+enum ValueExpected { // Is a value required for the option?
+  // zero reserved for the unspecified value
+  ValueOptional = 0x01,  // The value can appear... or not
+  ValueRequired = 0x02,  // The value is required to appear!
+  ValueDisallowed = 0x03 // A value may not be specified (for flags)
+};
+
+enum OptionHidden {   // Control whether -help shows this option
+  NotHidden = 0x00,   // Option included in -help & -help-hidden
+  Hidden = 0x01,      // -help doesn't, but -help-hidden does
+  ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg
+};
+
+// Formatting flags - This controls special features that the option might have
+// that cause it to be parsed differently...
+//
+// Prefix - This option allows arguments that are otherwise unrecognized to be
+// matched by options that are a prefix of the actual value.  This is useful for
+// cases like a linker, where options are typically of the form '-lfoo' or
+// '-L../../include' where -l or -L are the actual flags.  When prefix is
+// enabled, and used, the value for the flag comes from the suffix of the
+// argument.
+//
+// Grouping - With this option enabled, multiple letter options are allowed to
+// bunch together with only a single hyphen for the whole group.  This allows
+// emulation of the behavior that ls uses for example: ls -la === ls -l -a
+//
+
+enum FormattingFlags {
+  NormalFormatting = 0x00, // Nothing special
+  Positional = 0x01,       // Is a positional argument, no '-' required
+  Prefix = 0x02,           // Can this option directly prefix its value?
+  Grouping = 0x03          // Can this option group with other options?
+};
+
+enum MiscFlags {             // Miscellaneous flags to adjust argument
+  CommaSeparated = 0x01,     // Should this cl::list split between commas?
+  PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args?
+  Sink = 0x04                // Should this cl::list eat all unknown options?
+};
+
+//===----------------------------------------------------------------------===//
+// Option Category class
+//
+class OptionCategory {
+private:
+  const char *const Name;
+  const char *const Description;
+  void registerCategory();
+
+public:
+  OptionCategory(const char *const Name,
+                 const char *const Description = nullptr)
+      : Name(Name), Description(Description) {
+    registerCategory();
+  }
+  const char *getName() const { return Name; }
+  const char *getDescription() const { return Description; }
+};
+
+// The general Option Category (used as default category).
+extern OptionCategory GeneralCategory;
+
+//===----------------------------------------------------------------------===//
+// SubCommand class
+//
+class SubCommand {
+private:
+  const char *const Name = nullptr;
+  const char *const Description = nullptr;
+
+protected:
+  void registerSubCommand();
+  void unregisterSubCommand();
+
+public:
+  SubCommand(const char *const Name, const char *const Description = nullptr)
+      : Name(Name), Description(Description) {
+    registerSubCommand();
+  }
+  SubCommand() {}
+
+  void reset();
+
+  operator bool() const;
+
+  const char *getName() const { return Name; }
+  const char *getDescription() const { return Description; }
+
+  SmallVector<Option *, 4> PositionalOpts;
+  SmallVector<Option *, 4> SinkOpts;
+  StringMap<Option *> OptionsMap;
+
+  Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists.
+};
+
+// A special subcommand representing no subcommand
+extern ManagedStatic<SubCommand> TopLevelSubCommand;
+
+// A special subcommand that can be used to put an option into all subcommands.
+extern ManagedStatic<SubCommand> AllSubCommands;
+
+//===----------------------------------------------------------------------===//
+// Option Base class
+//
+class alias;
+class Option {
+  friend class alias;
+
+  // handleOccurrences - Overriden by subclasses to handle the value passed into
+  // an argument.  Should return true if there was an error processing the
+  // argument and the program should exit.
+  //
+  virtual bool handleOccurrence(unsigned pos, StringRef ArgName,
+                                StringRef Arg) = 0;
+
+  virtual enum ValueExpected getValueExpectedFlagDefault() const {
+    return ValueOptional;
+  }
+
+  // Out of line virtual function to provide home for the class.
+  virtual void anchor();
+
+  int NumOccurrences; // The number of times specified
+  // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid
+  // problems with signed enums in bitfields.
+  unsigned Occurrences : 3; // enum NumOccurrencesFlag
+  // not using the enum type for 'Value' because zero is an implementation
+  // detail representing the non-value
+  unsigned Value : 2;
+  unsigned HiddenFlag : 2; // enum OptionHidden
+  unsigned Formatting : 2; // enum FormattingFlags
+  unsigned Misc : 3;
+  unsigned Position;       // Position of last occurrence of the option
+  unsigned AdditionalVals; // Greater than 0 for multi-valued option.
+
+public:
+  StringRef ArgStr;   // The argument string itself (ex: "help", "o")
+  StringRef HelpStr;  // The descriptive text message for -help
+  StringRef ValueStr; // String describing what the value of this option is
+  OptionCategory *Category; // The Category this option belongs to
+  SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
+  bool FullyInitialized;    // Has addArguemnt been called?
+
+  inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
+    return (enum NumOccurrencesFlag)Occurrences;
+  }
+  inline enum ValueExpected getValueExpectedFlag() const {
+    return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault();
+  }
+  inline enum OptionHidden getOptionHiddenFlag() const {
+    return (enum OptionHidden)HiddenFlag;
+  }
+  inline enum FormattingFlags getFormattingFlag() const {
+    return (enum FormattingFlags)Formatting;
+  }
+  inline unsigned getMiscFlags() const { return Misc; }
+  inline unsigned getPosition() const { return Position; }
+  inline unsigned getNumAdditionalVals() const { return AdditionalVals; }
+
+  // hasArgStr - Return true if the argstr != ""
+  bool hasArgStr() const { return !ArgStr.empty(); }
+  bool isPositional() const { return getFormattingFlag() == cl::Positional; }
+  bool isSink() const { return getMiscFlags() & cl::Sink; }
+  bool isConsumeAfter() const {
+    return getNumOccurrencesFlag() == cl::ConsumeAfter;
+  }
+  bool isInAllSubCommands() const {
+    return any_of(Subs, [](const SubCommand *SC) {
+      return SC == &*AllSubCommands;
+    });
+  }
+
+  //-------------------------------------------------------------------------===
+  // Accessor functions set by OptionModifiers
+  //
+  void setArgStr(StringRef S);
+  void setDescription(StringRef S) { HelpStr = S; }
+  void setValueStr(StringRef S) { ValueStr = S; }
+  void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; }
+  void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; }
+  void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; }
+  void setFormattingFlag(enum FormattingFlags V) { Formatting = V; }
+  void setMiscFlag(enum MiscFlags M) { Misc |= M; }
+  void setPosition(unsigned pos) { Position = pos; }
+  void setCategory(OptionCategory &C) { Category = &C; }
+  void addSubCommand(SubCommand &S) { Subs.insert(&S); }
+
+protected:
+  explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
+                  enum OptionHidden Hidden)
+      : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
+        HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0),
+        AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""),
+        Category(&GeneralCategory), FullyInitialized(false) {}
+
+  inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
+
+public:
+  // addArgument - Register this argument with the commandline system.
+  //
+  void addArgument();
+
+  /// Unregisters this option from the CommandLine system.
+  ///
+  /// This option must have been the last option registered.
+  /// For testing purposes only.
+  void removeArgument();
+
+  // Return the width of the option tag for printing...
+  virtual size_t getOptionWidth() const = 0;
+
+  // printOptionInfo - Print out information about this option.  The
+  // to-be-maintained width is specified.
+  //
+  virtual void printOptionInfo(size_t GlobalWidth) const = 0;
+
+  virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0;
+
+  virtual void getExtraOptionNames(SmallVectorImpl<StringRef> &) {}
+
+  // addOccurrence - Wrapper around handleOccurrence that enforces Flags.
+  //
+  virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value,
+                             bool MultiArg = false);
+
+  // Prints option name followed by message.  Always returns true.
+  bool error(const Twine &Message, StringRef ArgName = StringRef());
+
+public:
+  inline int getNumOccurrences() const { return NumOccurrences; }
+  inline void reset() { NumOccurrences = 0; }
+  virtual ~Option() {}
+};
+
+//===----------------------------------------------------------------------===//
+// Command line option modifiers that can be used to modify the behavior of
+// command line option parsers...
+//
+
+// desc - Modifier to set the description shown in the -help output...
+struct desc {
+  const char *Desc;
+  desc(const char *Str) : Desc(Str) {}
+  void apply(Option &O) const { O.setDescription(Desc); }
+};
+
+// value_desc - Modifier to set the value description shown in the -help
+// output...
+struct value_desc {
+  const char *Desc;
+  value_desc(const char *Str) : Desc(Str) {}
+  void apply(Option &O) const { O.setValueStr(Desc); }
+};
+
+// init - Specify a default (initial) value for the command line argument, if
+// the default constructor for the argument type does not give you what you
+// want.  This is only valid on "opt" arguments, not on "list" arguments.
+//
+template <class Ty> struct initializer {
+  const Ty &Init;
+  initializer(const Ty &Val) : Init(Val) {}
+
+  template <class Opt> void apply(Opt &O) const { O.setInitialValue(Init); }
+};
+
+template <class Ty> initializer<Ty> init(const Ty &Val) {
+  return initializer<Ty>(Val);
+}
+
+// location - Allow the user to specify which external variable they want to
+// store the results of the command line argument processing into, if they don't
+// want to store it in the option itself.
+//
+template <class Ty> struct LocationClass {
+  Ty &Loc;
+  LocationClass(Ty &L) : Loc(L) {}
+
+  template <class Opt> void apply(Opt &O) const { O.setLocation(O, Loc); }
+};
+
+template <class Ty> LocationClass<Ty> location(Ty &L) {
+  return LocationClass<Ty>(L);
+}
+
+// cat - Specifiy the Option category for the command line argument to belong
+// to.
+struct cat {
+  OptionCategory &Category;
+  cat(OptionCategory &c) : Category(c) {}
+
+  template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
+};
+
+// sub - Specify the subcommand that this option belongs to.
+struct sub {
+  SubCommand &Sub;
+  sub(SubCommand &S) : Sub(S) {}
+
+  template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
+};
+
+//===----------------------------------------------------------------------===//
+// OptionValue class
+
+// Support value comparison outside the template.
+struct GenericOptionValue {
+  virtual bool compare(const GenericOptionValue &V) const = 0;
+
+protected:
+  ~GenericOptionValue() = default;
+  GenericOptionValue() = default;
+  GenericOptionValue(const GenericOptionValue&) = default;
+  GenericOptionValue &operator=(const GenericOptionValue &) = default;
+
+private:
+  virtual void anchor();
+};
+
+template <class DataType> struct OptionValue;
+
+// The default value safely does nothing. Option value printing is only
+// best-effort.
+template <class DataType, bool isClass>
+struct OptionValueBase : public GenericOptionValue {
+  // Temporary storage for argument passing.
+  typedef OptionValue<DataType> WrapperType;
+
+  bool hasValue() const { return false; }
+
+  const DataType &getValue() const { llvm_unreachable("no default value"); }
+
+  // Some options may take their value from a different data type.
+  template <class DT> void setValue(const DT & /*V*/) {}
+
+  bool compare(const DataType & /*V*/) const { return false; }
+
+  bool compare(const GenericOptionValue & /*V*/) const override {
+    return false;
+  }
+
+protected:
+  ~OptionValueBase() = default;
+};
+
+// Simple copy of the option value.
+template <class DataType> class OptionValueCopy : public GenericOptionValue {
+  DataType Value;
+  bool Valid;
+
+protected:
+  ~OptionValueCopy() = default;
+  OptionValueCopy(const OptionValueCopy&) = default;
+  OptionValueCopy &operator=(const OptionValueCopy&) = default;
+
+public:
+  OptionValueCopy() : Valid(false) {}
+
+  bool hasValue() const { return Valid; }
+
+  const DataType &getValue() const {
+    assert(Valid && "invalid option value");
+    return Value;
+  }
+
+  void setValue(const DataType &V) {
+    Valid = true;
+    Value = V;
+  }
+
+  bool compare(const DataType &V) const { return Valid && (Value != V); }
+
+  bool compare(const GenericOptionValue &V) const override {
+    const OptionValueCopy<DataType> &VC =
+        static_cast<const OptionValueCopy<DataType> &>(V);
+    if (!VC.hasValue())
+      return false;
+    return compare(VC.getValue());
+  }
+};
+
+// Non-class option values.
+template <class DataType>
+struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
+  typedef DataType WrapperType;
+
+protected:
+  ~OptionValueBase() = default;
+  OptionValueBase() = default;
+  OptionValueBase(const OptionValueBase&) = default;
+  OptionValueBase &operator=(const OptionValueBase&) = default;
+};
+
+// Top-level option class.
+template <class DataType>
+struct OptionValue final
+    : OptionValueBase<DataType, std::is_class<DataType>::value> {
+  OptionValue() = default;
+
+  OptionValue(const DataType &V) { this->setValue(V); }
+  // Some options may take their value from a different data type.
+  template <class DT> OptionValue<DataType> &operator=(const DT &V) {
+    this->setValue(V);
+    return *this;
+  }
+};
+
+// Other safe-to-copy-by-value common option types.
+enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
+template <>
+struct OptionValue<cl::boolOrDefault> final
+    : OptionValueCopy<cl::boolOrDefault> {
+  typedef cl::boolOrDefault WrapperType;
+
+  OptionValue() {}
+
+  OptionValue(const cl::boolOrDefault &V) { this->setValue(V); }
+  OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault &V) {
+    setValue(V);
+    return *this;
+  }
+
+private:
+  void anchor() override;
+};
+
+template <>
+struct OptionValue<std::string> final : OptionValueCopy<std::string> {
+  typedef StringRef WrapperType;
+
+  OptionValue() {}
+
+  OptionValue(const std::string &V) { this->setValue(V); }
+  OptionValue<std::string> &operator=(const std::string &V) {
+    setValue(V);
+    return *this;
+  }
+
+private:
+  void anchor() override;
+};
+
+//===----------------------------------------------------------------------===//
+// Enum valued command line option
+//
+#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC
+#define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC
+#define clEnumValEnd (reinterpret_cast<void *>(0))
+
+// values - For custom data types, allow specifying a group of values together
+// as the values that go into the mapping that the option handler uses.  Note
+// that the values list must always have a 0 at the end of the list to indicate
+// that the list has ended.
+//
+template <class DataType> class ValuesClass {
+  // Use a vector instead of a map, because the lists should be short,
+  // the overhead is less, and most importantly, it keeps them in the order
+  // inserted so we can print our option out nicely.
+  SmallVector<std::pair<const char *, std::pair<int, const char *>>, 4> Values;
+  void processValues(va_list Vals);
+
+public:
+  ValuesClass(const char *EnumName, DataType Val, const char *Desc,
+              va_list ValueArgs) {
+    // Insert the first value, which is required.
+    Values.push_back(std::make_pair(EnumName, std::make_pair(Val, Desc)));
+
+    // Process the varargs portion of the values...
+    while (const char *enumName = va_arg(ValueArgs, const char *)) {
+      DataType EnumVal = static_cast<DataType>(va_arg(ValueArgs, int));
+      const char *EnumDesc = va_arg(ValueArgs, const char *);
+      Values.push_back(std::make_pair(enumName, // Add value to value map
+                                      std::make_pair(EnumVal, EnumDesc)));
+    }
+  }
+
+  template <class Opt> void apply(Opt &O) const {
+    for (size_t i = 0, e = Values.size(); i != e; ++i)
+      O.getParser().addLiteralOption(Values[i].first, Values[i].second.first,
+                                     Values[i].second.second);
+  }
+};
+
+template <class DataType>
+ValuesClass<DataType> LLVM_END_WITH_NULL
+values(const char *Arg, DataType Val, const char *Desc, ...) {
+  va_list ValueArgs;
+  va_start(ValueArgs, Desc);
+  ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs);
+  va_end(ValueArgs);
+  return Vals;
+}
+
+//===----------------------------------------------------------------------===//
+// parser class - Parameterizable parser for different data types.  By default,
+// known data types (string, int, bool) have specialized parsers, that do what
+// you would expect.  The default parser, used for data types that are not
+// built-in, uses a mapping table to map specific options to values, which is
+// used, among other things, to handle enum types.
+
+//--------------------------------------------------
+// generic_parser_base - This class holds all the non-generic code that we do
+// not need replicated for every instance of the generic parser.  This also
+// allows us to put stuff into CommandLine.cpp
+//
+class generic_parser_base {
+protected:
+  class GenericOptionInfo {
+  public:
+    GenericOptionInfo(const char *name, const char *helpStr)
+        : Name(name), HelpStr(helpStr) {}
+    const char *Name;
+    const char *HelpStr;
+  };
+
+public:
+  generic_parser_base(Option &O) : Owner(O) {}
+
+  virtual ~generic_parser_base() {} // Base class should have virtual-dtor
+
+  // getNumOptions - Virtual function implemented by generic subclass to
+  // indicate how many entries are in Values.
+  //
+  virtual unsigned getNumOptions() const = 0;
+
+  // getOption - Return option name N.
+  virtual const char *getOption(unsigned N) const = 0;
+
+  // getDescription - Return description N
+  virtual const char *getDescription(unsigned N) const = 0;
+
+  // Return the width of the option tag for printing...
+  virtual size_t getOptionWidth(const Option &O) const;
+
+  virtual const GenericOptionValue &getOptionValue(unsigned N) const = 0;
+
+  // printOptionInfo - Print out information about this option.  The
+  // to-be-maintained width is specified.
+  //
+  virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const;
+
+  void printGenericOptionDiff(const Option &O, const GenericOptionValue &V,
+                              const GenericOptionValue &Default,
+                              size_t GlobalWidth) const;
+
+  // printOptionDiff - print the value of an option and it's default.
+  //
+  // Template definition ensures that the option and default have the same
+  // DataType (via the same AnyOptionValue).
+  template <class AnyOptionValue>
+  void printOptionDiff(const Option &O, const AnyOptionValue &V,
+                       const AnyOptionValue &Default,
+                       size_t GlobalWidth) const {
+    printGenericOptionDiff(O, V, Default, GlobalWidth);
+  }
+
+  void initialize() {}
+
+  void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) {
+    // If there has been no argstr specified, that means that we need to add an
+    // argument for every possible option.  This ensures that our options are
+    // vectored to us.
+    if (!Owner.hasArgStr())
+      for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
+        OptionNames.push_back(getOption(i));
+  }
+
+  enum ValueExpected getValueExpectedFlagDefault() const {
+    // If there is an ArgStr specified, then we are of the form:
+    //
+    //    -opt=O2   or   -opt O2  or  -optO2
+    //
+    // In which case, the value is required.  Otherwise if an arg str has not
+    // been specified, we are of the form:
+    //
+    //    -O2 or O2 or -la (where -l and -a are separate options)
+    //
+    // If this is the case, we cannot allow a value.
+    //
+    if (Owner.hasArgStr())
+      return ValueRequired;
+    else
+      return ValueDisallowed;
+  }
+
+  // findOption - Return the option number corresponding to the specified
+  // argument string.  If the option is not found, getNumOptions() is returned.
+  //
+  unsigned findOption(const char *Name);
+
+protected:
+  Option &Owner;
+};
+
+// Default parser implementation - This implementation depends on having a
+// mapping of recognized options to values of some sort.  In addition to this,
+// each entry in the mapping also tracks a help message that is printed with the
+// command line option for -help.  Because this is a simple mapping parser, the
+// data type can be any unsupported type.
+//
+template <class DataType> class parser : public generic_parser_base {
+protected:
+  class OptionInfo : public GenericOptionInfo {
+  public:
+    OptionInfo(const char *name, DataType v, const char *helpStr)
+        : GenericOptionInfo(name, helpStr), V(v) {}
+    OptionValue<DataType> V;
+  };
+  SmallVector<OptionInfo, 8> Values;
+
+public:
+  parser(Option &O) : generic_parser_base(O) {}
+  typedef DataType parser_data_type;
+
+  // Implement virtual functions needed by generic_parser_base
+  unsigned getNumOptions() const override { return unsigned(Values.size()); }
+  const char *getOption(unsigned N) const override { return Values[N].Name; }
+  const char *getDescription(unsigned N) const override {
+    return Values[N].HelpStr;
+  }
+
+  // getOptionValue - Return the value of option name N.
+  const GenericOptionValue &getOptionValue(unsigned N) const override {
+    return Values[N].V;
+  }
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) {
+    StringRef ArgVal;
+    if (Owner.hasArgStr())
+      ArgVal = Arg;
+    else
+      ArgVal = ArgName;
+
+    for (size_t i = 0, e = Values.size(); i != e; ++i)
+      if (Values[i].Name == ArgVal) {
+        V = Values[i].V.getValue();
+        return false;
+      }
+
+    return O.error("Cannot find option named '" + ArgVal + "'!");
+  }
+
+  /// addLiteralOption - Add an entry to the mapping table.
+  ///
+  template <class DT>
+  void addLiteralOption(const char *Name, const DT &V, const char *HelpStr) {
+    assert(findOption(Name) == Values.size() && "Option already exists!");
+    OptionInfo X(Name, static_cast<DataType>(V), HelpStr);
+    Values.push_back(X);
+    AddLiteralOption(Owner, Name);
+  }
+
+  /// removeLiteralOption - Remove the specified option.
+  ///
+  void removeLiteralOption(const char *Name) {
+    unsigned N = findOption(Name);
+    assert(N != Values.size() && "Option not found!");
+    Values.erase(Values.begin() + N);
+  }
+};
+
+//--------------------------------------------------
+// basic_parser - Super class of parsers to provide boilerplate code
+//
+class basic_parser_impl { // non-template implementation of basic_parser<t>
+public:
+  basic_parser_impl(Option &) {}
+
+
+  enum ValueExpected getValueExpectedFlagDefault() const {
+    return ValueRequired;
+  }
+
+  void getExtraOptionNames(SmallVectorImpl<StringRef> &) {}
+
+  void initialize() {}
+
+  // Return the width of the option tag for printing...
+  size_t getOptionWidth(const Option &O) const;
+
+  // printOptionInfo - Print out information about this option.  The
+  // to-be-maintained width is specified.
+  //
+  void printOptionInfo(const Option &O, size_t GlobalWidth) const;
+
+  // printOptionNoValue - Print a placeholder for options that don't yet support
+  // printOptionDiff().
+  void printOptionNoValue(const Option &O, size_t GlobalWidth) const;
+
+  // getValueName - Overload in subclass to provide a better default value.
+  virtual const char *getValueName() const { return "value"; }
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  virtual void anchor();
+
+protected:
+  ~basic_parser_impl() = default;
+  // A helper for basic_parser::printOptionDiff.
+  void printOptionName(const Option &O, size_t GlobalWidth) const;
+};
+
+// basic_parser - The real basic parser is just a template wrapper that provides
+// a typedef for the provided data type.
+//
+template <class DataType> class basic_parser : public basic_parser_impl {
+public:
+  basic_parser(Option &O) : basic_parser_impl(O) {}
+  typedef DataType parser_data_type;
+  typedef OptionValue<DataType> OptVal;
+
+protected:
+  // Workaround Clang PR22793
+  ~basic_parser() {}
+};
+
+//--------------------------------------------------
+// parser<bool>
+//
+template <> class parser<bool> final : public basic_parser<bool> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val);
+
+  void initialize() {}
+
+  enum ValueExpected getValueExpectedFlagDefault() const {
+    return ValueOptional;
+  }
+
+  // getValueName - Do not print =<value> at all.
+  const char *getValueName() const override { return nullptr; }
+
+  void printOptionDiff(const Option &O, bool V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<bool>;
+
+//--------------------------------------------------
+// parser<boolOrDefault>
+template <>
+class parser<boolOrDefault> final : public basic_parser<boolOrDefault> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val);
+
+  enum ValueExpected getValueExpectedFlagDefault() const {
+    return ValueOptional;
+  }
+
+  // getValueName - Do not print =<value> at all.
+  const char *getValueName() const override { return nullptr; }
+
+  void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<boolOrDefault>;
+
+//--------------------------------------------------
+// parser<int>
+//
+template <> class parser<int> final : public basic_parser<int> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val);
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "int"; }
+
+  void printOptionDiff(const Option &O, int V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<int>;
+
+//--------------------------------------------------
+// parser<unsigned>
+//
+template <> class parser<unsigned> final : public basic_parser<unsigned> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val);
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "uint"; }
+
+  void printOptionDiff(const Option &O, unsigned V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<unsigned>;
+
+//--------------------------------------------------
+// parser<unsigned long long>
+//
+template <>
+class parser<unsigned long long> final
+    : public basic_parser<unsigned long long> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg,
+             unsigned long long &Val);
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "uint"; }
+
+  void printOptionDiff(const Option &O, unsigned long long V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<unsigned long long>;
+
+//--------------------------------------------------
+// parser<double>
+//
+template <> class parser<double> final : public basic_parser<double> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val);
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "number"; }
+
+  void printOptionDiff(const Option &O, double V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<double>;
+
+//--------------------------------------------------
+// parser<float>
+//
+template <> class parser<float> final : public basic_parser<float> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val);
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "number"; }
+
+  void printOptionDiff(const Option &O, float V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<float>;
+
+//--------------------------------------------------
+// parser<std::string>
+//
+template <> class parser<std::string> final : public basic_parser<std::string> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &, StringRef, StringRef Arg, std::string &Value) {
+    Value = Arg.str();
+    return false;
+  }
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "string"; }
+
+  void printOptionDiff(const Option &O, StringRef V, const OptVal &Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<std::string>;
+
+//--------------------------------------------------
+// parser<char>
+//
+template <> class parser<char> final : public basic_parser<char> {
+public:
+  parser(Option &O) : basic_parser(O) {}
+
+  // parse - Return true on error.
+  bool parse(Option &, StringRef, StringRef Arg, char &Value) {
+    Value = Arg[0];
+    return false;
+  }
+
+  // getValueName - Overload in subclass to provide a better default value.
+  const char *getValueName() const override { return "char"; }
+
+  void printOptionDiff(const Option &O, char V, OptVal Default,
+                       size_t GlobalWidth) const;
+
+  // An out-of-line virtual method to provide a 'home' for this class.
+  void anchor() override;
+};
+
+extern template class basic_parser<char>;
+
+//--------------------------------------------------
+// PrintOptionDiff
+//
+// This collection of wrappers is the intermediary between class opt and class
+// parser to handle all the template nastiness.
+
+// This overloaded function is selected by the generic parser.
+template <class ParserClass, class DT>
+void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V,
+                     const OptionValue<DT> &Default, size_t GlobalWidth) {
+  OptionValue<DT> OV = V;
+  P.printOptionDiff(O, OV, Default, GlobalWidth);
+}
+
+// This is instantiated for basic parsers when the parsed value has a different
+// type than the option value. e.g. HelpPrinter.
+template <class ParserDT, class ValDT> struct OptionDiffPrinter {
+  void print(const Option &O, const parser<ParserDT> &P, const ValDT & /*V*/,
+             const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) {
+    P.printOptionNoValue(O, GlobalWidth);
+  }
+};
+
+// This is instantiated for basic parsers when the parsed value has the same
+// type as the option value.
+template <class DT> struct OptionDiffPrinter<DT, DT> {
+  void print(const Option &O, const parser<DT> &P, const DT &V,
+             const OptionValue<DT> &Default, size_t GlobalWidth) {
+    P.printOptionDiff(O, V, Default, GlobalWidth);
+  }
+};
+
+// This overloaded function is selected by the basic parser, which may parse a
+// different type than the option type.
+template <class ParserClass, class ValDT>
+void printOptionDiff(
+    const Option &O,
+    const basic_parser<typename ParserClass::parser_data_type> &P,
+    const ValDT &V, const OptionValue<ValDT> &Default, size_t GlobalWidth) {
+
+  OptionDiffPrinter<typename ParserClass::parser_data_type, ValDT> printer;
+  printer.print(O, static_cast<const ParserClass &>(P), V, Default,
+                GlobalWidth);
+}
+
+//===----------------------------------------------------------------------===//
+// applicator class - This class is used because we must use partial
+// specialization to handle literal string arguments specially (const char* does
+// not correctly respond to the apply method).  Because the syntax to use this
+// is a pain, we have the 'apply' method below to handle the nastiness...
+//
+template <class Mod> struct applicator {
+  template <class Opt> static void opt(const Mod &M, Opt &O) { M.apply(O); }
+};
+
+// Handle const char* as a special case...
+template <unsigned n> struct applicator<char[n]> {
+  template <class Opt> static void opt(const char *Str, Opt &O) {
+    O.setArgStr(Str);
+  }
+};
+template <unsigned n> struct applicator<const char[n]> {
+  template <class Opt> static void opt(const char *Str, Opt &O) {
+    O.setArgStr(Str);
+  }
+};
+template <> struct applicator<const char *> {
+  template <class Opt> static void opt(const char *Str, Opt &O) {
+    O.setArgStr(Str);
+  }
+};
+
+template <> struct applicator<NumOccurrencesFlag> {
+  static void opt(NumOccurrencesFlag N, Option &O) {
+    O.setNumOccurrencesFlag(N);
+  }
+};
+template <> struct applicator<ValueExpected> {
+  static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); }
+};
+template <> struct applicator<OptionHidden> {
+  static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); }
+};
+template <> struct applicator<FormattingFlags> {
+  static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); }
+};
+template <> struct applicator<MiscFlags> {
+  static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
+};
+
+// apply method - Apply modifiers to an option in a type safe way.
+template <class Opt, class Mod, class... Mods>
+void apply(Opt *O, const Mod &M, const Mods &... Ms) {
+  applicator<Mod>::opt(M, *O);
+  apply(O, Ms...);
+}
+
+template <class Opt, class Mod> void apply(Opt *O, const Mod &M) {
+  applicator<Mod>::opt(M, *O);
+}
+
+//===----------------------------------------------------------------------===//
+// opt_storage class
+
+// Default storage class definition: external storage.  This implementation
+// assumes the user will specify a variable to store the data into with the
+// cl::location(x) modifier.
+//
+template <class DataType, bool ExternalStorage, bool isClass>
+class opt_storage {
+  DataType *Location; // Where to store the object...
+  OptionValue<DataType> Default;
+
+  void check_location() const {
+    assert(Location && "cl::location(...) not specified for a command "
+                       "line option with external storage, "
+                       "or cl::init specified before cl::location()!!");
+  }
+
+public:
+  opt_storage() : Location(nullptr) {}
+
+  bool setLocation(Option &O, DataType &L) {
+    if (Location)
+      return O.error("cl::location(x) specified more than once!");
+    Location = &L;
+    Default = L;
+    return false;
+  }
+
+  template <class T> void setValue(const T &V, bool initial = false) {
+    check_location();
+    *Location = V;
+    if (initial)
+      Default = V;
+  }
+
+  DataType &getValue() {
+    check_location();
+    return *Location;
+  }
+  const DataType &getValue() const {
+    check_location();
+    return *Location;
+  }
+
+  operator DataType() const { return this->getValue(); }
+
+  const OptionValue<DataType> &getDefault() const { return Default; }
+};
+
+// Define how to hold a class type object, such as a string.  Since we can
+// inherit from a class, we do so.  This makes us exactly compatible with the
+// object in all cases that it is used.
+//
+template <class DataType>
+class opt_storage<DataType, false, true> : public DataType {
+public:
+  OptionValue<DataType> Default;
+
+  template <class T> void setValue(const T &V, bool initial = false) {
+    DataType::operator=(V);
+    if (initial)
+      Default = V;
+  }
+
+  DataType &getValue() { return *this; }
+  const DataType &getValue() const { return *this; }
+
+  const OptionValue<DataType> &getDefault() const { return Default; }
+};
+
+// Define a partial specialization to handle things we cannot inherit from.  In
+// this case, we store an instance through containment, and overload operators
+// to get at the value.
+//
+template <class DataType> class opt_storage<DataType, false, false> {
+public:
+  DataType Value;
+  OptionValue<DataType> Default;
+
+  // Make sure we initialize the value with the default constructor for the
+  // type.
+  opt_storage() : Value(DataType()), Default(DataType()) {}
+
+  template <class T> void setValue(const T &V, bool initial = false) {
+    Value = V;
+    if (initial)
+      Default = V;
+  }
+  DataType &getValue() { return Value; }
+  DataType getValue() const { return Value; }
+
+  const OptionValue<DataType> &getDefault() const { return Default; }
+
+  operator DataType() const { return getValue(); }
+
+  // If the datatype is a pointer, support -> on it.
+  DataType operator->() const { return Value; }
+};
+
+//===----------------------------------------------------------------------===//
+// opt - A scalar command line option.
+//
+template <class DataType, bool ExternalStorage = false,
+          class ParserClass = parser<DataType>>
+class opt : public Option,
+            public opt_storage<DataType, ExternalStorage,
+                               std::is_class<DataType>::value> {
+  ParserClass Parser;
+
+  bool handleOccurrence(unsigned pos, StringRef ArgName,
+                        StringRef Arg) override {
+    typename ParserClass::parser_data_type Val =
+        typename ParserClass::parser_data_type();
+    if (Parser.parse(*this, ArgName, Arg, Val))
+      return true; // Parse error!
+    this->setValue(Val);
+    this->setPosition(pos);
+    return false;
+  }
+
+  enum ValueExpected getValueExpectedFlagDefault() const override {
+    return Parser.getValueExpectedFlagDefault();
+  }
+  void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
+    return Parser.getExtraOptionNames(OptionNames);
+  }
+
+  // Forward printing stuff to the parser...
+  size_t getOptionWidth() const override {
+    return Parser.getOptionWidth(*this);
+  }
+  void printOptionInfo(size_t GlobalWidth) const override {
+    Parser.printOptionInfo(*this, GlobalWidth);
+  }
+
+  void printOptionValue(size_t GlobalWidth, bool Force) const override {
+    if (Force || this->getDefault().compare(this->getValue())) {
+      cl::printOptionDiff<ParserClass>(*this, Parser, this->getValue(),
+                                       this->getDefault(), GlobalWidth);
+    }
+  }
+
+  void done() {
+    addArgument();
+    Parser.initialize();
+  }
+
+  // Command line options should not be copyable
+  opt(const opt &) = delete;
+  opt &operator=(const opt &) = delete;
+
+public:
+  // setInitialValue - Used by the cl::init modifier...
+  void setInitialValue(const DataType &V) { this->setValue(V, true); }
+
+  ParserClass &getParser() { return Parser; }
+
+  template <class T> DataType &operator=(const T &Val) {
+    this->setValue(Val);
+    return this->getValue();
+  }
+
+  template <class... Mods>
+  explicit opt(const Mods &... Ms)
+      : Option(Optional, NotHidden), Parser(*this) {
+    apply(this, Ms...);
+    done();
+  }
+};
+
+extern template class opt<unsigned>;
+extern template class opt<int>;
+extern template class opt<std::string>;
+extern template class opt<char>;
+extern template class opt<bool>;
+
+//===----------------------------------------------------------------------===//
+// list_storage class
+
+// Default storage class definition: external storage.  This implementation
+// assumes the user will specify a variable to store the data into with the
+// cl::location(x) modifier.
+//
+template <class DataType, class StorageClass> class list_storage {
+  StorageClass *Location; // Where to store the object...
+
+public:
+  list_storage() : Location(0) {}
+
+  bool setLocation(Option &O, StorageClass &L) {
+    if (Location)
+      return O.error("cl::location(x) specified more than once!");
+    Location = &L;
+    return false;
+  }
+
+  template <class T> void addValue(const T &V) {
+    assert(Location != 0 && "cl::location(...) not specified for a command "
+                            "line option with external storage!");
+    Location->push_back(V);
+  }
+};
+
+// Define how to hold a class type object, such as a string.
+// Originally this code inherited from std::vector. In transitioning to a new
+// API for command line options we should change this. The new implementation
+// of this list_storage specialization implements the minimum subset of the
+// std::vector API required for all the current clients.
+//
+// FIXME: Reduce this API to a more narrow subset of std::vector
+//
+template <class DataType> class list_storage<DataType, bool> {
+  std::vector<DataType> Storage;
+
+public:
+  typedef typename std::vector<DataType>::iterator iterator;
+
+  iterator begin() { return Storage.begin(); }
+  iterator end() { return Storage.end(); }
+
+  typedef typename std::vector<DataType>::const_iterator const_iterator;
+  const_iterator begin() const { return Storage.begin(); }
+  const_iterator end() const { return Storage.end(); }
+
+  typedef typename std::vector<DataType>::size_type size_type;
+  size_type size() const { return Storage.size(); }
+
+  bool empty() const { return Storage.empty(); }
+
+  void push_back(const DataType &value) { Storage.push_back(value); }
+  void push_back(DataType &&value) { Storage.push_back(value); }
+
+  typedef typename std::vector<DataType>::reference reference;
+  typedef typename std::vector<DataType>::const_reference const_reference;
+  reference operator[](size_type pos) { return Storage[pos]; }
+  const_reference operator[](size_type pos) const { return Storage[pos]; }
+
+  iterator erase(const_iterator pos) { return Storage.erase(pos); }
+  iterator erase(const_iterator first, const_iterator last) {
+    return Storage.erase(first, last);
+  }
+
+  iterator erase(iterator pos) { return Storage.erase(pos); }
+  iterator erase(iterator first, iterator last) {
+    return Storage.erase(first, last);
+  }
+
+  iterator insert(const_iterator pos, const DataType &value) {
+    return Storage.insert(pos, value);
+  }
+  iterator insert(const_iterator pos, DataType &&value) {
+    return Storage.insert(pos, value);
+  }
+
+  iterator insert(iterator pos, const DataType &value) {
+    return Storage.insert(pos, value);
+  }
+  iterator insert(iterator pos, DataType &&value) {
+    return Storage.insert(pos, value);
+  }
+
+  reference front() { return Storage.front(); }
+  const_reference front() const { return Storage.front(); }
+
+  operator std::vector<DataType>&() { return Storage; }
+  operator ArrayRef<DataType>() { return Storage; }
+  std::vector<DataType> *operator&() { return &Storage; }
+  const std::vector<DataType> *operator&() const { return &Storage; }
+
+  template <class T> void addValue(const T &V) { Storage.push_back(V); }
+};
+
+//===----------------------------------------------------------------------===//
+// list - A list of command line options.
+//
+template <class DataType, class StorageClass = bool,
+          class ParserClass = parser<DataType>>
+class list : public Option, public list_storage<DataType, StorageClass> {
+  std::vector<unsigned> Positions;
+  ParserClass Parser;
+
+  enum ValueExpected getValueExpectedFlagDefault() const override {
+    return Parser.getValueExpectedFlagDefault();
+  }
+  void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
+    return Parser.getExtraOptionNames(OptionNames);
+  }
+
+  bool handleOccurrence(unsigned pos, StringRef ArgName,
+                        StringRef Arg) override {
+    typename ParserClass::parser_data_type Val =
+        typename ParserClass::parser_data_type();
+    if (Parser.parse(*this, ArgName, Arg, Val))
+      return true; // Parse Error!
+    list_storage<DataType, StorageClass>::addValue(Val);
+    setPosition(pos);
+    Positions.push_back(pos);
+    return false;
+  }
+
+  // Forward printing stuff to the parser...
+  size_t getOptionWidth() const override {
+    return Parser.getOptionWidth(*this);
+  }
+  void printOptionInfo(size_t GlobalWidth) const override {
+    Parser.printOptionInfo(*this, GlobalWidth);
+  }
+
+  // Unimplemented: list options don't currently store their default value.
+  void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
+  }
+
+  void done() {
+    addArgument();
+    Parser.initialize();
+  }
+
+  // Command line options should not be copyable
+  list(const list &) = delete;
+  list &operator=(const list &) = delete;
+
+public:
+  ParserClass &getParser() { return Parser; }
+
+  unsigned getPosition(unsigned optnum) const {
+    assert(optnum < this->size() && "Invalid option index");
+    return Positions[optnum];
+  }
+
+  void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); }
+
+  template <class... Mods>
+  explicit list(const Mods &... Ms)
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
+    apply(this, Ms...);
+    done();
+  }
+};
+
+// multi_val - Modifier to set the number of additional values.
+struct multi_val {
+  unsigned AdditionalVals;
+  explicit multi_val(unsigned N) : AdditionalVals(N) {}
+
+  template <typename D, typename S, typename P>
+  void apply(list<D, S, P> &L) const {
+    L.setNumAdditionalVals(AdditionalVals);
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// bits_storage class
+
+// Default storage class definition: external storage.  This implementation
+// assumes the user will specify a variable to store the data into with the
+// cl::location(x) modifier.
+//
+template <class DataType, class StorageClass> class bits_storage {
+  unsigned *Location; // Where to store the bits...
+
+  template <class T> static unsigned Bit(const T &V) {
+    unsigned BitPos = reinterpret_cast<unsigned>(V);
+    assert(BitPos < sizeof(unsigned) * CHAR_BIT &&
+           "enum exceeds width of bit vector!");
+    return 1 << BitPos;
+  }
+
+public:
+  bits_storage() : Location(nullptr) {}
+
+  bool setLocation(Option &O, unsigned &L) {
+    if (Location)
+      return O.error("cl::location(x) specified more than once!");
+    Location = &L;
+    return false;
+  }
+
+  template <class T> void addValue(const T &V) {
+    assert(Location != 0 && "cl::location(...) not specified for a command "
+                            "line option with external storage!");
+    *Location |= Bit(V);
+  }
+
+  unsigned getBits() { return *Location; }
+
+  template <class T> bool isSet(const T &V) {
+    return (*Location & Bit(V)) != 0;
+  }
+};
+
+// Define how to hold bits.  Since we can inherit from a class, we do so.
+// This makes us exactly compatible with the bits in all cases that it is used.
+//
+template <class DataType> class bits_storage<DataType, bool> {
+  unsigned Bits; // Where to store the bits...
+
+  template <class T> static unsigned Bit(const T &V) {
+    unsigned BitPos = (unsigned)V;
+    assert(BitPos < sizeof(unsigned) * CHAR_BIT &&
+           "enum exceeds width of bit vector!");
+    return 1 << BitPos;
+  }
+
+public:
+  template <class T> void addValue(const T &V) { Bits |= Bit(V); }
+
+  unsigned getBits() { return Bits; }
+
+  template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; }
+};
+
+//===----------------------------------------------------------------------===//
+// bits - A bit vector of command options.
+//
+template <class DataType, class Storage = bool,
+          class ParserClass = parser<DataType>>
+class bits : public Option, public bits_storage<DataType, Storage> {
+  std::vector<unsigned> Positions;
+  ParserClass Parser;
+
+  enum ValueExpected getValueExpectedFlagDefault() const override {
+    return Parser.getValueExpectedFlagDefault();
+  }
+  void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
+    return Parser.getExtraOptionNames(OptionNames);
+  }
+
+  bool handleOccurrence(unsigned pos, StringRef ArgName,
+                        StringRef Arg) override {
+    typename ParserClass::parser_data_type Val =
+        typename ParserClass::parser_data_type();
+    if (Parser.parse(*this, ArgName, Arg, Val))
+      return true; // Parse Error!
+    this->addValue(Val);
+    setPosition(pos);
+    Positions.push_back(pos);
+    return false;
+  }
+
+  // Forward printing stuff to the parser...
+  size_t getOptionWidth() const override {
+    return Parser.getOptionWidth(*this);
+  }
+  void printOptionInfo(size_t GlobalWidth) const override {
+    Parser.printOptionInfo(*this, GlobalWidth);
+  }
+
+  // Unimplemented: bits options don't currently store their default values.
+  void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
+  }
+
+  void done() {
+    addArgument();
+    Parser.initialize();
+  }
+
+  // Command line options should not be copyable
+  bits(const bits &) = delete;
+  bits &operator=(const bits &) = delete;
+
+public:
+  ParserClass &getParser() { return Parser; }
+
+  unsigned getPosition(unsigned optnum) const {
+    assert(optnum < this->size() && "Invalid option index");
+    return Positions[optnum];
+  }
+
+  template <class... Mods>
+  explicit bits(const Mods &... Ms)
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
+    apply(this, Ms...);
+    done();
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Aliased command line option (alias this name to a preexisting name)
+//
+
+class alias : public Option {
+  Option *AliasFor;
+  bool handleOccurrence(unsigned pos, StringRef /*ArgName*/,
+                        StringRef Arg) override {
+    return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg);
+  }
+  bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value,
+                     bool MultiArg = false) override {
+    return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg);
+  }
+  // Handle printing stuff...
+  size_t getOptionWidth() const override;
+  void printOptionInfo(size_t GlobalWidth) const override;
+
+  // Aliases do not need to print their values.
+  void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
+  }
+
+  ValueExpected getValueExpectedFlagDefault() const override {
+    return AliasFor->getValueExpectedFlag();
+  }
+
+  void done() {
+    if (!hasArgStr())
+      error("cl::alias must have argument name specified!");
+    if (!AliasFor)
+      error("cl::alias must have an cl::aliasopt(option) specified!");
+    Subs = AliasFor->Subs;
+    addArgument();
+  }
+
+  // Command line options should not be copyable
+  alias(const alias &) = delete;
+  alias &operator=(const alias &) = delete;
+
+public:
+  void setAliasFor(Option &O) {
+    if (AliasFor)
+      error("cl::alias must only have one cl::aliasopt(...) specified!");
+    AliasFor = &O;
+  }
+
+  template <class... Mods>
+  explicit alias(const Mods &... Ms)
+      : Option(Optional, Hidden), AliasFor(nullptr) {
+    apply(this, Ms...);
+    done();
+  }
+};
+
+// aliasfor - Modifier to set the option an alias aliases.
+struct aliasopt {
+  Option &Opt;
+  explicit aliasopt(Option &O) : Opt(O) {}
+  void apply(alias &A) const { A.setAliasFor(Opt); }
+};
+
+// extrahelp - provide additional help at the end of the normal help
+// output. All occurrences of cl::extrahelp will be accumulated and
+// printed to stderr at the end of the regular help, just before
+// exit is called.
+struct extrahelp {
+  const char *morehelp;
+  explicit extrahelp(const char *help);
+};
+
+void PrintVersionMessage();
+
+/// This function just prints the help message, exactly the same way as if the
+/// -help or -help-hidden option had been given on the command line.
+///
+/// NOTE: THIS FUNCTION TERMINATES THE PROGRAM!
+///
+/// \param Hidden if true will print hidden options
+/// \param Categorized if true print options in categories
+void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
+
+//===----------------------------------------------------------------------===//
+// Public interface for accessing registered options.
+//
+
+/// \brief Use this to get a StringMap to all registered named options
+/// (e.g. -help). Note \p Map Should be an empty StringMap.
+///
+/// \return A reference to the StringMap used by the cl APIs to parse options.
+///
+/// Access to unnamed arguments (i.e. positional) are not provided because
+/// it is expected that the client already has access to these.
+///
+/// Typical usage:
+/// \code
+/// main(int argc,char* argv[]) {
+/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions();
+/// assert(opts.count("help") == 1)
+/// opts["help"]->setDescription("Show alphabetical help information")
+/// // More code
+/// llvm::cl::ParseCommandLineOptions(argc,argv);
+/// //More code
+/// }
+/// \endcode
+///
+/// This interface is useful for modifying options in libraries that are out of
+/// the control of the client. The options should be modified before calling
+/// llvm::cl::ParseCommandLineOptions().
+///
+/// Hopefully this API can be depricated soon. Any situation where options need
+/// to be modified by tools or libraries should be handled by sane APIs rather
+/// than just handing around a global list.
+StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand);
+
+//===----------------------------------------------------------------------===//
+// Standalone command line processing utilities.
+//
+
+/// \brief Tokenizes a command line that can contain escapes and quotes.
+//
+/// The quoting rules match those used by GCC and other tools that use
+/// libiberty's buildargv() or expandargv() utilities, and do not match bash.
+/// They differ from buildargv() on treatment of backslashes that do not escape
+/// a special character to make it possible to accept most Windows file paths.
+///
+/// \param [in] Source The string to be split on whitespace with quotes.
+/// \param [in] Saver Delegates back to the caller for saving parsed strings.
+/// \param [in] MarkEOLs true if tokenizing a response file and you want end of
+/// lines and end of the response file to be marked with a nullptr string.
+/// \param [out] NewArgv All parsed strings are appended to NewArgv.
+void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver,
+                            SmallVectorImpl<const char *> &NewArgv,
+                            bool MarkEOLs = false);
+
+/// \brief Tokenizes a Windows command line which may contain quotes and escaped
+/// quotes.
+///
+/// See MSDN docs for CommandLineToArgvW for information on the quoting rules.
+/// http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=vs.85).aspx
+///
+/// \param [in] Source The string to be split on whitespace with quotes.
+/// \param [in] Saver Delegates back to the caller for saving parsed strings.
+/// \param [in] MarkEOLs true if tokenizing a response file and you want end of
+/// lines and end of the response file to be marked with a nullptr string.
+/// \param [out] NewArgv All parsed strings are appended to NewArgv.
+void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver,
+                                SmallVectorImpl<const char *> &NewArgv,
+                                bool MarkEOLs = false);
+
+/// \brief String tokenization function type.  Should be compatible with either
+/// Windows or Unix command line tokenizers.
+typedef void (*TokenizerCallback)(StringRef Source, StringSaver &Saver,
+                                  SmallVectorImpl<const char *> &NewArgv,
+                                  bool MarkEOLs);
+
+/// \brief Expand response files on a command line recursively using the given
+/// StringSaver and tokenization strategy.  Argv should contain the command line
+/// before expansion and will be modified in place. If requested, Argv will
+/// also be populated with nullptrs indicating where each response file line
+/// ends, which is useful for the "/link" argument that needs to consume all
+/// remaining arguments only until the next end of line, when in a response
+/// file.
+///
+/// \param [in] Saver Delegates back to the caller for saving parsed strings.
+/// \param [in] Tokenizer Tokenization strategy. Typically Unix or Windows.
+/// \param [in,out] Argv Command line into which to expand response files.
+/// \param [in] MarkEOLs Mark end of lines and the end of the response file
+/// with nullptrs in the Argv vector.
+/// \return true if all @files were expanded successfully or there were none.
+bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
+                         SmallVectorImpl<const char *> &Argv,
+                         bool MarkEOLs = false);
+
+/// \brief Mark all options not part of this category as cl::ReallyHidden.
+///
+/// \param Category the category of options to keep displaying
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(cl::OptionCategory &Category,
+                          SubCommand &Sub = *TopLevelSubCommand);
+
+/// \brief Mark all options not part of the categories as cl::ReallyHidden.
+///
+/// \param Categories the categories of options to keep displaying.
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
+                          SubCommand &Sub = *TopLevelSubCommand);
+
+/// \brief Reset all command line options to a state that looks as if they have
+/// never appeared on the command line.  This is useful for being able to parse
+/// a command line multiple times (especially useful for writing tests).
+void ResetAllOptionOccurrences();
+
+/// \brief Reset the command line parser back to its initial state.  This
+/// removes
+/// all options, categories, and subcommands and returns the parser to a state
+/// where no options are supported.
+void ResetCommandLineParser();
+
+} // End namespace cl
+
+} // End namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Compiler.h b/third_party/llvm-subzero/include/llvm/Support/Compiler.h
new file mode 100644
index 0000000..3cf9910
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Compiler.h
@@ -0,0 +1,515 @@
+//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several macros, based on the current compiler.  This allows
+// use of compiler-specific features in a way that remains portable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_COMPILER_H
+#define LLVM_SUPPORT_COMPILER_H
+
+#include "llvm/Config/llvm-config.h"
+
+#if defined(_MSC_VER)
+#include <sal.h>
+#endif
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+#ifndef __has_extension
+# define __has_extension(x) 0
+#endif
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+
+#ifndef __has_cpp_attribute
+# define __has_cpp_attribute(x) 0
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/// \macro LLVM_GNUC_PREREQ
+/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't
+/// available.
+#ifndef LLVM_GNUC_PREREQ
+# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+#  define LLVM_GNUC_PREREQ(maj, min, patch) \
+    ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
+     ((maj) << 20) + ((min) << 10) + (patch))
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+#  define LLVM_GNUC_PREREQ(maj, min, patch) \
+    ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
+# else
+#  define LLVM_GNUC_PREREQ(maj, min, patch) 0
+# endif
+#endif
+
+/// \macro LLVM_MSC_PREREQ
+/// \brief Is the compiler MSVC of at least the specified version?
+/// The common \param version values to check for are:
+///  * 1800: Microsoft Visual Studio 2013 / 12.0
+///  * 1900: Microsoft Visual Studio 2015 / 14.0
+#ifdef _MSC_VER
+#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
+
+// We require at least MSVC 2013.
+#if !LLVM_MSC_PREREQ(1800)
+#error LLVM requires at least MSVC 2013.
+#endif
+
+#else
+#define LLVM_MSC_PREREQ(version) 0
+#endif
+
+#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900)
+#define LLVM_NOEXCEPT noexcept
+#else
+#define LLVM_NOEXCEPT throw()
+#endif
+
+/// \brief Does the compiler support ref-qualifiers for *this?
+///
+/// Sadly, this is separate from just rvalue reference support because GCC
+/// and MSVC implemented this later than everything else.
+#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
+#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
+#else
+#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
+#endif
+
+/// Expands to '&' if ref-qualifiers for *this are supported.
+///
+/// This can be used to provide lvalue/rvalue overrides of member functions.
+/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+#define LLVM_LVALUE_FUNCTION &
+#else
+#define LLVM_LVALUE_FUNCTION
+#endif
+
+#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1900)
+# define LLVM_CONSTEXPR constexpr
+#else
+# define LLVM_CONSTEXPR
+#endif
+
+/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
+/// into a shared library, then the class should be private to the library and
+/// not accessible from outside it.  Can also be used to mark variables and
+/// functions, making them private to any shared library they are linked into.
+/// On PE/COFF targets, library visibility is the default, so this isn't needed.
+#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) &&              \
+    !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)
+#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
+#else
+#define LLVM_LIBRARY_VISIBILITY
+#endif
+
+#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0)
+#define LLVM_END_WITH_NULL __attribute__((sentinel))
+#else
+#define LLVM_END_WITH_NULL
+#endif
+
+#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
+#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
+#else
+#define LLVM_ATTRIBUTE_USED
+#endif
+
+#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0)
+#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_UNUSED_RESULT _Check_return_
+#else
+#define LLVM_ATTRIBUTE_UNUSED_RESULT
+#endif
+
+// Some compilers warn about unused functions. When a function is sometimes
+// used or not depending on build settings (e.g. a function only called from
+// within "assert"), this attribute can be used to suppress such warnings.
+//
+// However, it shouldn't be used for unused *variables*, as those have a much
+// more portable solution:
+//   (void)unused_var_name;
+// Prefer cast-to-void wherever it is sufficient.
+#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0)
+#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define LLVM_ATTRIBUTE_UNUSED
+#endif
+
+// FIXME: Provide this for PE/COFF targets.
+#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) &&                    \
+    (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32))
+#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
+#else
+#define LLVM_ATTRIBUTE_WEAK
+#endif
+
+// Prior to clang 3.2, clang did not accept any spelling of
+// __has_attribute(const), so assume it is supported.
+#if defined(__clang__) || defined(__GNUC__)
+// aka 'CONST' but following LLVM Conventions.
+#define LLVM_READNONE __attribute__((__const__))
+#else
+#define LLVM_READNONE
+#endif
+
+#if __has_attribute(pure) || defined(__GNUC__)
+// aka 'PURE' but following LLVM Conventions.
+#define LLVM_READONLY __attribute__((__pure__))
+#else
+#define LLVM_READONLY
+#endif
+
+#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0)
+#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
+#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
+#else
+#define LLVM_LIKELY(EXPR) (EXPR)
+#define LLVM_UNLIKELY(EXPR) (EXPR)
+#endif
+
+/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
+/// mark a method "not for inlining".
+#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
+#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
+#else
+#define LLVM_ATTRIBUTE_NOINLINE
+#endif
+
+/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
+/// so, mark a method "always inline" because it is performance sensitive. GCC
+/// 3.4 supported this but is buggy in various cases and produces unimplemented
+/// errors, just use it in GCC 4.0 and later.
+#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
+#else
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE
+#endif
+
+#ifdef __GNUC__
+#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn)
+#else
+#define LLVM_ATTRIBUTE_NORETURN
+#endif
+
+#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL
+#endif
+
+/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
+/// pointer that does not alias any other valid pointer.
+#ifdef __GNUC__
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
+#endif
+
+/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
+#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
+#define LLVM_FALLTHROUGH [[fallthrough]]
+#elif !__cplusplus
+// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
+// error when __has_cpp_attribute is given a scoped attribute in C mode.
+#define LLVM_FALLTHROUGH
+#elif __has_cpp_attribute(clang::fallthrough)
+#define LLVM_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define LLVM_FALLTHROUGH
+#endif
+
+/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
+/// pedantic diagnostics.
+#ifdef __GNUC__
+#define LLVM_EXTENSION __extension__
+#else
+#define LLVM_EXTENSION
+#endif
+
+// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
+#if __has_feature(attribute_deprecated_with_message)
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+  decl __attribute__((deprecated(message)))
+#elif defined(__GNUC__)
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+  decl __attribute__((deprecated))
+#elif defined(_MSC_VER)
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+  __declspec(deprecated(message)) decl
+#else
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+  decl
+#endif
+
+/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
+/// to an expression which states that it is undefined behavior for the
+/// compiler to reach this point.  Otherwise is not defined.
+#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
+# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+# define LLVM_BUILTIN_UNREACHABLE __assume(false)
+#endif
+
+/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
+/// which causes the program to exit abnormally.
+#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
+# define LLVM_BUILTIN_TRAP __builtin_trap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC, does not require forward
+// declarations involving platform-specific typedefs (unlike RaiseException),
+// results in a call to vectored exception handlers, and encodes to a short
+// instruction that still causes the trapping behavior we want.
+# define LLVM_BUILTIN_TRAP __debugbreak()
+#else
+# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
+#endif
+
+/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to
+/// an expression which causes the program to break while running
+/// under a debugger.
+#if __has_builtin(__builtin_debugtrap)
+# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC and breaks while
+// running under the debugger, and also supports invoking a debugger
+// when the OS is configured appropriately.
+# define LLVM_BUILTIN_DEBUGTRAP __debugbreak()
+#else
+// Just continue execution when built with compilers that have no
+// support. This is a debugging aid and not intended to force the
+// program to abort if encountered.
+# define LLVM_BUILTIN_DEBUGTRAP
+#endif
+
+/// \macro LLVM_ASSUME_ALIGNED
+/// \brief Returns a pointer with an assumed alignment.
+#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
+# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
+#elif defined(LLVM_BUILTIN_UNREACHABLE)
+// As of today, clang does not support __builtin_assume_aligned.
+# define LLVM_ASSUME_ALIGNED(p, a) \
+           (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p)))
+#else
+# define LLVM_ASSUME_ALIGNED(p, a) (p)
+#endif
+
+/// \macro LLVM_ALIGNAS
+/// \brief Used to specify a minimum alignment for a structure or variable. The
+/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute
+/// alignments in terms of the size of a pointer.
+///
+/// Note that __declspec(align) has special quirks, it's not legal to pass a
+/// structure with __declspec(align) as a formal parameter.
+#ifdef _MSC_VER
+# define LLVM_ALIGNAS(x) __declspec(align(x))
+#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0)
+# define LLVM_ALIGNAS(x) __attribute__((aligned(x)))
+#else
+# define LLVM_ALIGNAS(x) alignas(x)
+#endif
+
+/// \macro LLVM_PACKED
+/// \brief Used to specify a packed structure.
+/// LLVM_PACKED(
+///    struct A {
+///      int i;
+///      int j;
+///      int k;
+///      long long l;
+///   });
+///
+/// LLVM_PACKED_START
+/// struct B {
+///   int i;
+///   int j;
+///   int k;
+///   long long l;
+/// };
+/// LLVM_PACKED_END 
+#ifdef _MSC_VER
+# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
+# define LLVM_PACKED_START __pragma(pack(push, 1))
+# define LLVM_PACKED_END   __pragma(pack(pop))
+#else
+# define LLVM_PACKED(d) d __attribute__((packed))
+# define LLVM_PACKED_START _Pragma("pack(push, 1)")
+# define LLVM_PACKED_END   _Pragma("pack(pop)")
+#endif
+
+/// \macro LLVM_PTR_SIZE
+/// \brief A constant integer equivalent to the value of sizeof(void*).
+/// Generally used in combination with LLVM_ALIGNAS or when doing computation in
+/// the preprocessor.
+#ifdef __SIZEOF_POINTER__
+# define LLVM_PTR_SIZE __SIZEOF_POINTER__
+#elif defined(_WIN64)
+# define LLVM_PTR_SIZE 8
+#elif defined(_WIN32)
+# define LLVM_PTR_SIZE 4
+#elif defined(_MSC_VER)
+# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
+#else
+# define LLVM_PTR_SIZE sizeof(void *)
+#endif
+
+/// \macro LLVM_FUNCTION_NAME
+/// \brief Expands to __func__ on compilers which support it.  Otherwise,
+/// expands to a compiler-dependent replacement.
+#if defined(_MSC_VER)
+# define LLVM_FUNCTION_NAME __FUNCTION__
+#else
+# define LLVM_FUNCTION_NAME __func__
+#endif
+
+/// \macro LLVM_MEMORY_SANITIZER_BUILD
+/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation.
+#if __has_feature(memory_sanitizer)
+# define LLVM_MEMORY_SANITIZER_BUILD 1
+# include <sanitizer/msan_interface.h>
+#else
+# define LLVM_MEMORY_SANITIZER_BUILD 0
+# define __msan_allocated_memory(p, size)
+# define __msan_unpoison(p, size)
+#endif
+
+/// \macro LLVM_ADDRESS_SANITIZER_BUILD
+/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation.
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# define LLVM_ADDRESS_SANITIZER_BUILD 1
+# include <sanitizer/asan_interface.h>
+#else
+# define LLVM_ADDRESS_SANITIZER_BUILD 0
+# define __asan_poison_memory_region(p, size)
+# define __asan_unpoison_memory_region(p, size)
+#endif
+
+/// \macro LLVM_THREAD_SANITIZER_BUILD
+/// \brief Whether LLVM itself is built with ThreadSanitizer instrumentation.
+#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# define LLVM_THREAD_SANITIZER_BUILD 1
+#else
+# define LLVM_THREAD_SANITIZER_BUILD 0
+#endif
+
+#if LLVM_THREAD_SANITIZER_BUILD
+// Thread Sanitizer is a tool that finds races in code.
+// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
+// tsan detects these exact functions by name.
+#ifdef __cplusplus
+extern "C" {
+#endif
+void AnnotateHappensAfter(const char *file, int line, const volatile void *cv);
+void AnnotateHappensBefore(const char *file, int line, const volatile void *cv);
+void AnnotateIgnoreWritesBegin(const char *file, int line);
+void AnnotateIgnoreWritesEnd(const char *file, int line);
+#ifdef __cplusplus
+}
+#endif
+
+// This marker is used to define a happens-before arc. The race detector will
+// infer an arc from the begin to the end when they share the same pointer
+// argument.
+# define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__, __LINE__, cv)
+
+// This marker defines the destination of a happens-before arc.
+# define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__, __LINE__, cv)
+
+// Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
+# define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+// Resume checking for racy writes.
+# define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+#else
+# define TsanHappensBefore(cv)
+# define TsanHappensAfter(cv)
+# define TsanIgnoreWritesBegin()
+# define TsanIgnoreWritesEnd()
+#endif
+
+/// \macro LLVM_NO_SANITIZE
+/// \brief Disable a particular sanitizer for a function.
+#if __has_attribute(no_sanitize)
+#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND)))
+#else
+#define LLVM_NO_SANITIZE(KIND)
+#endif
+
+/// \brief Mark debug helper function definitions like dump() that should not be
+/// stripped from debug builds.
+// FIXME: Move this to a private config.h as it's not usable in public headers.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
+#else
+#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
+#endif
+
+/// \macro LLVM_PRETTY_FUNCTION
+/// \brief Gets a user-friendly looking function signature for the current scope
+/// using the best available method on each platform.  The exact format of the
+/// resulting string is implementation specific and non-portable, so this should
+/// only be used, for example, for logging or diagnostics.
+#if defined(_MSC_VER)
+#define LLVM_PRETTY_FUNCTION __FUNCSIG__
+#elif defined(__GNUC__) || defined(__clang__)
+#define LLVM_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else 
+#define LLVM_PRETTY_FUNCTION __func__
+#endif
+
+/// \macro LLVM_THREAD_LOCAL
+/// \brief A thread-local storage specifier which can be used with globals,
+/// extern globals, and static globals.
+///
+/// This is essentially an extremely restricted analog to C++11's thread_local
+/// support, and uses that when available. However, it falls back on
+/// platform-specific or vendor-provided extensions when necessary. These
+/// extensions don't support many of the C++11 thread_local's features. You
+/// should only use this for PODs that you can statically initialize to
+/// some constant value. In almost all circumstances this is most appropriate
+/// for use with a pointer, integer, or small aggregation of pointers and
+/// integers.
+#if LLVM_ENABLE_THREADS
+#if __has_feature(cxx_thread_local)
+#define LLVM_THREAD_LOCAL thread_local
+#elif defined(_MSC_VER)
+// MSVC supports this with a __declspec.
+#define LLVM_THREAD_LOCAL __declspec(thread)
+#else
+// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
+// we only need the restricted functionality that provides.
+#define LLVM_THREAD_LOCAL __thread
+#endif
+#else // !LLVM_ENABLE_THREADS
+// If threading is disabled entirely, this compiles to nothing and you get
+// a normal global variable.
+#define LLVM_THREAD_LOCAL
+#endif
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ConvertUTF.h b/third_party/llvm-subzero/include/llvm/Support/ConvertUTF.h
new file mode 100644
index 0000000..5de5774
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ConvertUTF.h
@@ -0,0 +1,299 @@
+/*===--- ConvertUTF.h - Universal Character Names conversions ---------------===
+ *
+ *                     The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *==------------------------------------------------------------------------==*/
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+    Conversions between UTF32, UTF-16, and UTF-8.  Header file.
+
+    Several funtions are included here, forming a complete set of
+    conversions between the three formats.  UTF-7 is not included
+    here, but is handled in a separate source file.
+
+    Each of these routines takes pointers to input buffers and output
+    buffers.  The input buffers are const.
+
+    Each routine converts the text between *sourceStart and sourceEnd,
+    putting the result into the buffer between *targetStart and
+    targetEnd. Note: the end pointers are *after* the last item: e.g.
+    *(sourceEnd - 1) is the last item.
+
+    The return result indicates whether the conversion was successful,
+    and if not, whether the problem was in the source or target buffers.
+    (Only the first encountered problem is indicated.)
+
+    After the conversion, *sourceStart and *targetStart are both
+    updated to point to the end of last text successfully converted in
+    the respective buffers.
+
+    Input parameters:
+        sourceStart - pointer to a pointer to the source buffer.
+                The contents of this are modified on return so that
+                it points at the next thing to be converted.
+        targetStart - similarly, pointer to pointer to the target buffer.
+        sourceEnd, targetEnd - respectively pointers to the ends of the
+                two buffers, for overflow checking only.
+
+    These conversion functions take a ConversionFlags argument. When this
+    flag is set to strict, both irregular sequences and isolated surrogates
+    will cause an error.  When the flag is set to lenient, both irregular
+    sequences and isolated surrogates are converted.
+
+    Whether the flag is strict or lenient, all illegal sequences will cause
+    an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+    or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+    must check for illegal sequences.
+
+    When the flag is set to lenient, characters over 0x10FFFF are converted
+    to the replacement character; otherwise (when the flag is set to strict)
+    they constitute an error.
+
+    Output parameters:
+        The value "sourceIllegal" is returned from some routines if the input
+        sequence is malformed.  When "sourceIllegal" is returned, the source
+        value will point to the illegal value that caused the problem. E.g.,
+        in UTF-8 when a sequence is malformed, it points to the start of the
+        malformed sequence.
+
+    Author: Mark E. Davis, 1994.
+    Rev History: Rick McGowan, fixes & updates May 2001.
+         Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+#ifndef LLVM_SUPPORT_CONVERTUTF_H
+#define LLVM_SUPPORT_CONVERTUTF_H
+
+/* ---------------------------------------------------------------------
+    The following 4 definitions are compiler-specific.
+    The C standard does not guarantee that wchar_t has at least
+    16 bits, so wchar_t is no less portable than unsigned short!
+    All should be unsigned values to avoid sign extension during
+    bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned int    UTF32;  /* at least 32 bits */
+typedef unsigned short  UTF16;  /* at least 16 bits */
+typedef unsigned char   UTF8;   /* typically 8 bits */
+typedef unsigned char   Boolean; /* 0 or 1 */
+
+/* Some fundamental constants */
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4
+
+#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE  0xFEFF
+#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE
+
+typedef enum {
+  conversionOK,           /* conversion successful */
+  sourceExhausted,        /* partial character in source, but hit end */
+  targetExhausted,        /* insuff. room in target for conversion */
+  sourceIllegal           /* source sequence is illegal/malformed */
+} ConversionResult;
+
+typedef enum {
+  strictConversion = 0,
+  lenientConversion
+} ConversionFlags;
+
+/* This is for C++ and does no harm in C */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ConversionResult ConvertUTF8toUTF16 (
+  const UTF8** sourceStart, const UTF8* sourceEnd,
+  UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+/**
+ * Convert a partial UTF8 sequence to UTF32.  If the sequence ends in an
+ * incomplete code unit sequence, returns \c sourceExhausted.
+ */
+ConversionResult ConvertUTF8toUTF32Partial(
+  const UTF8** sourceStart, const UTF8* sourceEnd,
+  UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+/**
+ * Convert a partial UTF8 sequence to UTF32.  If the sequence ends in an
+ * incomplete code unit sequence, returns \c sourceIllegal.
+ */
+ConversionResult ConvertUTF8toUTF32(
+  const UTF8** sourceStart, const UTF8* sourceEnd,
+  UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF8 (
+  const UTF16** sourceStart, const UTF16* sourceEnd,
+  UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF8 (
+  const UTF32** sourceStart, const UTF32* sourceEnd,
+  UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF32 (
+  const UTF16** sourceStart, const UTF16* sourceEnd,
+  UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF16 (
+  const UTF32** sourceStart, const UTF32* sourceEnd,
+  UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+
+Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd);
+
+unsigned getNumBytesForUTF8(UTF8 firstByte);
+
+#ifdef __cplusplus
+}
+
+/*************************************************************************/
+/* Below are LLVM-specific wrappers of the functions above. */
+
+#include <string>
+#include <cstddef>
+
+namespace llvm {
+template <typename T> class ArrayRef;
+template <typename T> class SmallVectorImpl;
+class StringRef;
+
+/**
+ * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on
+ * WideCharWidth. The converted data is written to ResultPtr, which needs to
+ * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success,
+ * ResultPtr will point one after the end of the copied string. On failure,
+ * ResultPtr will not be changed, and ErrorPtr will be set to the location of
+ * the first character which could not be converted.
+ * \return true on success.
+ */
+bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
+                       char *&ResultPtr, const UTF8 *&ErrorPtr);
+
+/**
+* Converts a UTF-8 StringRef to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result);
+
+/**
+* Converts a UTF-8 C-string to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result);
+
+/**
+* Converts a std::wstring to a UTF-8 encoded std::string.
+* \return true on success.
+*/
+bool convertWideToUTF8(const std::wstring &Source, std::string &Result);
+
+
+/**
+ * Convert an Unicode code point to UTF8 sequence.
+ *
+ * \param Source a Unicode code point.
+ * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least
+ * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes.  On success \c ResultPtr is
+ * updated one past end of the converted sequence.
+ *
+ * \returns true on success.
+ */
+bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr);
+
+/**
+ * Convert the first UTF8 sequence in the given source buffer to a UTF32
+ * code point.
+ *
+ * \param [in,out] source A pointer to the source buffer. If the conversion
+ * succeeds, this pointer will be updated to point to the byte just past the
+ * end of the converted sequence.
+ * \param sourceEnd A pointer just past the end of the source buffer.
+ * \param [out] target The converted code
+ * \param flags Whether the conversion is strict or lenient.
+ *
+ * \returns conversionOK on success
+ *
+ * \sa ConvertUTF8toUTF32
+ */
+static inline ConversionResult convertUTF8Sequence(const UTF8 **source,
+                                                   const UTF8 *sourceEnd,
+                                                   UTF32 *target,
+                                                   ConversionFlags flags) {
+  if (*source == sourceEnd)
+    return sourceExhausted;
+  unsigned size = getNumBytesForUTF8(**source);
+  if ((ptrdiff_t)size > sourceEnd - *source)
+    return sourceExhausted;
+  return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags);
+}
+
+/**
+ * Returns true if a blob of text starts with a UTF-16 big or little endian byte
+ * order mark.
+ */
+bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes);
+
+/**
+ * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
+ *
+ * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text.
+ * \param [out] Out Converted UTF-8 is stored here on success.
+ * \returns true on success
+ */
+bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out);
+
+/**
+* Converts a UTF16 string into a UTF8 std::string.
+*
+* \param [in] Src A buffer of UTF-16 encoded text.
+* \param [out] Out Converted UTF-8 is stored here on success.
+* \returns true on success
+*/
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out);
+
+/**
+ * Converts a UTF-8 string into a UTF-16 string with native endianness.
+ *
+ * \returns true on success
+ */
+bool convertUTF8ToUTF16String(StringRef SrcUTF8,
+                              SmallVectorImpl<UTF16> &DstUTF16);
+
+} /* end namespace llvm */
+
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/DataStream.h b/third_party/llvm-subzero/include/llvm/Support/DataStream.h
new file mode 100644
index 0000000..a544316
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/DataStream.h
@@ -0,0 +1,38 @@
+//===---- llvm/Support/DataStream.h - Lazy bitcode streaming ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines DataStreamer, which fetches bytes of data from
+// a stream source. It provides support for streaming (lazy reading) of
+// data, e.g. bitcode
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_SUPPORT_DATASTREAM_H
+#define LLVM_SUPPORT_DATASTREAM_H
+
+#include <memory>
+#include <string>
+
+namespace llvm {
+
+class DataStreamer {
+public:
+  /// Fetch bytes [start-end) from the stream, and write them to the
+  /// buffer pointed to by buf. Returns the number of bytes actually written.
+  virtual size_t GetBytes(unsigned char *buf, size_t len) = 0;
+
+  virtual ~DataStreamer();
+};
+
+std::unique_ptr<DataStreamer> getDataFileStreamer(const std::string &Filename,
+                                                  std::string *Err);
+}
+
+#endif  // LLVM_SUPPORT_DATASTREAM_H_
diff --git a/third_party/llvm-subzero/include/llvm/Support/DataTypes.h b/third_party/llvm-subzero/include/llvm/Support/DataTypes.h
new file mode 100644
index 0000000..329c819
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/DataTypes.h
@@ -0,0 +1,213 @@
+/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file contains definitions to figure out the size of _HOST_ data types.*|
+|* This file is important because different host OS's define different macros,*|
+|* which makes portability tough.  This file exports the following            *|
+|* definitions:                                                               *|
+|*                                                                            *|
+|*   [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*|
+|*   [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values.     *|
+|*                                                                            *|
+|* No library is required when using these functions.                         *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*/
+
+/* Please leave this file C-compatible. */
+
+/* Please keep this file in sync with DataTypes.h.in */
+
+#ifndef SUPPORT_DATATYPES_H
+#define SUPPORT_DATATYPES_H
+
+#define HAVE_SYS_TYPES_H 1
+/* #undef HAVE_INTTYPES_H */
+#define HAVE_STDINT_H 1
+#define HAVE_UINT64_T 1
+/* #undef HAVE_U_INT64_T */
+
+#ifdef __cplusplus
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+#ifndef _MSC_VER
+
+/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS
+   being defined.  We would define it here, but in order to prevent Bad Things
+   happening when system headers or C++ STL headers include stdint.h before we
+   define it here, we define it on the g++ command line (in Makefile.rules). */
+#if !defined(__STDC_LIMIT_MACROS)
+#error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h"
+#endif
+
+#if !defined(__STDC_CONSTANT_MACROS)
+#error "Must #define __STDC_CONSTANT_MACROS before " \
+        "#including Support/DataTypes.h"
+#endif
+
+/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef _AIX
+#include "llvm/Support/AIXDataTypesFix.h"
+#endif
+
+/* Handle incorrect definition of uint64_t as u_int64_t */
+#ifndef HAVE_UINT64_T
+#ifdef HAVE_U_INT64_T
+typedef u_int64_t uint64_t;
+#else
+#error "Don't have a definition for uint64_t on this platform"
+#endif
+#endif
+
+#ifdef _OpenBSD_
+#define INT8_MAX 127
+#define INT8_MIN -128
+#define UINT8_MAX 255
+#define INT16_MAX 32767
+#define INT16_MIN -32768
+#define UINT16_MAX 65535
+#define INT32_MAX 2147483647
+#define INT32_MIN -2147483648
+#define UINT32_MAX 4294967295U
+#endif
+
+#else /* _MSC_VER */
+/* Visual C++ doesn't provide standard integer headers, but it does provide
+   built-in data types. */
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#ifdef __cplusplus
+#include <cmath>
+#else
+#include <math.h>
+#endif
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed int ssize_t;
+#ifndef INT8_MAX
+#define INT8_MAX 127
+#endif
+#ifndef INT8_MIN
+#define INT8_MIN -128
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX 255
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX 32767
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN -32768
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX 65535
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX 2147483647
+#endif
+#ifndef INT32_MIN
+/* MSC treats -2147483648 as -(2147483648U). */
+#define INT32_MIN (-INT32_MAX - 1)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX 4294967295U
+#endif
+/* Certain compatibility updates to VC++ introduce the `cstdint'
+ * header, which defines the INT*_C macros. On default installs they
+ * are absent. */
+#ifndef INT8_C
+#define INT8_C(C) C##i8
+#endif
+#ifndef UINT8_C
+#define UINT8_C(C) C##ui8
+#endif
+#ifndef INT16_C
+#define INT16_C(C) C##i16
+#endif
+#ifndef UINT16_C
+#define UINT16_C(C) C##ui16
+#endif
+#ifndef INT32_C
+#define INT32_C(C) C##i32
+#endif
+#ifndef UINT32_C
+#define UINT32_C(C) C##ui32
+#endif
+#ifndef INT64_C
+#define INT64_C(C) C##i64
+#endif
+#ifndef UINT64_C
+#define UINT64_C(C) C##ui64
+#endif
+
+#ifndef PRId64
+# define PRId64 "I64d"
+#endif
+#ifndef PRIi64
+# define PRIu64 "I64i"
+#endif
+#ifndef PRIo64
+# define PRIx64 "I64o"
+#endif
+#ifndef PRIu64
+# define PRIu64 "I64u"
+#endif
+#ifndef PRIx64
+# define PRIx64 "I64x"
+#endif
+#ifndef PRIX64
+# define PRIX64 "I64X"
+#endif
+
+#endif /* _MSC_VER */
+
+/* Set defaults for constants which we cannot find. */
+#if !defined(INT64_MAX)
+#define INT64_MAX 9223372036854775807LL
+#endif
+#if !defined(INT64_MIN)
+#define INT64_MIN ((-INT64_MAX) - 1)
+#endif
+#if !defined(UINT64_MAX)
+#define UINT64_MAX 0xffffffffffffffffULL
+#endif
+
+#if __GNUC__ > 3
+#define END_WITH_NULL __attribute__((sentinel))
+#else
+#define END_WITH_NULL
+#endif
+
+#ifndef HUGE_VALF
+#define HUGE_VALF (float)HUGE_VAL
+#endif
+
+#endif /* SUPPORT_DATATYPES_H */
diff --git a/third_party/llvm-subzero/include/llvm/Support/Debug.h b/third_party/llvm-subzero/include/llvm/Support/Debug.h
new file mode 100644
index 0000000..dc42379
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Debug.h
@@ -0,0 +1,97 @@
+//===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a handy way of adding debugging information to your
+// code, without it being enabled all of the time, and without having to add
+// command line options to enable it.
+//
+// In particular, just wrap your code with the DEBUG() macro, and it will be
+// enabled automatically if you specify '-debug' on the command-line.
+// DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo" specify
+// that your debug code belongs to class "foo". Be careful that you only do
+// this after including Debug.h and not around any #include of headers. Headers
+// should define and undef the macro acround the code that needs to use the
+// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo'
+// to enable JUST the debug information for the foo class.
+//
+// When compiling without assertions, the -debug-* options and all code in
+// DEBUG() statements disappears, so it does not affect the runtime of the code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DEBUG_H
+#define LLVM_SUPPORT_DEBUG_H
+
+namespace llvm {
+
+class raw_ostream;
+
+#ifndef NDEBUG
+/// DebugFlag - This boolean is set to true if the '-debug' command line option
+/// is specified.  This should probably not be referenced directly, instead, use
+/// the DEBUG macro below.
+///
+extern bool DebugFlag;
+
+/// isCurrentDebugType - Return true if the specified string is the debug type
+/// specified on the command line, or if none was specified on the command line
+/// with the -debug-only=X option.
+///
+bool isCurrentDebugType(const char *Type);
+
+/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X
+/// option were specified.  Note that DebugFlag also needs to be set to true for
+/// debug output to be produced.
+///
+void setCurrentDebugType(const char *Type);
+
+/// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug
+/// information.  In the '-debug' option is specified on the commandline, and if
+/// this is a debug build, then the code specified as the option to the macro
+/// will be executed.  Otherwise it will not be.  Example:
+///
+/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n");
+///
+/// This will emit the debug information if -debug is present, and -debug-only
+/// is not specified, or is specified as "bitset".
+#define DEBUG_WITH_TYPE(TYPE, X)                                        \
+  do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)) { X; } \
+  } while (false)
+
+#else
+#define isCurrentDebugType(X) (false)
+#define setCurrentDebugType(X)
+#define DEBUG_WITH_TYPE(TYPE, X) do { } while (false)
+#endif
+
+/// EnableDebugBuffering - This defaults to false.  If true, the debug
+/// stream will install signal handlers to dump any buffered debug
+/// output.  It allows clients to selectively allow the debug stream
+/// to install signal handlers if they are certain there will be no
+/// conflict.
+///
+extern bool EnableDebugBuffering;
+
+/// dbgs() - This returns a reference to a raw_ostream for debugging
+/// messages.  If debugging is disabled it returns errs().  Use it
+/// like: dbgs() << "foo" << "bar";
+raw_ostream &dbgs();
+
+// DEBUG macro - This macro should be used by passes to emit debug information.
+// In the '-debug' option is specified on the commandline, and if this is a
+// debug build, then the code specified as the option to the macro will be
+// executed.  Otherwise it will not be.  Example:
+//
+// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n");
+//
+#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X)
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_DEBUG_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELF.h b/third_party/llvm-subzero/include/llvm/Support/ELF.h
new file mode 100644
index 0000000..826c0de
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELF.h
@@ -0,0 +1,1370 @@
+//===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains common, non-processor-specific data structures and
+// constants for the ELF file format.
+//
+// The details of the ELF32 bits in this file are largely based on the Tool
+// Interface Standard (TIS) Executable and Linking Format (ELF) Specification
+// Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format
+// Version 1.5, Draft 2, May 1998 as well as OpenBSD header files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ELF_H
+#define LLVM_SUPPORT_ELF_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include <cstring>
+
+namespace llvm {
+
+namespace ELF {
+
+typedef uint32_t Elf32_Addr; // Program address
+typedef uint32_t Elf32_Off;  // File offset
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Word;
+typedef int32_t  Elf32_Sword;
+
+typedef uint64_t Elf64_Addr;
+typedef uint64_t Elf64_Off;
+typedef uint16_t Elf64_Half;
+typedef uint32_t Elf64_Word;
+typedef int32_t  Elf64_Sword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t  Elf64_Sxword;
+
+// Object file magic string.
+static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' };
+
+// e_ident size and indices.
+enum {
+  EI_MAG0       = 0,          // File identification index.
+  EI_MAG1       = 1,          // File identification index.
+  EI_MAG2       = 2,          // File identification index.
+  EI_MAG3       = 3,          // File identification index.
+  EI_CLASS      = 4,          // File class.
+  EI_DATA       = 5,          // Data encoding.
+  EI_VERSION    = 6,          // File version.
+  EI_OSABI      = 7,          // OS/ABI identification.
+  EI_ABIVERSION = 8,          // ABI version.
+  EI_PAD        = 9,          // Start of padding bytes.
+  EI_NIDENT     = 16          // Number of bytes in e_ident.
+};
+
+struct Elf32_Ehdr {
+  unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes
+  Elf32_Half    e_type;      // Type of file (see ET_* below)
+  Elf32_Half    e_machine;   // Required architecture for this file (see EM_*)
+  Elf32_Word    e_version;   // Must be equal to 1
+  Elf32_Addr    e_entry;     // Address to jump to in order to start program
+  Elf32_Off     e_phoff;     // Program header table's file offset, in bytes
+  Elf32_Off     e_shoff;     // Section header table's file offset, in bytes
+  Elf32_Word    e_flags;     // Processor-specific flags
+  Elf32_Half    e_ehsize;    // Size of ELF header, in bytes
+  Elf32_Half    e_phentsize; // Size of an entry in the program header table
+  Elf32_Half    e_phnum;     // Number of entries in the program header table
+  Elf32_Half    e_shentsize; // Size of an entry in the section header table
+  Elf32_Half    e_shnum;     // Number of entries in the section header table
+  Elf32_Half    e_shstrndx;  // Sect hdr table index of sect name string table
+  bool checkMagic() const {
+    return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0;
+  }
+  unsigned char getFileClass() const { return e_ident[EI_CLASS]; }
+  unsigned char getDataEncoding() const { return e_ident[EI_DATA]; }
+};
+
+// 64-bit ELF header. Fields are the same as for ELF32, but with different
+// types (see above).
+struct Elf64_Ehdr {
+  unsigned char e_ident[EI_NIDENT];
+  Elf64_Half    e_type;
+  Elf64_Half    e_machine;
+  Elf64_Word    e_version;
+  Elf64_Addr    e_entry;
+  Elf64_Off     e_phoff;
+  Elf64_Off     e_shoff;
+  Elf64_Word    e_flags;
+  Elf64_Half    e_ehsize;
+  Elf64_Half    e_phentsize;
+  Elf64_Half    e_phnum;
+  Elf64_Half    e_shentsize;
+  Elf64_Half    e_shnum;
+  Elf64_Half    e_shstrndx;
+  bool checkMagic() const {
+    return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0;
+  }
+  unsigned char getFileClass() const { return e_ident[EI_CLASS]; }
+  unsigned char getDataEncoding() const { return e_ident[EI_DATA]; }
+};
+
+// File types
+enum {
+  ET_NONE   = 0,      // No file type
+  ET_REL    = 1,      // Relocatable file
+  ET_EXEC   = 2,      // Executable file
+  ET_DYN    = 3,      // Shared object file
+  ET_CORE   = 4,      // Core file
+  ET_LOPROC = 0xff00, // Beginning of processor-specific codes
+  ET_HIPROC = 0xffff  // Processor-specific
+};
+
+// Versioning
+enum {
+  EV_NONE = 0,
+  EV_CURRENT = 1
+};
+
+// Machine architectures
+// See current registered ELF machine architectures at:
+//    http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html
+enum {
+  EM_NONE          = 0, // No machine
+  EM_M32           = 1, // AT&T WE 32100
+  EM_SPARC         = 2, // SPARC
+  EM_386           = 3, // Intel 386
+  EM_68K           = 4, // Motorola 68000
+  EM_88K           = 5, // Motorola 88000
+  EM_IAMCU         = 6, // Intel MCU
+  EM_860           = 7, // Intel 80860
+  EM_MIPS          = 8, // MIPS R3000
+  EM_S370          = 9, // IBM System/370
+  EM_MIPS_RS3_LE   = 10, // MIPS RS3000 Little-endian
+  EM_PARISC        = 15, // Hewlett-Packard PA-RISC
+  EM_VPP500        = 17, // Fujitsu VPP500
+  EM_SPARC32PLUS   = 18, // Enhanced instruction set SPARC
+  EM_960           = 19, // Intel 80960
+  EM_PPC           = 20, // PowerPC
+  EM_PPC64         = 21, // PowerPC64
+  EM_S390          = 22, // IBM System/390
+  EM_SPU           = 23, // IBM SPU/SPC
+  EM_V800          = 36, // NEC V800
+  EM_FR20          = 37, // Fujitsu FR20
+  EM_RH32          = 38, // TRW RH-32
+  EM_RCE           = 39, // Motorola RCE
+  EM_ARM           = 40, // ARM
+  EM_ALPHA         = 41, // DEC Alpha
+  EM_SH            = 42, // Hitachi SH
+  EM_SPARCV9       = 43, // SPARC V9
+  EM_TRICORE       = 44, // Siemens TriCore
+  EM_ARC           = 45, // Argonaut RISC Core
+  EM_H8_300        = 46, // Hitachi H8/300
+  EM_H8_300H       = 47, // Hitachi H8/300H
+  EM_H8S           = 48, // Hitachi H8S
+  EM_H8_500        = 49, // Hitachi H8/500
+  EM_IA_64         = 50, // Intel IA-64 processor architecture
+  EM_MIPS_X        = 51, // Stanford MIPS-X
+  EM_COLDFIRE      = 52, // Motorola ColdFire
+  EM_68HC12        = 53, // Motorola M68HC12
+  EM_MMA           = 54, // Fujitsu MMA Multimedia Accelerator
+  EM_PCP           = 55, // Siemens PCP
+  EM_NCPU          = 56, // Sony nCPU embedded RISC processor
+  EM_NDR1          = 57, // Denso NDR1 microprocessor
+  EM_STARCORE      = 58, // Motorola Star*Core processor
+  EM_ME16          = 59, // Toyota ME16 processor
+  EM_ST100         = 60, // STMicroelectronics ST100 processor
+  EM_TINYJ         = 61, // Advanced Logic Corp. TinyJ embedded processor family
+  EM_X86_64        = 62, // AMD x86-64 architecture
+  EM_PDSP          = 63, // Sony DSP Processor
+  EM_PDP10         = 64, // Digital Equipment Corp. PDP-10
+  EM_PDP11         = 65, // Digital Equipment Corp. PDP-11
+  EM_FX66          = 66, // Siemens FX66 microcontroller
+  EM_ST9PLUS       = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller
+  EM_ST7           = 68, // STMicroelectronics ST7 8-bit microcontroller
+  EM_68HC16        = 69, // Motorola MC68HC16 Microcontroller
+  EM_68HC11        = 70, // Motorola MC68HC11 Microcontroller
+  EM_68HC08        = 71, // Motorola MC68HC08 Microcontroller
+  EM_68HC05        = 72, // Motorola MC68HC05 Microcontroller
+  EM_SVX           = 73, // Silicon Graphics SVx
+  EM_ST19          = 74, // STMicroelectronics ST19 8-bit microcontroller
+  EM_VAX           = 75, // Digital VAX
+  EM_CRIS          = 76, // Axis Communications 32-bit embedded processor
+  EM_JAVELIN       = 77, // Infineon Technologies 32-bit embedded processor
+  EM_FIREPATH      = 78, // Element 14 64-bit DSP Processor
+  EM_ZSP           = 79, // LSI Logic 16-bit DSP Processor
+  EM_MMIX          = 80, // Donald Knuth's educational 64-bit processor
+  EM_HUANY         = 81, // Harvard University machine-independent object files
+  EM_PRISM         = 82, // SiTera Prism
+  EM_AVR           = 83, // Atmel AVR 8-bit microcontroller
+  EM_FR30          = 84, // Fujitsu FR30
+  EM_D10V          = 85, // Mitsubishi D10V
+  EM_D30V          = 86, // Mitsubishi D30V
+  EM_V850          = 87, // NEC v850
+  EM_M32R          = 88, // Mitsubishi M32R
+  EM_MN10300       = 89, // Matsushita MN10300
+  EM_MN10200       = 90, // Matsushita MN10200
+  EM_PJ            = 91, // picoJava
+  EM_OPENRISC      = 92, // OpenRISC 32-bit embedded processor
+  EM_ARC_COMPACT   = 93, // ARC International ARCompact processor (old
+                         // spelling/synonym: EM_ARC_A5)
+  EM_XTENSA        = 94, // Tensilica Xtensa Architecture
+  EM_VIDEOCORE     = 95, // Alphamosaic VideoCore processor
+  EM_TMM_GPP       = 96, // Thompson Multimedia General Purpose Processor
+  EM_NS32K         = 97, // National Semiconductor 32000 series
+  EM_TPC           = 98, // Tenor Network TPC processor
+  EM_SNP1K         = 99, // Trebia SNP 1000 processor
+  EM_ST200         = 100, // STMicroelectronics (www.st.com) ST200
+  EM_IP2K          = 101, // Ubicom IP2xxx microcontroller family
+  EM_MAX           = 102, // MAX Processor
+  EM_CR            = 103, // National Semiconductor CompactRISC microprocessor
+  EM_F2MC16        = 104, // Fujitsu F2MC16
+  EM_MSP430        = 105, // Texas Instruments embedded microcontroller msp430
+  EM_BLACKFIN      = 106, // Analog Devices Blackfin (DSP) processor
+  EM_SE_C33        = 107, // S1C33 Family of Seiko Epson processors
+  EM_SEP           = 108, // Sharp embedded microprocessor
+  EM_ARCA          = 109, // Arca RISC Microprocessor
+  EM_UNICORE       = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC
+                          // of Peking University
+  EM_EXCESS        = 111, // eXcess: 16/32/64-bit configurable embedded CPU
+  EM_DXP           = 112, // Icera Semiconductor Inc. Deep Execution Processor
+  EM_ALTERA_NIOS2  = 113, // Altera Nios II soft-core processor
+  EM_CRX           = 114, // National Semiconductor CompactRISC CRX
+  EM_XGATE         = 115, // Motorola XGATE embedded processor
+  EM_C166          = 116, // Infineon C16x/XC16x processor
+  EM_M16C          = 117, // Renesas M16C series microprocessors
+  EM_DSPIC30F      = 118, // Microchip Technology dsPIC30F Digital Signal
+                          // Controller
+  EM_CE            = 119, // Freescale Communication Engine RISC core
+  EM_M32C          = 120, // Renesas M32C series microprocessors
+  EM_TSK3000       = 131, // Altium TSK3000 core
+  EM_RS08          = 132, // Freescale RS08 embedded processor
+  EM_SHARC         = 133, // Analog Devices SHARC family of 32-bit DSP
+                          // processors
+  EM_ECOG2         = 134, // Cyan Technology eCOG2 microprocessor
+  EM_SCORE7        = 135, // Sunplus S+core7 RISC processor
+  EM_DSP24         = 136, // New Japan Radio (NJR) 24-bit DSP Processor
+  EM_VIDEOCORE3    = 137, // Broadcom VideoCore III processor
+  EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture
+  EM_SE_C17        = 139, // Seiko Epson C17 family
+  EM_TI_C6000      = 140, // The Texas Instruments TMS320C6000 DSP family
+  EM_TI_C2000      = 141, // The Texas Instruments TMS320C2000 DSP family
+  EM_TI_C5500      = 142, // The Texas Instruments TMS320C55x DSP family
+  EM_MMDSP_PLUS    = 160, // STMicroelectronics 64bit VLIW Data Signal Processor
+  EM_CYPRESS_M8C   = 161, // Cypress M8C microprocessor
+  EM_R32C          = 162, // Renesas R32C series microprocessors
+  EM_TRIMEDIA      = 163, // NXP Semiconductors TriMedia architecture family
+  EM_HEXAGON       = 164, // Qualcomm Hexagon processor
+  EM_8051          = 165, // Intel 8051 and variants
+  EM_STXP7X        = 166, // STMicroelectronics STxP7x family of configurable
+                          // and extensible RISC processors
+  EM_NDS32         = 167, // Andes Technology compact code size embedded RISC
+                          // processor family
+  EM_ECOG1         = 168, // Cyan Technology eCOG1X family
+  EM_ECOG1X        = 168, // Cyan Technology eCOG1X family
+  EM_MAXQ30        = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers
+  EM_XIMO16        = 170, // New Japan Radio (NJR) 16-bit DSP Processor
+  EM_MANIK         = 171, // M2000 Reconfigurable RISC Microprocessor
+  EM_CRAYNV2       = 172, // Cray Inc. NV2 vector architecture
+  EM_RX            = 173, // Renesas RX family
+  EM_METAG         = 174, // Imagination Technologies META processor
+                          // architecture
+  EM_MCST_ELBRUS   = 175, // MCST Elbrus general purpose hardware architecture
+  EM_ECOG16        = 176, // Cyan Technology eCOG16 family
+  EM_CR16          = 177, // National Semiconductor CompactRISC CR16 16-bit
+                          // microprocessor
+  EM_ETPU          = 178, // Freescale Extended Time Processing Unit
+  EM_SLE9X         = 179, // Infineon Technologies SLE9X core
+  EM_L10M          = 180, // Intel L10M
+  EM_K10M          = 181, // Intel K10M
+  EM_AARCH64       = 183, // ARM AArch64
+  EM_AVR32         = 185, // Atmel Corporation 32-bit microprocessor family
+  EM_STM8          = 186, // STMicroeletronics STM8 8-bit microcontroller
+  EM_TILE64        = 187, // Tilera TILE64 multicore architecture family
+  EM_TILEPRO       = 188, // Tilera TILEPro multicore architecture family
+  EM_CUDA          = 190, // NVIDIA CUDA architecture
+  EM_TILEGX        = 191, // Tilera TILE-Gx multicore architecture family
+  EM_CLOUDSHIELD   = 192, // CloudShield architecture family
+  EM_COREA_1ST     = 193, // KIPO-KAIST Core-A 1st generation processor family
+  EM_COREA_2ND     = 194, // KIPO-KAIST Core-A 2nd generation processor family
+  EM_ARC_COMPACT2  = 195, // Synopsys ARCompact V2
+  EM_OPEN8         = 196, // Open8 8-bit RISC soft processor core
+  EM_RL78          = 197, // Renesas RL78 family
+  EM_VIDEOCORE5    = 198, // Broadcom VideoCore V processor
+  EM_78KOR         = 199, // Renesas 78KOR family
+  EM_56800EX       = 200, // Freescale 56800EX Digital Signal Controller (DSC)
+  EM_BA1           = 201, // Beyond BA1 CPU architecture
+  EM_BA2           = 202, // Beyond BA2 CPU architecture
+  EM_XCORE         = 203, // XMOS xCORE processor family
+  EM_MCHP_PIC      = 204, // Microchip 8-bit PIC(r) family
+  EM_INTEL205      = 205, // Reserved by Intel
+  EM_INTEL206      = 206, // Reserved by Intel
+  EM_INTEL207      = 207, // Reserved by Intel
+  EM_INTEL208      = 208, // Reserved by Intel
+  EM_INTEL209      = 209, // Reserved by Intel
+  EM_KM32          = 210, // KM211 KM32 32-bit processor
+  EM_KMX32         = 211, // KM211 KMX32 32-bit processor
+  EM_KMX16         = 212, // KM211 KMX16 16-bit processor
+  EM_KMX8          = 213, // KM211 KMX8 8-bit processor
+  EM_KVARC         = 214, // KM211 KVARC processor
+  EM_CDP           = 215, // Paneve CDP architecture family
+  EM_COGE          = 216, // Cognitive Smart Memory Processor
+  EM_COOL          = 217, // iCelero CoolEngine
+  EM_NORC          = 218, // Nanoradio Optimized RISC
+  EM_CSR_KALIMBA   = 219, // CSR Kalimba architecture family
+  EM_AMDGPU        = 224, // AMD GPU architecture
+  EM_LANAI         = 244, // Lanai 32-bit processor
+  EM_BPF           = 247, // Linux kernel bpf virtual machine
+
+  // A request has been made to the maintainer of the official registry for
+  // such numbers for an official value for WebAssembly. As soon as one is
+  // allocated, this enum will be updated to use it.
+  EM_WEBASSEMBLY   = 0x4157, // WebAssembly architecture
+};
+
+// Object file classes.
+enum {
+  ELFCLASSNONE = 0,
+  ELFCLASS32 = 1, // 32-bit object file
+  ELFCLASS64 = 2  // 64-bit object file
+};
+
+// Object file byte orderings.
+enum {
+  ELFDATANONE = 0, // Invalid data encoding.
+  ELFDATA2LSB = 1, // Little-endian object file
+  ELFDATA2MSB = 2  // Big-endian object file
+};
+
+// OS ABI identification.
+enum {
+  ELFOSABI_NONE = 0,          // UNIX System V ABI
+  ELFOSABI_HPUX = 1,          // HP-UX operating system
+  ELFOSABI_NETBSD = 2,        // NetBSD
+  ELFOSABI_GNU = 3,           // GNU/Linux
+  ELFOSABI_LINUX = 3,         // Historical alias for ELFOSABI_GNU.
+  ELFOSABI_HURD = 4,          // GNU/Hurd
+  ELFOSABI_SOLARIS = 6,       // Solaris
+  ELFOSABI_AIX = 7,           // AIX
+  ELFOSABI_IRIX = 8,          // IRIX
+  ELFOSABI_FREEBSD = 9,       // FreeBSD
+  ELFOSABI_TRU64 = 10,        // TRU64 UNIX
+  ELFOSABI_MODESTO = 11,      // Novell Modesto
+  ELFOSABI_OPENBSD = 12,      // OpenBSD
+  ELFOSABI_OPENVMS = 13,      // OpenVMS
+  ELFOSABI_NSK = 14,          // Hewlett-Packard Non-Stop Kernel
+  ELFOSABI_AROS = 15,         // AROS
+  ELFOSABI_FENIXOS = 16,      // FenixOS
+  ELFOSABI_CLOUDABI = 17,     // Nuxi CloudABI
+  ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000
+  ELFOSABI_AMDGPU_HSA = 64,   // AMD HSA runtime
+  ELFOSABI_C6000_LINUX = 65,  // Linux TMS320C6000
+  ELFOSABI_ARM = 97,          // ARM
+  ELFOSABI_STANDALONE = 255   // Standalone (embedded) application
+};
+
+#define ELF_RELOC(name, value) name = value,
+
+// X86_64 relocations.
+enum {
+#include "ELFRelocs/x86_64.def"
+};
+
+// i386 relocations.
+enum {
+#include "ELFRelocs/i386.def"
+};
+
+// ELF Relocation types for PPC32
+enum {
+#include "ELFRelocs/PowerPC.def"
+};
+
+// Specific e_flags for PPC64
+enum {
+  // e_flags bits specifying ABI:
+  // 1 for original ABI using function descriptors,
+  // 2 for revised ABI without function descriptors,
+  // 0 for unspecified or not using any features affected by the differences.
+  EF_PPC64_ABI = 3
+};
+
+// Special values for the st_other field in the symbol table entry for PPC64.
+enum {
+  STO_PPC64_LOCAL_BIT = 5,
+  STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT)
+};
+static inline int64_t
+decodePPC64LocalEntryOffset(unsigned Other) {
+  unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
+  return ((1 << Val) >> 2) << 2;
+}
+static inline unsigned
+encodePPC64LocalEntryOffset(int64_t Offset) {
+  unsigned Val = (Offset >= 4 * 4
+                  ? (Offset >= 8 * 4
+                     ? (Offset >= 16 * 4 ? 6 : 5)
+                     : 4)
+                  : (Offset >= 2 * 4
+                     ? 3
+                     : (Offset >= 1 * 4 ? 2 : 0)));
+  return Val << STO_PPC64_LOCAL_BIT;
+}
+
+// ELF Relocation types for PPC64
+enum {
+#include "ELFRelocs/PowerPC64.def"
+};
+
+// ELF Relocation types for AArch64
+enum {
+#include "ELFRelocs/AArch64.def"
+};
+
+// ARM Specific e_flags
+enum : unsigned {
+  EF_ARM_SOFT_FLOAT =     0x00000200U,
+  EF_ARM_VFP_FLOAT =      0x00000400U,
+  EF_ARM_EABI_UNKNOWN =   0x00000000U,
+  EF_ARM_EABI_VER1 =      0x01000000U,
+  EF_ARM_EABI_VER2 =      0x02000000U,
+  EF_ARM_EABI_VER3 =      0x03000000U,
+  EF_ARM_EABI_VER4 =      0x04000000U,
+  EF_ARM_EABI_VER5 =      0x05000000U,
+  EF_ARM_EABIMASK =       0xFF000000U
+};
+
+// ELF Relocation types for ARM
+enum {
+#include "ELFRelocs/ARM.def"
+};
+
+// AVR specific e_flags
+enum : unsigned {
+  EF_AVR_ARCH_AVR1    = 1,
+  EF_AVR_ARCH_AVR2    = 2,
+  EF_AVR_ARCH_AVR25   = 25,
+  EF_AVR_ARCH_AVR3    = 3,
+  EF_AVR_ARCH_AVR31   = 31,
+  EF_AVR_ARCH_AVR35   = 35,
+  EF_AVR_ARCH_AVR4    = 4,
+  EF_AVR_ARCH_AVR5    = 5,
+  EF_AVR_ARCH_AVR51   = 51,
+  EF_AVR_ARCH_AVR6    = 6,
+  EF_AVR_ARCH_AVRTINY = 100,
+  EF_AVR_ARCH_XMEGA1  = 101,
+  EF_AVR_ARCH_XMEGA2  = 102,
+  EF_AVR_ARCH_XMEGA3  = 103,
+  EF_AVR_ARCH_XMEGA4  = 104,
+  EF_AVR_ARCH_XMEGA5  = 105,
+  EF_AVR_ARCH_XMEGA6  = 106,
+  EF_AVR_ARCH_XMEGA7  = 107
+};
+
+// ELF Relocation types for AVR
+enum {
+#include "ELFRelocs/AVR.def"
+};
+
+// Mips Specific e_flags
+enum : unsigned {
+  EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions
+  EF_MIPS_PIC       = 0x00000002, // Position independent code
+  EF_MIPS_CPIC      = 0x00000004, // Call object with Position independent code
+  EF_MIPS_ABI2      = 0x00000020, // File uses N32 ABI
+  EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine
+                                  // in 32-bit mode
+  EF_MIPS_FP64      = 0x00000200, // Code compiled for a 32-bit machine
+                                  // but uses 64-bit FP registers
+  EF_MIPS_NAN2008   = 0x00000400, // Uses IEE 754-2008 NaN encoding
+
+  // ABI flags
+  EF_MIPS_ABI_O32    = 0x00001000, // This file follows the first MIPS 32 bit ABI
+  EF_MIPS_ABI_O64    = 0x00002000, // O32 ABI extended for 64-bit architecture.
+  EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode.
+  EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode.
+  EF_MIPS_ABI        = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant.
+
+  // MIPS machine variant
+  EF_MIPS_MACH_NONE    = 0x00000000, // A standard MIPS implementation.
+  EF_MIPS_MACH_3900    = 0x00810000, // Toshiba R3900
+  EF_MIPS_MACH_4010    = 0x00820000, // LSI R4010
+  EF_MIPS_MACH_4100    = 0x00830000, // NEC VR4100
+  EF_MIPS_MACH_4650    = 0x00850000, // MIPS R4650
+  EF_MIPS_MACH_4120    = 0x00870000, // NEC VR4120
+  EF_MIPS_MACH_4111    = 0x00880000, // NEC VR4111/VR4181
+  EF_MIPS_MACH_SB1     = 0x008a0000, // Broadcom SB-1
+  EF_MIPS_MACH_OCTEON  = 0x008b0000, // Cavium Networks Octeon
+  EF_MIPS_MACH_XLR     = 0x008c0000, // RMI Xlr
+  EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2
+  EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3
+  EF_MIPS_MACH_5400    = 0x00910000, // NEC VR5400
+  EF_MIPS_MACH_5900    = 0x00920000, // MIPS R5900
+  EF_MIPS_MACH_5500    = 0x00980000, // NEC VR5500
+  EF_MIPS_MACH_9000    = 0x00990000, // Unknown
+  EF_MIPS_MACH_LS2E    = 0x00a00000, // ST Microelectronics Loongson 2E
+  EF_MIPS_MACH_LS2F    = 0x00a10000, // ST Microelectronics Loongson 2F
+  EF_MIPS_MACH_LS3A    = 0x00a20000, // Loongson 3A
+  EF_MIPS_MACH         = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask
+
+  // ARCH_ASE
+  EF_MIPS_MICROMIPS = 0x02000000, // microMIPS
+  EF_MIPS_ARCH_ASE_M16 =
+                      0x04000000, // Has Mips-16 ISA extensions
+  EF_MIPS_ARCH_ASE_MDMX =
+                      0x08000000, // Has MDMX multimedia extensions
+  EF_MIPS_ARCH_ASE  = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags
+
+  // ARCH
+  EF_MIPS_ARCH_1    = 0x00000000, // MIPS1 instruction set
+  EF_MIPS_ARCH_2    = 0x10000000, // MIPS2 instruction set
+  EF_MIPS_ARCH_3    = 0x20000000, // MIPS3 instruction set
+  EF_MIPS_ARCH_4    = 0x30000000, // MIPS4 instruction set
+  EF_MIPS_ARCH_5    = 0x40000000, // MIPS5 instruction set
+  EF_MIPS_ARCH_32   = 0x50000000, // MIPS32 instruction set per linux not elf.h
+  EF_MIPS_ARCH_64   = 0x60000000, // MIPS64 instruction set per linux not elf.h
+  EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5
+  EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5
+  EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6
+  EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6
+  EF_MIPS_ARCH      = 0xf0000000  // Mask for applying EF_MIPS_ARCH_ variant
+};
+
+// ELF Relocation types for Mips
+enum {
+#include "ELFRelocs/Mips.def"
+};
+
+// Special values for the st_other field in the symbol table entry for MIPS.
+enum {
+  STO_MIPS_OPTIONAL        = 0x04,  // Symbol whose definition is optional
+  STO_MIPS_PLT             = 0x08,  // PLT entry related dynamic table record
+  STO_MIPS_PIC             = 0x20,  // PIC func in an object mixes PIC/non-PIC
+  STO_MIPS_MICROMIPS       = 0x80,  // MIPS Specific ISA for MicroMips
+  STO_MIPS_MIPS16          = 0xf0   // MIPS Specific ISA for Mips16
+};
+
+// .MIPS.options section descriptor kinds
+enum {
+  ODK_NULL       = 0,   // Undefined
+  ODK_REGINFO    = 1,   // Register usage information
+  ODK_EXCEPTIONS = 2,   // Exception processing options
+  ODK_PAD        = 3,   // Section padding options
+  ODK_HWPATCH    = 4,   // Hardware patches applied
+  ODK_FILL       = 5,   // Linker fill value
+  ODK_TAGS       = 6,   // Space for tool identification
+  ODK_HWAND      = 7,   // Hardware AND patches applied
+  ODK_HWOR       = 8,   // Hardware OR patches applied
+  ODK_GP_GROUP   = 9,   // GP group to use for text/data sections
+  ODK_IDENT      = 10,  // ID information
+  ODK_PAGESIZE   = 11   // Page size information
+};
+
+// Hexagon-specific e_flags
+enum {
+  // Object processor version flags, bits[11:0]
+  EF_HEXAGON_MACH_V2      = 0x00000001,   // Hexagon V2
+  EF_HEXAGON_MACH_V3      = 0x00000002,   // Hexagon V3
+  EF_HEXAGON_MACH_V4      = 0x00000003,   // Hexagon V4
+  EF_HEXAGON_MACH_V5      = 0x00000004,   // Hexagon V5
+  EF_HEXAGON_MACH_V55     = 0x00000005,   // Hexagon V55
+  EF_HEXAGON_MACH_V60     = 0x00000060,   // Hexagon V60
+
+  // Highest ISA version flags
+  EF_HEXAGON_ISA_MACH     = 0x00000000,   // Same as specified in bits[11:0]
+                                          // of e_flags
+  EF_HEXAGON_ISA_V2       = 0x00000010,   // Hexagon V2 ISA
+  EF_HEXAGON_ISA_V3       = 0x00000020,   // Hexagon V3 ISA
+  EF_HEXAGON_ISA_V4       = 0x00000030,   // Hexagon V4 ISA
+  EF_HEXAGON_ISA_V5       = 0x00000040,   // Hexagon V5 ISA
+  EF_HEXAGON_ISA_V55      = 0x00000050,   // Hexagon V55 ISA
+  EF_HEXAGON_ISA_V60      = 0x00000060,   // Hexagon V60 ISA
+};
+
+// Hexagon-specific section indexes for common small data
+enum {
+  SHN_HEXAGON_SCOMMON     = 0xff00,       // Other access sizes
+  SHN_HEXAGON_SCOMMON_1   = 0xff01,       // Byte-sized access
+  SHN_HEXAGON_SCOMMON_2   = 0xff02,       // Half-word-sized access
+  SHN_HEXAGON_SCOMMON_4   = 0xff03,       // Word-sized access
+  SHN_HEXAGON_SCOMMON_8   = 0xff04        // Double-word-size access
+};
+
+// ELF Relocation types for Hexagon
+enum {
+#include "ELFRelocs/Hexagon.def"
+};
+
+// ELF Relocation type for Lanai.
+enum {
+#include "ELFRelocs/Lanai.def"
+};
+
+// ELF Relocation types for S390/zSeries
+enum {
+#include "ELFRelocs/SystemZ.def"
+};
+
+// ELF Relocation type for Sparc.
+enum {
+#include "ELFRelocs/Sparc.def"
+};
+
+// ELF Relocation types for WebAssembly
+enum {
+#include "ELFRelocs/WebAssembly.def"
+};
+
+// ELF Relocation types for AMDGPU
+enum {
+#include "ELFRelocs/AMDGPU.def"
+};
+
+// ELF Relocation types for BPF
+enum {
+#include "ELFRelocs/BPF.def"
+};
+
+#undef ELF_RELOC
+
+// Section header.
+struct Elf32_Shdr {
+  Elf32_Word sh_name;      // Section name (index into string table)
+  Elf32_Word sh_type;      // Section type (SHT_*)
+  Elf32_Word sh_flags;     // Section flags (SHF_*)
+  Elf32_Addr sh_addr;      // Address where section is to be loaded
+  Elf32_Off  sh_offset;    // File offset of section data, in bytes
+  Elf32_Word sh_size;      // Size of section, in bytes
+  Elf32_Word sh_link;      // Section type-specific header table index link
+  Elf32_Word sh_info;      // Section type-specific extra information
+  Elf32_Word sh_addralign; // Section address alignment
+  Elf32_Word sh_entsize;   // Size of records contained within the section
+};
+
+// Section header for ELF64 - same fields as ELF32, different types.
+struct Elf64_Shdr {
+  Elf64_Word  sh_name;
+  Elf64_Word  sh_type;
+  Elf64_Xword sh_flags;
+  Elf64_Addr  sh_addr;
+  Elf64_Off   sh_offset;
+  Elf64_Xword sh_size;
+  Elf64_Word  sh_link;
+  Elf64_Word  sh_info;
+  Elf64_Xword sh_addralign;
+  Elf64_Xword sh_entsize;
+};
+
+// Special section indices.
+enum {
+  SHN_UNDEF     = 0,      // Undefined, missing, irrelevant, or meaningless
+  SHN_LORESERVE = 0xff00, // Lowest reserved index
+  SHN_LOPROC    = 0xff00, // Lowest processor-specific index
+  SHN_HIPROC    = 0xff1f, // Highest processor-specific index
+  SHN_LOOS      = 0xff20, // Lowest operating system-specific index
+  SHN_HIOS      = 0xff3f, // Highest operating system-specific index
+  SHN_ABS       = 0xfff1, // Symbol has absolute value; does not need relocation
+  SHN_COMMON    = 0xfff2, // FORTRAN COMMON or C external global variables
+  SHN_XINDEX    = 0xffff, // Mark that the index is >= SHN_LORESERVE
+  SHN_HIRESERVE = 0xffff  // Highest reserved index
+};
+
+// Section types.
+enum : unsigned {
+  SHT_NULL          = 0,  // No associated section (inactive entry).
+  SHT_PROGBITS      = 1,  // Program-defined contents.
+  SHT_SYMTAB        = 2,  // Symbol table.
+  SHT_STRTAB        = 3,  // String table.
+  SHT_RELA          = 4,  // Relocation entries; explicit addends.
+  SHT_HASH          = 5,  // Symbol hash table.
+  SHT_DYNAMIC       = 6,  // Information for dynamic linking.
+  SHT_NOTE          = 7,  // Information about the file.
+  SHT_NOBITS        = 8,  // Data occupies no space in the file.
+  SHT_REL           = 9,  // Relocation entries; no explicit addends.
+  SHT_SHLIB         = 10, // Reserved.
+  SHT_DYNSYM        = 11, // Symbol table.
+  SHT_INIT_ARRAY    = 14, // Pointers to initialization functions.
+  SHT_FINI_ARRAY    = 15, // Pointers to termination functions.
+  SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions.
+  SHT_GROUP         = 17, // Section group.
+  SHT_SYMTAB_SHNDX  = 18, // Indices for SHN_XINDEX entries.
+  SHT_LOOS          = 0x60000000, // Lowest operating system-specific type.
+  SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes.
+  SHT_GNU_HASH      = 0x6ffffff6, // GNU-style hash table.
+  SHT_GNU_verdef    = 0x6ffffffd, // GNU version definitions.
+  SHT_GNU_verneed   = 0x6ffffffe, // GNU version references.
+  SHT_GNU_versym    = 0x6fffffff, // GNU symbol versions table.
+  SHT_HIOS          = 0x6fffffff, // Highest operating system-specific type.
+  SHT_LOPROC        = 0x70000000, // Lowest processor arch-specific type.
+  // Fixme: All this is duplicated in MCSectionELF. Why??
+  // Exception Index table
+  SHT_ARM_EXIDX           = 0x70000001U,
+  // BPABI DLL dynamic linking pre-emption map
+  SHT_ARM_PREEMPTMAP      = 0x70000002U,
+  //  Object file compatibility attributes
+  SHT_ARM_ATTRIBUTES      = 0x70000003U,
+  SHT_ARM_DEBUGOVERLAY    = 0x70000004U,
+  SHT_ARM_OVERLAYSECTION  = 0x70000005U,
+  SHT_HEX_ORDERED         = 0x70000000, // Link editor is to sort the entries in
+                                        // this section based on their sizes
+  SHT_X86_64_UNWIND       = 0x70000001, // Unwind information
+
+  SHT_MIPS_REGINFO        = 0x70000006, // Register usage information
+  SHT_MIPS_OPTIONS        = 0x7000000d, // General options
+  SHT_MIPS_ABIFLAGS       = 0x7000002a, // ABI information.
+
+  SHT_HIPROC        = 0x7fffffff, // Highest processor arch-specific type.
+  SHT_LOUSER        = 0x80000000, // Lowest type reserved for applications.
+  SHT_HIUSER        = 0xffffffff  // Highest type reserved for applications.
+};
+
+// Section flags.
+enum : unsigned {
+  // Section data should be writable during execution.
+  SHF_WRITE = 0x1,
+
+  // Section occupies memory during program execution.
+  SHF_ALLOC = 0x2,
+
+  // Section contains executable machine instructions.
+  SHF_EXECINSTR = 0x4,
+
+  // The data in this section may be merged.
+  SHF_MERGE = 0x10,
+
+  // The data in this section is null-terminated strings.
+  SHF_STRINGS = 0x20,
+
+  // A field in this section holds a section header table index.
+  SHF_INFO_LINK = 0x40U,
+
+  // Adds special ordering requirements for link editors.
+  SHF_LINK_ORDER = 0x80U,
+
+  // This section requires special OS-specific processing to avoid incorrect
+  // behavior.
+  SHF_OS_NONCONFORMING = 0x100U,
+
+  // This section is a member of a section group.
+  SHF_GROUP = 0x200U,
+
+  // This section holds Thread-Local Storage.
+  SHF_TLS = 0x400U,
+
+  // Identifies a section containing compressed data.
+  SHF_COMPRESSED = 0x800U,
+
+  // This section is excluded from the final executable or shared library.
+  SHF_EXCLUDE = 0x80000000U,
+
+  // Start of target-specific flags.
+
+  /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped
+  /// together by the linker to form the constant pool and the cp register is
+  /// set to the start of the constant pool by the boot code.
+  XCORE_SHF_CP_SECTION = 0x800U,
+
+  /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped
+  /// together by the linker to form the data section and the dp register is
+  /// set to the start of the section by the boot code.
+  XCORE_SHF_DP_SECTION = 0x1000U,
+
+  SHF_MASKOS   = 0x0ff00000,
+
+  // Bits indicating processor-specific flags.
+  SHF_MASKPROC = 0xf0000000,
+
+  // If an object file section does not have this flag set, then it may not hold
+  // more than 2GB and can be freely referred to in objects using smaller code
+  // models. Otherwise, only objects using larger code models can refer to them.
+  // For example, a medium code model object can refer to data in a section that
+  // sets this flag besides being able to refer to data in a section that does
+  // not set it; likewise, a small code model object can refer only to code in a
+  // section that does not set this flag.
+  SHF_X86_64_LARGE = 0x10000000,
+
+  // All sections with the GPREL flag are grouped into a global data area
+  // for faster accesses
+  SHF_HEX_GPREL = 0x10000000,
+
+  // Section contains text/data which may be replicated in other sections.
+  // Linker must retain only one copy.
+  SHF_MIPS_NODUPES = 0x01000000,
+
+  // Linker must generate implicit hidden weak names.
+  SHF_MIPS_NAMES   = 0x02000000,
+
+  // Section data local to process.
+  SHF_MIPS_LOCAL   = 0x04000000,
+
+  // Do not strip this section.
+  SHF_MIPS_NOSTRIP = 0x08000000,
+
+  // Section must be part of global data area.
+  SHF_MIPS_GPREL   = 0x10000000,
+
+  // This section should be merged.
+  SHF_MIPS_MERGE   = 0x20000000,
+
+  // Address size to be inferred from section entry size.
+  SHF_MIPS_ADDR    = 0x40000000,
+
+  // Section data is string data by default.
+  SHF_MIPS_STRING  = 0x80000000,
+
+  SHF_AMDGPU_HSA_GLOBAL   = 0x00100000,
+  SHF_AMDGPU_HSA_READONLY = 0x00200000,
+  SHF_AMDGPU_HSA_CODE     = 0x00400000,
+  SHF_AMDGPU_HSA_AGENT    = 0x00800000
+};
+
+// Section Group Flags
+enum : unsigned {
+  GRP_COMDAT = 0x1,
+  GRP_MASKOS = 0x0ff00000,
+  GRP_MASKPROC = 0xf0000000
+};
+
+// Symbol table entries for ELF32.
+struct Elf32_Sym {
+  Elf32_Word    st_name;  // Symbol name (index into string table)
+  Elf32_Addr    st_value; // Value or address associated with the symbol
+  Elf32_Word    st_size;  // Size of the symbol
+  unsigned char st_info;  // Symbol's type and binding attributes
+  unsigned char st_other; // Must be zero; reserved
+  Elf32_Half    st_shndx; // Which section (header table index) it's defined in
+
+  // These accessors and mutators correspond to the ELF32_ST_BIND,
+  // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
+  unsigned char getBinding() const { return st_info >> 4; }
+  unsigned char getType() const { return st_info & 0x0f; }
+  void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
+  void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
+  void setBindingAndType(unsigned char b, unsigned char t) {
+    st_info = (b << 4) + (t & 0x0f);
+  }
+};
+
+// Symbol table entries for ELF64.
+struct Elf64_Sym {
+  Elf64_Word      st_name;  // Symbol name (index into string table)
+  unsigned char   st_info;  // Symbol's type and binding attributes
+  unsigned char   st_other; // Must be zero; reserved
+  Elf64_Half      st_shndx; // Which section (header tbl index) it's defined in
+  Elf64_Addr      st_value; // Value or address associated with the symbol
+  Elf64_Xword     st_size;  // Size of the symbol
+
+  // These accessors and mutators are identical to those defined for ELF32
+  // symbol table entries.
+  unsigned char getBinding() const { return st_info >> 4; }
+  unsigned char getType() const { return st_info & 0x0f; }
+  void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
+  void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
+  void setBindingAndType(unsigned char b, unsigned char t) {
+    st_info = (b << 4) + (t & 0x0f);
+  }
+};
+
+// The size (in bytes) of symbol table entries.
+enum {
+  SYMENTRY_SIZE32 = 16, // 32-bit symbol entry size
+  SYMENTRY_SIZE64 = 24  // 64-bit symbol entry size.
+};
+
+// Symbol bindings.
+enum {
+  STB_LOCAL = 0,   // Local symbol, not visible outside obj file containing def
+  STB_GLOBAL = 1,  // Global symbol, visible to all object files being combined
+  STB_WEAK = 2,    // Weak symbol, like global but lower-precedence
+  STB_GNU_UNIQUE = 10,
+  STB_LOOS   = 10, // Lowest operating system-specific binding type
+  STB_HIOS   = 12, // Highest operating system-specific binding type
+  STB_LOPROC = 13, // Lowest processor-specific binding type
+  STB_HIPROC = 15  // Highest processor-specific binding type
+};
+
+// Symbol types.
+enum {
+  STT_NOTYPE  = 0,   // Symbol's type is not specified
+  STT_OBJECT  = 1,   // Symbol is a data object (variable, array, etc.)
+  STT_FUNC    = 2,   // Symbol is executable code (function, etc.)
+  STT_SECTION = 3,   // Symbol refers to a section
+  STT_FILE    = 4,   // Local, absolute symbol that refers to a file
+  STT_COMMON  = 5,   // An uninitialized common block
+  STT_TLS     = 6,   // Thread local data object
+  STT_GNU_IFUNC = 10, // GNU indirect function
+  STT_LOOS    = 10,  // Lowest operating system-specific symbol type
+  STT_HIOS    = 12,  // Highest operating system-specific symbol type
+  STT_LOPROC  = 13,  // Lowest processor-specific symbol type
+  STT_HIPROC  = 15,  // Highest processor-specific symbol type
+
+  // AMDGPU symbol types
+  STT_AMDGPU_HSA_KERNEL            = 10,
+  STT_AMDGPU_HSA_INDIRECT_FUNCTION = 11,
+  STT_AMDGPU_HSA_METADATA          = 12
+};
+
+enum {
+  STV_DEFAULT   = 0,  // Visibility is specified by binding type
+  STV_INTERNAL  = 1,  // Defined by processor supplements
+  STV_HIDDEN    = 2,  // Not visible to other components
+  STV_PROTECTED = 3   // Visible in other components but not preemptable
+};
+
+// Symbol number.
+enum {
+  STN_UNDEF = 0
+};
+
+// Special relocation symbols used in the MIPS64 ELF relocation entries
+enum {
+  RSS_UNDEF = 0, // None
+  RSS_GP = 1,    // Value of gp
+  RSS_GP0 = 2,   // Value of gp used to create object being relocated
+  RSS_LOC = 3    // Address of location being relocated
+};
+
+// Relocation entry, without explicit addend.
+struct Elf32_Rel {
+  Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr)
+  Elf32_Word r_info;   // Symbol table index and type of relocation to apply
+
+  // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
+  // and ELF32_R_INFO macros defined in the ELF specification:
+  Elf32_Word getSymbol() const { return (r_info >> 8); }
+  unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
+  void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); }
+  void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
+  void setSymbolAndType(Elf32_Word s, unsigned char t) {
+    r_info = (s << 8) + t;
+  }
+};
+
+// Relocation entry with explicit addend.
+struct Elf32_Rela {
+  Elf32_Addr  r_offset; // Location (file byte offset, or program virtual addr)
+  Elf32_Word  r_info;   // Symbol table index and type of relocation to apply
+  Elf32_Sword r_addend; // Compute value for relocatable field by adding this
+
+  // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
+  // and ELF32_R_INFO macros defined in the ELF specification:
+  Elf32_Word getSymbol() const { return (r_info >> 8); }
+  unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
+  void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); }
+  void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
+  void setSymbolAndType(Elf32_Word s, unsigned char t) {
+    r_info = (s << 8) + t;
+  }
+};
+
+// Relocation entry, without explicit addend.
+struct Elf64_Rel {
+  Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr).
+  Elf64_Xword r_info;   // Symbol table index and type of relocation to apply.
+
+  // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
+  // and ELF64_R_INFO macros defined in the ELF specification:
+  Elf64_Word getSymbol() const { return (r_info >> 32); }
+  Elf64_Word getType() const {
+    return (Elf64_Word) (r_info & 0xffffffffL);
+  }
+  void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); }
+  void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); }
+  void setSymbolAndType(Elf64_Word s, Elf64_Word t) {
+    r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL);
+  }
+};
+
+// Relocation entry with explicit addend.
+struct Elf64_Rela {
+  Elf64_Addr  r_offset; // Location (file byte offset, or program virtual addr).
+  Elf64_Xword  r_info;   // Symbol table index and type of relocation to apply.
+  Elf64_Sxword r_addend; // Compute value for relocatable field by adding this.
+
+  // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
+  // and ELF64_R_INFO macros defined in the ELF specification:
+  Elf64_Word getSymbol() const { return (r_info >> 32); }
+  Elf64_Word getType() const {
+    return (Elf64_Word) (r_info & 0xffffffffL);
+  }
+  void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); }
+  void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); }
+  void setSymbolAndType(Elf64_Word s, Elf64_Word t) {
+    r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL);
+  }
+};
+
+// Program header for ELF32.
+struct Elf32_Phdr {
+  Elf32_Word p_type;   // Type of segment
+  Elf32_Off  p_offset; // File offset where segment is located, in bytes
+  Elf32_Addr p_vaddr;  // Virtual address of beginning of segment
+  Elf32_Addr p_paddr;  // Physical address of beginning of segment (OS-specific)
+  Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero)
+  Elf32_Word p_memsz;  // Num. of bytes in mem image of segment (may be zero)
+  Elf32_Word p_flags;  // Segment flags
+  Elf32_Word p_align;  // Segment alignment constraint
+};
+
+// Program header for ELF64.
+struct Elf64_Phdr {
+  Elf64_Word   p_type;   // Type of segment
+  Elf64_Word   p_flags;  // Segment flags
+  Elf64_Off    p_offset; // File offset where segment is located, in bytes
+  Elf64_Addr   p_vaddr;  // Virtual address of beginning of segment
+  Elf64_Addr   p_paddr;  // Physical addr of beginning of segment (OS-specific)
+  Elf64_Xword  p_filesz; // Num. of bytes in file image of segment (may be zero)
+  Elf64_Xword  p_memsz;  // Num. of bytes in mem image of segment (may be zero)
+  Elf64_Xword  p_align;  // Segment alignment constraint
+};
+
+// Segment types.
+enum {
+  PT_NULL    = 0, // Unused segment.
+  PT_LOAD    = 1, // Loadable segment.
+  PT_DYNAMIC = 2, // Dynamic linking information.
+  PT_INTERP  = 3, // Interpreter pathname.
+  PT_NOTE    = 4, // Auxiliary information.
+  PT_SHLIB   = 5, // Reserved.
+  PT_PHDR    = 6, // The program header table itself.
+  PT_TLS     = 7, // The thread-local storage template.
+  PT_LOOS    = 0x60000000, // Lowest operating system-specific pt entry type.
+  PT_HIOS    = 0x6fffffff, // Highest operating system-specific pt entry type.
+  PT_LOPROC  = 0x70000000, // Lowest processor-specific program hdr entry type.
+  PT_HIPROC  = 0x7fffffff, // Highest processor-specific program hdr entry type.
+
+  // x86-64 program header types.
+  // These all contain stack unwind tables.
+  PT_GNU_EH_FRAME  = 0x6474e550,
+  PT_SUNW_EH_FRAME = 0x6474e550,
+  PT_SUNW_UNWIND   = 0x6464e550,
+
+  PT_GNU_STACK  = 0x6474e551, // Indicates stack executability.
+  PT_GNU_RELRO  = 0x6474e552, // Read-only after relocation.
+
+  // ARM program header types.
+  PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info
+  // These all contain stack unwind tables.
+  PT_ARM_EXIDX   = 0x70000001,
+  PT_ARM_UNWIND  = 0x70000001,
+
+  // MIPS program header types.
+  PT_MIPS_REGINFO  = 0x70000000,  // Register usage information.
+  PT_MIPS_RTPROC   = 0x70000001,  // Runtime procedure table.
+  PT_MIPS_OPTIONS  = 0x70000002,  // Options segment.
+  PT_MIPS_ABIFLAGS = 0x70000003,  // Abiflags segment.
+
+  // AMDGPU program header types.
+  PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM = 0x60000000,
+  PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT   = 0x60000001,
+  PT_AMDGPU_HSA_LOAD_READONLY_AGENT = 0x60000002,
+  PT_AMDGPU_HSA_LOAD_CODE_AGENT     = 0x60000003,
+
+  // WebAssembly program header types.
+  PT_WEBASSEMBLY_FUNCTIONS = PT_LOPROC + 0, // Function definitions.
+};
+
+// Segment flag bits.
+enum : unsigned {
+  PF_X        = 1,         // Execute
+  PF_W        = 2,         // Write
+  PF_R        = 4,         // Read
+  PF_MASKOS   = 0x0ff00000,// Bits for operating system-specific semantics.
+  PF_MASKPROC = 0xf0000000 // Bits for processor-specific semantics.
+};
+
+// Dynamic table entry for ELF32.
+struct Elf32_Dyn
+{
+  Elf32_Sword d_tag;            // Type of dynamic table entry.
+  union
+  {
+      Elf32_Word d_val;         // Integer value of entry.
+      Elf32_Addr d_ptr;         // Pointer value of entry.
+  } d_un;
+};
+
+// Dynamic table entry for ELF64.
+struct Elf64_Dyn
+{
+  Elf64_Sxword d_tag;           // Type of dynamic table entry.
+  union
+  {
+      Elf64_Xword d_val;        // Integer value of entry.
+      Elf64_Addr  d_ptr;        // Pointer value of entry.
+  } d_un;
+};
+
+// Dynamic table entry tags.
+enum {
+  DT_NULL         = 0,        // Marks end of dynamic array.
+  DT_NEEDED       = 1,        // String table offset of needed library.
+  DT_PLTRELSZ     = 2,        // Size of relocation entries in PLT.
+  DT_PLTGOT       = 3,        // Address associated with linkage table.
+  DT_HASH         = 4,        // Address of symbolic hash table.
+  DT_STRTAB       = 5,        // Address of dynamic string table.
+  DT_SYMTAB       = 6,        // Address of dynamic symbol table.
+  DT_RELA         = 7,        // Address of relocation table (Rela entries).
+  DT_RELASZ       = 8,        // Size of Rela relocation table.
+  DT_RELAENT      = 9,        // Size of a Rela relocation entry.
+  DT_STRSZ        = 10,       // Total size of the string table.
+  DT_SYMENT       = 11,       // Size of a symbol table entry.
+  DT_INIT         = 12,       // Address of initialization function.
+  DT_FINI         = 13,       // Address of termination function.
+  DT_SONAME       = 14,       // String table offset of a shared objects name.
+  DT_RPATH        = 15,       // String table offset of library search path.
+  DT_SYMBOLIC     = 16,       // Changes symbol resolution algorithm.
+  DT_REL          = 17,       // Address of relocation table (Rel entries).
+  DT_RELSZ        = 18,       // Size of Rel relocation table.
+  DT_RELENT       = 19,       // Size of a Rel relocation entry.
+  DT_PLTREL       = 20,       // Type of relocation entry used for linking.
+  DT_DEBUG        = 21,       // Reserved for debugger.
+  DT_TEXTREL      = 22,       // Relocations exist for non-writable segments.
+  DT_JMPREL       = 23,       // Address of relocations associated with PLT.
+  DT_BIND_NOW     = 24,       // Process all relocations before execution.
+  DT_INIT_ARRAY   = 25,       // Pointer to array of initialization functions.
+  DT_FINI_ARRAY   = 26,       // Pointer to array of termination functions.
+  DT_INIT_ARRAYSZ = 27,       // Size of DT_INIT_ARRAY.
+  DT_FINI_ARRAYSZ = 28,       // Size of DT_FINI_ARRAY.
+  DT_RUNPATH      = 29,       // String table offset of lib search path.
+  DT_FLAGS        = 30,       // Flags.
+  DT_ENCODING     = 32,       // Values from here to DT_LOOS follow the rules
+                              // for the interpretation of the d_un union.
+
+  DT_PREINIT_ARRAY = 32,      // Pointer to array of preinit functions.
+  DT_PREINIT_ARRAYSZ = 33,    // Size of the DT_PREINIT_ARRAY array.
+
+  DT_LOOS         = 0x60000000, // Start of environment specific tags.
+  DT_HIOS         = 0x6FFFFFFF, // End of environment specific tags.
+  DT_LOPROC       = 0x70000000, // Start of processor specific tags.
+  DT_HIPROC       = 0x7FFFFFFF, // End of processor specific tags.
+
+  DT_GNU_HASH     = 0x6FFFFEF5, // Reference to the GNU hash table.
+  DT_TLSDESC_PLT  = 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls.
+  DT_TLSDESC_GOT  = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor resolver PLT entry.
+  DT_RELACOUNT    = 0x6FFFFFF9, // ELF32_Rela count.
+  DT_RELCOUNT     = 0x6FFFFFFA, // ELF32_Rel count.
+
+  DT_FLAGS_1      = 0X6FFFFFFB, // Flags_1.
+  DT_VERSYM       = 0x6FFFFFF0, // The address of .gnu.version section.
+  DT_VERDEF       = 0X6FFFFFFC, // The address of the version definition table.
+  DT_VERDEFNUM    = 0X6FFFFFFD, // The number of entries in DT_VERDEF.
+  DT_VERNEED      = 0X6FFFFFFE, // The address of the version Dependency table.
+  DT_VERNEEDNUM   = 0X6FFFFFFF, // The number of entries in DT_VERNEED.
+
+  // Mips specific dynamic table entry tags.
+  DT_MIPS_RLD_VERSION   = 0x70000001, // 32 bit version number for runtime
+                                      // linker interface.
+  DT_MIPS_TIME_STAMP    = 0x70000002, // Time stamp.
+  DT_MIPS_ICHECKSUM     = 0x70000003, // Checksum of external strings
+                                      // and common sizes.
+  DT_MIPS_IVERSION      = 0x70000004, // Index of version string
+                                      // in string table.
+  DT_MIPS_FLAGS         = 0x70000005, // 32 bits of flags.
+  DT_MIPS_BASE_ADDRESS  = 0x70000006, // Base address of the segment.
+  DT_MIPS_MSYM          = 0x70000007, // Address of .msym section.
+  DT_MIPS_CONFLICT      = 0x70000008, // Address of .conflict section.
+  DT_MIPS_LIBLIST       = 0x70000009, // Address of .liblist section.
+  DT_MIPS_LOCAL_GOTNO   = 0x7000000a, // Number of local global offset
+                                      // table entries.
+  DT_MIPS_CONFLICTNO    = 0x7000000b, // Number of entries
+                                      // in the .conflict section.
+  DT_MIPS_LIBLISTNO     = 0x70000010, // Number of entries
+                                      // in the .liblist section.
+  DT_MIPS_SYMTABNO      = 0x70000011, // Number of entries
+                                      // in the .dynsym section.
+  DT_MIPS_UNREFEXTNO    = 0x70000012, // Index of first external dynamic symbol
+                                      // not referenced locally.
+  DT_MIPS_GOTSYM        = 0x70000013, // Index of first dynamic symbol
+                                      // in global offset table.
+  DT_MIPS_HIPAGENO      = 0x70000014, // Number of page table entries
+                                      // in global offset table.
+  DT_MIPS_RLD_MAP       = 0x70000016, // Address of run time loader map,
+                                      // used for debugging.
+  DT_MIPS_DELTA_CLASS       = 0x70000017, // Delta C++ class definition.
+  DT_MIPS_DELTA_CLASS_NO    = 0x70000018, // Number of entries
+                                          // in DT_MIPS_DELTA_CLASS.
+  DT_MIPS_DELTA_INSTANCE    = 0x70000019, // Delta C++ class instances.
+  DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries
+                                          // in DT_MIPS_DELTA_INSTANCE.
+  DT_MIPS_DELTA_RELOC       = 0x7000001B, // Delta relocations.
+  DT_MIPS_DELTA_RELOC_NO    = 0x7000001C, // Number of entries
+                                          // in DT_MIPS_DELTA_RELOC.
+  DT_MIPS_DELTA_SYM         = 0x7000001D, // Delta symbols that Delta
+                                          // relocations refer to.
+  DT_MIPS_DELTA_SYM_NO      = 0x7000001E, // Number of entries
+                                          // in DT_MIPS_DELTA_SYM.
+  DT_MIPS_DELTA_CLASSSYM    = 0x70000020, // Delta symbols that hold
+                                          // class declarations.
+  DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries
+                                          // in DT_MIPS_DELTA_CLASSSYM.
+  DT_MIPS_CXX_FLAGS         = 0x70000022, // Flags indicating information
+                                          // about C++ flavor.
+  DT_MIPS_PIXIE_INIT        = 0x70000023, // Pixie information.
+  DT_MIPS_SYMBOL_LIB        = 0x70000024, // Address of .MIPS.symlib
+  DT_MIPS_LOCALPAGE_GOTIDX  = 0x70000025, // The GOT index of the first PTE
+                                          // for a segment
+  DT_MIPS_LOCAL_GOTIDX      = 0x70000026, // The GOT index of the first PTE
+                                          // for a local symbol
+  DT_MIPS_HIDDEN_GOTIDX     = 0x70000027, // The GOT index of the first PTE
+                                          // for a hidden symbol
+  DT_MIPS_PROTECTED_GOTIDX  = 0x70000028, // The GOT index of the first PTE
+                                          // for a protected symbol
+  DT_MIPS_OPTIONS           = 0x70000029, // Address of `.MIPS.options'.
+  DT_MIPS_INTERFACE         = 0x7000002A, // Address of `.interface'.
+  DT_MIPS_DYNSTR_ALIGN      = 0x7000002B, // Unknown.
+  DT_MIPS_INTERFACE_SIZE    = 0x7000002C, // Size of the .interface section.
+  DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve
+                                              // function stored in the GOT.
+  DT_MIPS_PERF_SUFFIX       = 0x7000002E, // Default suffix of DSO to be added
+                                          // by rld on dlopen() calls.
+  DT_MIPS_COMPACT_SIZE      = 0x7000002F, // Size of compact relocation
+                                          // section (O32).
+  DT_MIPS_GP_VALUE          = 0x70000030, // GP value for auxiliary GOTs.
+  DT_MIPS_AUX_DYNAMIC       = 0x70000031, // Address of auxiliary .dynamic.
+  DT_MIPS_PLTGOT            = 0x70000032, // Address of the base of the PLTGOT.
+  DT_MIPS_RWPLT             = 0x70000034, // Points to the base
+                                          // of a writable PLT.
+  DT_MIPS_RLD_MAP_REL       = 0x70000035, // Relative offset of run time loader
+                                          // map, used for debugging.
+
+  // Sun machine-independent extensions.
+  DT_AUXILIARY              = 0x7FFFFFFD, // Shared object to load before self
+  DT_FILTER                 = 0x7FFFFFFF  // Shared object to get values from
+};
+
+// DT_FLAGS values.
+enum {
+  DF_ORIGIN     = 0x01, // The object may reference $ORIGIN.
+  DF_SYMBOLIC   = 0x02, // Search the shared lib before searching the exe.
+  DF_TEXTREL    = 0x04, // Relocations may modify a non-writable segment.
+  DF_BIND_NOW   = 0x08, // Process all relocations on load.
+  DF_STATIC_TLS = 0x10  // Reject attempts to load dynamically.
+};
+
+// State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry.
+enum {
+  DF_1_NOW        = 0x00000001, // Set RTLD_NOW for this object.
+  DF_1_GLOBAL     = 0x00000002, // Set RTLD_GLOBAL for this object.
+  DF_1_GROUP      = 0x00000004, // Set RTLD_GROUP for this object.
+  DF_1_NODELETE   = 0x00000008, // Set RTLD_NODELETE for this object.
+  DF_1_LOADFLTR   = 0x00000010, // Trigger filtee loading at runtime.
+  DF_1_INITFIRST  = 0x00000020, // Set RTLD_INITFIRST for this object.
+  DF_1_NOOPEN     = 0x00000040, // Set RTLD_NOOPEN for this object.
+  DF_1_ORIGIN     = 0x00000080, // $ORIGIN must be handled.
+  DF_1_DIRECT     = 0x00000100, // Direct binding enabled.
+  DF_1_TRANS      = 0x00000200,
+  DF_1_INTERPOSE  = 0x00000400, // Object is used to interpose.
+  DF_1_NODEFLIB   = 0x00000800, // Ignore default lib search path.
+  DF_1_NODUMP     = 0x00001000, // Object can't be dldump'ed.
+  DF_1_CONFALT    = 0x00002000, // Configuration alternative created.
+  DF_1_ENDFILTEE  = 0x00004000, // Filtee terminates filters search.
+  DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time.
+  DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time.
+  DF_1_NODIRECT   = 0x00020000, // Object has no-direct binding.
+  DF_1_IGNMULDEF  = 0x00040000,
+  DF_1_NOKSYMS    = 0x00080000,
+  DF_1_NOHDR      = 0x00100000,
+  DF_1_EDITED     = 0x00200000, // Object is modified after built.
+  DF_1_NORELOC    = 0x00400000,
+  DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers.
+  DF_1_GLOBAUDIT  = 0x01000000, // Global auditing required.
+  DF_1_SINGLETON  = 0x02000000  // Singleton symbols are used.
+};
+
+// DT_MIPS_FLAGS values.
+enum {
+  RHF_NONE                    = 0x00000000, // No flags.
+  RHF_QUICKSTART              = 0x00000001, // Uses shortcut pointers.
+  RHF_NOTPOT                  = 0x00000002, // Hash size is not a power of two.
+  RHS_NO_LIBRARY_REPLACEMENT  = 0x00000004, // Ignore LD_LIBRARY_PATH.
+  RHF_NO_MOVE                 = 0x00000008, // DSO address may not be relocated.
+  RHF_SGI_ONLY                = 0x00000010, // SGI specific features.
+  RHF_GUARANTEE_INIT          = 0x00000020, // Guarantee that .init will finish
+                                            // executing before any non-init
+                                            // code in DSO is called.
+  RHF_DELTA_C_PLUS_PLUS       = 0x00000040, // Contains Delta C++ code.
+  RHF_GUARANTEE_START_INIT    = 0x00000080, // Guarantee that .init will start
+                                            // executing before any non-init
+                                            // code in DSO is called.
+  RHF_PIXIE                   = 0x00000100, // Generated by pixie.
+  RHF_DEFAULT_DELAY_LOAD      = 0x00000200, // Delay-load DSO by default.
+  RHF_REQUICKSTART            = 0x00000400, // Object may be requickstarted
+  RHF_REQUICKSTARTED          = 0x00000800, // Object has been requickstarted
+  RHF_CORD                    = 0x00001000, // Generated by cord.
+  RHF_NO_UNRES_UNDEF          = 0x00002000, // Object contains no unresolved
+                                            // undef symbols.
+  RHF_RLD_ORDER_SAFE          = 0x00004000  // Symbol table is in a safe order.
+};
+
+// ElfXX_VerDef structure version (GNU versioning)
+enum {
+  VER_DEF_NONE    = 0,
+  VER_DEF_CURRENT = 1
+};
+
+// VerDef Flags (ElfXX_VerDef::vd_flags)
+enum {
+  VER_FLG_BASE = 0x1,
+  VER_FLG_WEAK = 0x2,
+  VER_FLG_INFO = 0x4
+};
+
+// Special constants for the version table. (SHT_GNU_versym/.gnu.version)
+enum {
+  VER_NDX_LOCAL  = 0,      // Unversioned local symbol
+  VER_NDX_GLOBAL = 1,      // Unversioned global symbol
+  VERSYM_VERSION = 0x7fff, // Version Index mask
+  VERSYM_HIDDEN  = 0x8000  // Hidden bit (non-default version)
+};
+
+// ElfXX_VerNeed structure version (GNU versioning)
+enum {
+  VER_NEED_NONE = 0,
+  VER_NEED_CURRENT = 1
+};
+
+// SHT_NOTE section types
+enum {
+  NT_GNU_ABI_TAG = 1,
+  NT_GNU_HWCAP = 2,
+  NT_GNU_BUILD_ID = 3,
+  NT_GNU_GOLD_VERSION = 4,
+};
+
+enum {
+  GNU_ABI_TAG_LINUX = 0,
+  GNU_ABI_TAG_HURD = 1,
+  GNU_ABI_TAG_SOLARIS = 2,
+  GNU_ABI_TAG_FREEBSD = 3,
+  GNU_ABI_TAG_NETBSD = 4,
+  GNU_ABI_TAG_SYLLABLE = 5,
+  GNU_ABI_TAG_NACL = 6,
+};
+
+// Compressed section header for ELF32.
+struct Elf32_Chdr {
+  Elf32_Word ch_type;
+  Elf32_Word ch_size;
+  Elf32_Word ch_addralign;
+};
+
+// Compressed section header for ELF64.
+struct Elf64_Chdr {
+  Elf64_Word ch_type;
+  Elf64_Word ch_reserved;
+  Elf64_Xword ch_size;
+  Elf64_Xword ch_addralign;
+};
+
+// Legal values for ch_type field of compressed section header.
+enum {
+  ELFCOMPRESS_ZLIB = 1,            // ZLIB/DEFLATE algorithm.
+  ELFCOMPRESS_LOOS = 0x60000000,   // Start of OS-specific.
+  ELFCOMPRESS_HIOS = 0x6fffffff,   // End of OS-specific.
+  ELFCOMPRESS_LOPROC = 0x70000000, // Start of processor-specific.
+  ELFCOMPRESS_HIPROC = 0x7fffffff  // End of processor-specific.
+};
+
+} // end namespace ELF
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AArch64.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AArch64.def
new file mode 100644
index 0000000..aa0c560
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AArch64.def
@@ -0,0 +1,147 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// ABI release 1.0
+ELF_RELOC(R_AARCH64_NONE,                             0)
+
+ELF_RELOC(R_AARCH64_ABS64,                        0x101)
+ELF_RELOC(R_AARCH64_ABS32,                        0x102)
+ELF_RELOC(R_AARCH64_ABS16,                        0x103)
+ELF_RELOC(R_AARCH64_PREL64,                       0x104)
+ELF_RELOC(R_AARCH64_PREL32,                       0x105)
+ELF_RELOC(R_AARCH64_PREL16,                       0x106)
+
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0,                 0x107)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0_NC,              0x108)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1,                 0x109)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1_NC,              0x10a)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2,                 0x10b)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2_NC,              0x10c)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G3,                 0x10d)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G0,                 0x10e)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G1,                 0x10f)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G2,                 0x110)
+
+ELF_RELOC(R_AARCH64_LD_PREL_LO19,                 0x111)
+ELF_RELOC(R_AARCH64_ADR_PREL_LO21,                0x112)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21,             0x113)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC,          0x114)
+ELF_RELOC(R_AARCH64_ADD_ABS_LO12_NC,              0x115)
+ELF_RELOC(R_AARCH64_LDST8_ABS_LO12_NC,            0x116)
+
+ELF_RELOC(R_AARCH64_TSTBR14,                      0x117)
+ELF_RELOC(R_AARCH64_CONDBR19,                     0x118)
+ELF_RELOC(R_AARCH64_JUMP26,                       0x11a)
+ELF_RELOC(R_AARCH64_CALL26,                       0x11b)
+
+ELF_RELOC(R_AARCH64_LDST16_ABS_LO12_NC,           0x11c)
+ELF_RELOC(R_AARCH64_LDST32_ABS_LO12_NC,           0x11d)
+ELF_RELOC(R_AARCH64_LDST64_ABS_LO12_NC,           0x11e)
+
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0,                 0x11f)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0_NC,              0x120)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1,                 0x121)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1_NC,              0x122)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2,                 0x123)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2_NC,              0x124)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G3,                 0x125)
+
+ELF_RELOC(R_AARCH64_LDST128_ABS_LO12_NC,          0x12b)
+
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0,               0x12c)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC,            0x12d)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1,               0x12e)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC,            0x12f)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2,               0x130)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC,            0x131)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G3,               0x132)
+
+ELF_RELOC(R_AARCH64_GOTREL64,                     0x133)
+ELF_RELOC(R_AARCH64_GOTREL32,                     0x134)
+
+ELF_RELOC(R_AARCH64_GOT_LD_PREL19,                0x135)
+ELF_RELOC(R_AARCH64_LD64_GOTOFF_LO15,             0x136)
+ELF_RELOC(R_AARCH64_ADR_GOT_PAGE,                 0x137)
+ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC,             0x138)
+ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15,            0x139)
+
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21,             0x200)
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21,             0x201)
+ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC,            0x202)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G1,                0x203)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC,             0x204)
+
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PREL21,             0x205)
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PAGE21,             0x206)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC,            0x207)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G1,                0x208)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC,             0x209)
+ELF_RELOC(R_AARCH64_TLSLD_LD_PREL19,              0x20a)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2,         0x20b)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1,         0x20c)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,      0x20d)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0,         0x20e)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,      0x20f)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12,        0x210)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12,        0x211)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC,     0x212)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12,      0x213)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC,   0x214)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12,     0x215)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,  0x216)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12,     0x217)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,  0x218)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12,     0x219)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,  0x21a)
+
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1,       0x21b)
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,    0x21c)
+ELF_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,    0x21d)
+ELF_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,  0x21e)
+ELF_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19,     0x21f)
+
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2,          0x220)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1,          0x221)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC,       0x222)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0,          0x223)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC,       0x224)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12,         0x225)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12,         0x226)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,      0x227)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12,       0x228)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC,    0x229)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12,      0x22a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC,   0x22b)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12,      0x22c)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC,   0x22d)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12,      0x22e)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC,   0x22f)
+
+ELF_RELOC(R_AARCH64_TLSDESC_LD_PREL19,            0x230)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PREL21,           0x231)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21,           0x232)
+ELF_RELOC(R_AARCH64_TLSDESC_LD64_LO12_NC,         0x233)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD_LO12_NC,          0x234)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G1,               0x235)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC,            0x236)
+ELF_RELOC(R_AARCH64_TLSDESC_LDR,                  0x237)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD,                  0x238)
+ELF_RELOC(R_AARCH64_TLSDESC_CALL,                 0x239)
+
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12,     0x23a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC,  0x23b)
+
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12,    0x23c)
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d)
+
+ELF_RELOC(R_AARCH64_COPY,                         0x400)
+ELF_RELOC(R_AARCH64_GLOB_DAT,                     0x401)
+ELF_RELOC(R_AARCH64_JUMP_SLOT,                    0x402)
+ELF_RELOC(R_AARCH64_RELATIVE,                     0x403)
+ELF_RELOC(R_AARCH64_TLS_DTPREL64,                 0x404)
+ELF_RELOC(R_AARCH64_TLS_DTPMOD64,                 0x405)
+ELF_RELOC(R_AARCH64_TLS_TPREL64,                  0x406)
+ELF_RELOC(R_AARCH64_TLSDESC,                      0x407)
+ELF_RELOC(R_AARCH64_IRELATIVE,                    0x408)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AMDGPU.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AMDGPU.def
new file mode 100644
index 0000000..c1e6797
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AMDGPU.def
@@ -0,0 +1,12 @@
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_AMDGPU_NONE,          0)
+ELF_RELOC(R_AMDGPU_ABS32_LO,      1)
+ELF_RELOC(R_AMDGPU_ABS32_HI,      2)
+ELF_RELOC(R_AMDGPU_ABS64,         3)
+ELF_RELOC(R_AMDGPU_REL32,         4)
+ELF_RELOC(R_AMDGPU_REL64,         5)
+ELF_RELOC(R_AMDGPU_ABS32,         6)
+ELF_RELOC(R_AMDGPU_GOTPCREL,      7)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/ARM.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/ARM.def
new file mode 100644
index 0000000..730fc5b
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/ARM.def
@@ -0,0 +1,138 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Meets 2.09 ABI Specs.
+ELF_RELOC(R_ARM_NONE,                   0x00)
+ELF_RELOC(R_ARM_PC24,                   0x01)
+ELF_RELOC(R_ARM_ABS32,                  0x02)
+ELF_RELOC(R_ARM_REL32,                  0x03)
+ELF_RELOC(R_ARM_LDR_PC_G0,              0x04)
+ELF_RELOC(R_ARM_ABS16,                  0x05)
+ELF_RELOC(R_ARM_ABS12,                  0x06)
+ELF_RELOC(R_ARM_THM_ABS5,               0x07)
+ELF_RELOC(R_ARM_ABS8,                   0x08)
+ELF_RELOC(R_ARM_SBREL32,                0x09)
+ELF_RELOC(R_ARM_THM_CALL,               0x0a)
+ELF_RELOC(R_ARM_THM_PC8,                0x0b)
+ELF_RELOC(R_ARM_BREL_ADJ,               0x0c)
+ELF_RELOC(R_ARM_TLS_DESC,               0x0d)
+ELF_RELOC(R_ARM_THM_SWI8,               0x0e)
+ELF_RELOC(R_ARM_XPC25,                  0x0f)
+ELF_RELOC(R_ARM_THM_XPC22,              0x10)
+ELF_RELOC(R_ARM_TLS_DTPMOD32,           0x11)
+ELF_RELOC(R_ARM_TLS_DTPOFF32,           0x12)
+ELF_RELOC(R_ARM_TLS_TPOFF32,            0x13)
+ELF_RELOC(R_ARM_COPY,                   0x14)
+ELF_RELOC(R_ARM_GLOB_DAT,               0x15)
+ELF_RELOC(R_ARM_JUMP_SLOT,              0x16)
+ELF_RELOC(R_ARM_RELATIVE,               0x17)
+ELF_RELOC(R_ARM_GOTOFF32,               0x18)
+ELF_RELOC(R_ARM_BASE_PREL,              0x19)
+ELF_RELOC(R_ARM_GOT_BREL,               0x1a)
+ELF_RELOC(R_ARM_PLT32,                  0x1b)
+ELF_RELOC(R_ARM_CALL,                   0x1c)
+ELF_RELOC(R_ARM_JUMP24,                 0x1d)
+ELF_RELOC(R_ARM_THM_JUMP24,             0x1e)
+ELF_RELOC(R_ARM_BASE_ABS,               0x1f)
+ELF_RELOC(R_ARM_ALU_PCREL_7_0,          0x20)
+ELF_RELOC(R_ARM_ALU_PCREL_15_8,         0x21)
+ELF_RELOC(R_ARM_ALU_PCREL_23_15,        0x22)
+ELF_RELOC(R_ARM_LDR_SBREL_11_0_NC,      0x23)
+ELF_RELOC(R_ARM_ALU_SBREL_19_12_NC,     0x24)
+ELF_RELOC(R_ARM_ALU_SBREL_27_20_CK,     0x25)
+ELF_RELOC(R_ARM_TARGET1,                0x26)
+ELF_RELOC(R_ARM_SBREL31,                0x27)
+ELF_RELOC(R_ARM_V4BX,                   0x28)
+ELF_RELOC(R_ARM_TARGET2,                0x29)
+ELF_RELOC(R_ARM_PREL31,                 0x2a)
+ELF_RELOC(R_ARM_MOVW_ABS_NC,            0x2b)
+ELF_RELOC(R_ARM_MOVT_ABS,               0x2c)
+ELF_RELOC(R_ARM_MOVW_PREL_NC,           0x2d)
+ELF_RELOC(R_ARM_MOVT_PREL,              0x2e)
+ELF_RELOC(R_ARM_THM_MOVW_ABS_NC,        0x2f)
+ELF_RELOC(R_ARM_THM_MOVT_ABS,           0x30)
+ELF_RELOC(R_ARM_THM_MOVW_PREL_NC,       0x31)
+ELF_RELOC(R_ARM_THM_MOVT_PREL,          0x32)
+ELF_RELOC(R_ARM_THM_JUMP19,             0x33)
+ELF_RELOC(R_ARM_THM_JUMP6,              0x34)
+ELF_RELOC(R_ARM_THM_ALU_PREL_11_0,      0x35)
+ELF_RELOC(R_ARM_THM_PC12,               0x36)
+ELF_RELOC(R_ARM_ABS32_NOI,              0x37)
+ELF_RELOC(R_ARM_REL32_NOI,              0x38)
+ELF_RELOC(R_ARM_ALU_PC_G0_NC,           0x39)
+ELF_RELOC(R_ARM_ALU_PC_G0,              0x3a)
+ELF_RELOC(R_ARM_ALU_PC_G1_NC,           0x3b)
+ELF_RELOC(R_ARM_ALU_PC_G1,              0x3c)
+ELF_RELOC(R_ARM_ALU_PC_G2,              0x3d)
+ELF_RELOC(R_ARM_LDR_PC_G1,              0x3e)
+ELF_RELOC(R_ARM_LDR_PC_G2,              0x3f)
+ELF_RELOC(R_ARM_LDRS_PC_G0,             0x40)
+ELF_RELOC(R_ARM_LDRS_PC_G1,             0x41)
+ELF_RELOC(R_ARM_LDRS_PC_G2,             0x42)
+ELF_RELOC(R_ARM_LDC_PC_G0,              0x43)
+ELF_RELOC(R_ARM_LDC_PC_G1,              0x44)
+ELF_RELOC(R_ARM_LDC_PC_G2,              0x45)
+ELF_RELOC(R_ARM_ALU_SB_G0_NC,           0x46)
+ELF_RELOC(R_ARM_ALU_SB_G0,              0x47)
+ELF_RELOC(R_ARM_ALU_SB_G1_NC,           0x48)
+ELF_RELOC(R_ARM_ALU_SB_G1,              0x49)
+ELF_RELOC(R_ARM_ALU_SB_G2,              0x4a)
+ELF_RELOC(R_ARM_LDR_SB_G0,              0x4b)
+ELF_RELOC(R_ARM_LDR_SB_G1,              0x4c)
+ELF_RELOC(R_ARM_LDR_SB_G2,              0x4d)
+ELF_RELOC(R_ARM_LDRS_SB_G0,             0x4e)
+ELF_RELOC(R_ARM_LDRS_SB_G1,             0x4f)
+ELF_RELOC(R_ARM_LDRS_SB_G2,             0x50)
+ELF_RELOC(R_ARM_LDC_SB_G0,              0x51)
+ELF_RELOC(R_ARM_LDC_SB_G1,              0x52)
+ELF_RELOC(R_ARM_LDC_SB_G2,              0x53)
+ELF_RELOC(R_ARM_MOVW_BREL_NC,           0x54)
+ELF_RELOC(R_ARM_MOVT_BREL,              0x55)
+ELF_RELOC(R_ARM_MOVW_BREL,              0x56)
+ELF_RELOC(R_ARM_THM_MOVW_BREL_NC,       0x57)
+ELF_RELOC(R_ARM_THM_MOVT_BREL,          0x58)
+ELF_RELOC(R_ARM_THM_MOVW_BREL,          0x59)
+ELF_RELOC(R_ARM_TLS_GOTDESC,            0x5a)
+ELF_RELOC(R_ARM_TLS_CALL,               0x5b)
+ELF_RELOC(R_ARM_TLS_DESCSEQ,            0x5c)
+ELF_RELOC(R_ARM_THM_TLS_CALL,           0x5d)
+ELF_RELOC(R_ARM_PLT32_ABS,              0x5e)
+ELF_RELOC(R_ARM_GOT_ABS,                0x5f)
+ELF_RELOC(R_ARM_GOT_PREL,               0x60)
+ELF_RELOC(R_ARM_GOT_BREL12,             0x61)
+ELF_RELOC(R_ARM_GOTOFF12,               0x62)
+ELF_RELOC(R_ARM_GOTRELAX,               0x63)
+ELF_RELOC(R_ARM_GNU_VTENTRY,            0x64)
+ELF_RELOC(R_ARM_GNU_VTINHERIT,          0x65)
+ELF_RELOC(R_ARM_THM_JUMP11,             0x66)
+ELF_RELOC(R_ARM_THM_JUMP8,              0x67)
+ELF_RELOC(R_ARM_TLS_GD32,               0x68)
+ELF_RELOC(R_ARM_TLS_LDM32,              0x69)
+ELF_RELOC(R_ARM_TLS_LDO32,              0x6a)
+ELF_RELOC(R_ARM_TLS_IE32,               0x6b)
+ELF_RELOC(R_ARM_TLS_LE32,               0x6c)
+ELF_RELOC(R_ARM_TLS_LDO12,              0x6d)
+ELF_RELOC(R_ARM_TLS_LE12,               0x6e)
+ELF_RELOC(R_ARM_TLS_IE12GP,             0x6f)
+ELF_RELOC(R_ARM_PRIVATE_0,              0x70)
+ELF_RELOC(R_ARM_PRIVATE_1,              0x71)
+ELF_RELOC(R_ARM_PRIVATE_2,              0x72)
+ELF_RELOC(R_ARM_PRIVATE_3,              0x73)
+ELF_RELOC(R_ARM_PRIVATE_4,              0x74)
+ELF_RELOC(R_ARM_PRIVATE_5,              0x75)
+ELF_RELOC(R_ARM_PRIVATE_6,              0x76)
+ELF_RELOC(R_ARM_PRIVATE_7,              0x77)
+ELF_RELOC(R_ARM_PRIVATE_8,              0x78)
+ELF_RELOC(R_ARM_PRIVATE_9,              0x79)
+ELF_RELOC(R_ARM_PRIVATE_10,             0x7a)
+ELF_RELOC(R_ARM_PRIVATE_11,             0x7b)
+ELF_RELOC(R_ARM_PRIVATE_12,             0x7c)
+ELF_RELOC(R_ARM_PRIVATE_13,             0x7d)
+ELF_RELOC(R_ARM_PRIVATE_14,             0x7e)
+ELF_RELOC(R_ARM_PRIVATE_15,             0x7f)
+ELF_RELOC(R_ARM_ME_TOO,                 0x80)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16,      0x81)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32,      0x82)
+ELF_RELOC(R_ARM_IRELATIVE,              0xa0)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AVR.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AVR.def
new file mode 100644
index 0000000..5692d6c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AVR.def
@@ -0,0 +1,40 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_AVR_NONE,                  0)
+ELF_RELOC(R_AVR_32,                    1)
+ELF_RELOC(R_AVR_7_PCREL,               2)
+ELF_RELOC(R_AVR_13_PCREL,              3)
+ELF_RELOC(R_AVR_16,                    4)
+ELF_RELOC(R_AVR_16_PM,                 5)
+ELF_RELOC(R_AVR_LO8_LDI,               6)
+ELF_RELOC(R_AVR_HI8_LDI,               7)
+ELF_RELOC(R_AVR_HH8_LDI,               8)
+ELF_RELOC(R_AVR_LO8_LDI_NEG,           9)
+ELF_RELOC(R_AVR_HI8_LDI_NEG,          10)
+ELF_RELOC(R_AVR_HH8_LDI_NEG,          11)
+ELF_RELOC(R_AVR_LO8_LDI_PM,           12)
+ELF_RELOC(R_AVR_HI8_LDI_PM,           13)
+ELF_RELOC(R_AVR_HH8_LDI_PM,           14)
+ELF_RELOC(R_AVR_LO8_LDI_PM_NEG,       15)
+ELF_RELOC(R_AVR_HI8_LDI_PM_NEG,       16)
+ELF_RELOC(R_AVR_HH8_LDI_PM_NEG,       17)
+ELF_RELOC(R_AVR_CALL,                 18)
+ELF_RELOC(R_AVR_LDI,                  19)
+ELF_RELOC(R_AVR_6,                    20)
+ELF_RELOC(R_AVR_6_ADIW,               21)
+ELF_RELOC(R_AVR_MS8_LDI,              22)
+ELF_RELOC(R_AVR_MS8_LDI_NEG,          23)
+ELF_RELOC(R_AVR_LO8_LDI_GS,           24)
+ELF_RELOC(R_AVR_HI8_LDI_GS,           25)
+ELF_RELOC(R_AVR_8,                    26)
+ELF_RELOC(R_AVR_8_LO8,                27)
+ELF_RELOC(R_AVR_8_HI8,                28)
+ELF_RELOC(R_AVR_8_HLO8,               29)
+ELF_RELOC(R_AVR_SYM_DIFF,             30)
+ELF_RELOC(R_AVR_16_LDST,              31)
+ELF_RELOC(R_AVR_LDS_STS_16,           33)
+ELF_RELOC(R_AVR_PORT6,                34)
+ELF_RELOC(R_AVR_PORT5,                35)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/BPF.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/BPF.def
new file mode 100644
index 0000000..868974d
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/BPF.def
@@ -0,0 +1,9 @@
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// No relocation
+ELF_RELOC(R_BPF_NONE,        0)
+// Map index in "maps" section to file descriptor
+// within ld_64 instruction.
+ELF_RELOC(R_BPF_MAP_FD,      1)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Hexagon.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Hexagon.def
new file mode 100644
index 0000000..74e1d40
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Hexagon.def
@@ -0,0 +1,101 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Release 5 ABI
+ELF_RELOC(R_HEX_NONE,                0)
+ELF_RELOC(R_HEX_B22_PCREL,           1)
+ELF_RELOC(R_HEX_B15_PCREL,           2)
+ELF_RELOC(R_HEX_B7_PCREL,            3)
+ELF_RELOC(R_HEX_LO16,                4)
+ELF_RELOC(R_HEX_HI16,                5)
+ELF_RELOC(R_HEX_32,                  6)
+ELF_RELOC(R_HEX_16,                  7)
+ELF_RELOC(R_HEX_8,                   8)
+ELF_RELOC(R_HEX_GPREL16_0,           9)
+ELF_RELOC(R_HEX_GPREL16_1,           10)
+ELF_RELOC(R_HEX_GPREL16_2,           11)
+ELF_RELOC(R_HEX_GPREL16_3,           12)
+ELF_RELOC(R_HEX_HL16,                13)
+ELF_RELOC(R_HEX_B13_PCREL,           14)
+ELF_RELOC(R_HEX_B9_PCREL,            15)
+ELF_RELOC(R_HEX_B32_PCREL_X,         16)
+ELF_RELOC(R_HEX_32_6_X,              17)
+ELF_RELOC(R_HEX_B22_PCREL_X,         18)
+ELF_RELOC(R_HEX_B15_PCREL_X,         19)
+ELF_RELOC(R_HEX_B13_PCREL_X,         20)
+ELF_RELOC(R_HEX_B9_PCREL_X,          21)
+ELF_RELOC(R_HEX_B7_PCREL_X,          22)
+ELF_RELOC(R_HEX_16_X,                23)
+ELF_RELOC(R_HEX_12_X,                24)
+ELF_RELOC(R_HEX_11_X,                25)
+ELF_RELOC(R_HEX_10_X,                26)
+ELF_RELOC(R_HEX_9_X,                 27)
+ELF_RELOC(R_HEX_8_X,                 28)
+ELF_RELOC(R_HEX_7_X,                 29)
+ELF_RELOC(R_HEX_6_X,                 30)
+ELF_RELOC(R_HEX_32_PCREL,            31)
+ELF_RELOC(R_HEX_COPY,                32)
+ELF_RELOC(R_HEX_GLOB_DAT,            33)
+ELF_RELOC(R_HEX_JMP_SLOT,            34)
+ELF_RELOC(R_HEX_RELATIVE,            35)
+ELF_RELOC(R_HEX_PLT_B22_PCREL,       36)
+ELF_RELOC(R_HEX_GOTREL_LO16,         37)
+ELF_RELOC(R_HEX_GOTREL_HI16,         38)
+ELF_RELOC(R_HEX_GOTREL_32,           39)
+ELF_RELOC(R_HEX_GOT_LO16,            40)
+ELF_RELOC(R_HEX_GOT_HI16,            41)
+ELF_RELOC(R_HEX_GOT_32,              42)
+ELF_RELOC(R_HEX_GOT_16,              43)
+ELF_RELOC(R_HEX_DTPMOD_32,           44)
+ELF_RELOC(R_HEX_DTPREL_LO16,         45)
+ELF_RELOC(R_HEX_DTPREL_HI16,         46)
+ELF_RELOC(R_HEX_DTPREL_32,           47)
+ELF_RELOC(R_HEX_DTPREL_16,           48)
+ELF_RELOC(R_HEX_GD_PLT_B22_PCREL,    49)
+ELF_RELOC(R_HEX_GD_GOT_LO16,         50)
+ELF_RELOC(R_HEX_GD_GOT_HI16,         51)
+ELF_RELOC(R_HEX_GD_GOT_32,           52)
+ELF_RELOC(R_HEX_GD_GOT_16,           53)
+ELF_RELOC(R_HEX_IE_LO16,             54)
+ELF_RELOC(R_HEX_IE_HI16,             55)
+ELF_RELOC(R_HEX_IE_32,               56)
+ELF_RELOC(R_HEX_IE_GOT_LO16,         57)
+ELF_RELOC(R_HEX_IE_GOT_HI16,         58)
+ELF_RELOC(R_HEX_IE_GOT_32,           59)
+ELF_RELOC(R_HEX_IE_GOT_16,           60)
+ELF_RELOC(R_HEX_TPREL_LO16,          61)
+ELF_RELOC(R_HEX_TPREL_HI16,          62)
+ELF_RELOC(R_HEX_TPREL_32,            63)
+ELF_RELOC(R_HEX_TPREL_16,            64)
+ELF_RELOC(R_HEX_6_PCREL_X,           65)
+ELF_RELOC(R_HEX_GOTREL_32_6_X,       66)
+ELF_RELOC(R_HEX_GOTREL_16_X,         67)
+ELF_RELOC(R_HEX_GOTREL_11_X,         68)
+ELF_RELOC(R_HEX_GOT_32_6_X,          69)
+ELF_RELOC(R_HEX_GOT_16_X,            70)
+ELF_RELOC(R_HEX_GOT_11_X,            71)
+ELF_RELOC(R_HEX_DTPREL_32_6_X,       72)
+ELF_RELOC(R_HEX_DTPREL_16_X,         73)
+ELF_RELOC(R_HEX_DTPREL_11_X,         74)
+ELF_RELOC(R_HEX_GD_GOT_32_6_X,       75)
+ELF_RELOC(R_HEX_GD_GOT_16_X,         76)
+ELF_RELOC(R_HEX_GD_GOT_11_X,         77)
+ELF_RELOC(R_HEX_IE_32_6_X,           78)
+ELF_RELOC(R_HEX_IE_16_X,             79)
+ELF_RELOC(R_HEX_IE_GOT_32_6_X,       80)
+ELF_RELOC(R_HEX_IE_GOT_16_X,         81)
+ELF_RELOC(R_HEX_IE_GOT_11_X,         82)
+ELF_RELOC(R_HEX_TPREL_32_6_X,        83)
+ELF_RELOC(R_HEX_TPREL_16_X,          84)
+ELF_RELOC(R_HEX_TPREL_11_X,          85)
+ELF_RELOC(R_HEX_LD_PLT_B22_PCREL,    86)
+ELF_RELOC(R_HEX_LD_GOT_LO16,         87)
+ELF_RELOC(R_HEX_LD_GOT_HI16,         88)
+ELF_RELOC(R_HEX_LD_GOT_32,           89)
+ELF_RELOC(R_HEX_LD_GOT_16,           90)
+ELF_RELOC(R_HEX_LD_GOT_32_6_X,       91)
+ELF_RELOC(R_HEX_LD_GOT_16_X,         92)
+ELF_RELOC(R_HEX_LD_GOT_11_X,         93)
+ELF_RELOC(R_HEX_23_REG,              94)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Lanai.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Lanai.def
new file mode 100644
index 0000000..77ecb04
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Lanai.def
@@ -0,0 +1,19 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// No relocation
+ELF_RELOC(R_LANAI_NONE,        0)
+// 21-bit symbol relocation
+ELF_RELOC(R_LANAI_21,          1)
+// 21-bit symbol relocation with last two bits masked to 0
+ELF_RELOC(R_LANAI_21_F,        2)
+// 25-bit branch targets
+ELF_RELOC(R_LANAI_25,          3)
+// General 32-bit relocation
+ELF_RELOC(R_LANAI_32,          4)
+// Upper 16-bits of a symbolic relocation
+ELF_RELOC(R_LANAI_HI16,        5)
+// Lower 16-bits of a symbolic relocation
+ELF_RELOC(R_LANAI_LO16,        6)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Mips.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Mips.def
new file mode 100644
index 0000000..bc0088d
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Mips.def
@@ -0,0 +1,117 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_MIPS_NONE,                0)
+ELF_RELOC(R_MIPS_16,                  1)
+ELF_RELOC(R_MIPS_32,                  2)
+ELF_RELOC(R_MIPS_REL32,               3)
+ELF_RELOC(R_MIPS_26,                  4)
+ELF_RELOC(R_MIPS_HI16,                5)
+ELF_RELOC(R_MIPS_LO16,                6)
+ELF_RELOC(R_MIPS_GPREL16,             7)
+ELF_RELOC(R_MIPS_LITERAL,             8)
+ELF_RELOC(R_MIPS_GOT16,               9)
+ELF_RELOC(R_MIPS_PC16,               10)
+ELF_RELOC(R_MIPS_CALL16,             11)
+ELF_RELOC(R_MIPS_GPREL32,            12)
+ELF_RELOC(R_MIPS_UNUSED1,            13)
+ELF_RELOC(R_MIPS_UNUSED2,            14)
+ELF_RELOC(R_MIPS_UNUSED3,            15)
+ELF_RELOC(R_MIPS_SHIFT5,             16)
+ELF_RELOC(R_MIPS_SHIFT6,             17)
+ELF_RELOC(R_MIPS_64,                 18)
+ELF_RELOC(R_MIPS_GOT_DISP,           19)
+ELF_RELOC(R_MIPS_GOT_PAGE,           20)
+ELF_RELOC(R_MIPS_GOT_OFST,           21)
+ELF_RELOC(R_MIPS_GOT_HI16,           22)
+ELF_RELOC(R_MIPS_GOT_LO16,           23)
+ELF_RELOC(R_MIPS_SUB,                24)
+ELF_RELOC(R_MIPS_INSERT_A,           25)
+ELF_RELOC(R_MIPS_INSERT_B,           26)
+ELF_RELOC(R_MIPS_DELETE,             27)
+ELF_RELOC(R_MIPS_HIGHER,             28)
+ELF_RELOC(R_MIPS_HIGHEST,            29)
+ELF_RELOC(R_MIPS_CALL_HI16,          30)
+ELF_RELOC(R_MIPS_CALL_LO16,          31)
+ELF_RELOC(R_MIPS_SCN_DISP,           32)
+ELF_RELOC(R_MIPS_REL16,              33)
+ELF_RELOC(R_MIPS_ADD_IMMEDIATE,      34)
+ELF_RELOC(R_MIPS_PJUMP,              35)
+ELF_RELOC(R_MIPS_RELGOT,             36)
+ELF_RELOC(R_MIPS_JALR,               37)
+ELF_RELOC(R_MIPS_TLS_DTPMOD32,       38)
+ELF_RELOC(R_MIPS_TLS_DTPREL32,       39)
+ELF_RELOC(R_MIPS_TLS_DTPMOD64,       40)
+ELF_RELOC(R_MIPS_TLS_DTPREL64,       41)
+ELF_RELOC(R_MIPS_TLS_GD,             42)
+ELF_RELOC(R_MIPS_TLS_LDM,            43)
+ELF_RELOC(R_MIPS_TLS_DTPREL_HI16,    44)
+ELF_RELOC(R_MIPS_TLS_DTPREL_LO16,    45)
+ELF_RELOC(R_MIPS_TLS_GOTTPREL,       46)
+ELF_RELOC(R_MIPS_TLS_TPREL32,        47)
+ELF_RELOC(R_MIPS_TLS_TPREL64,        48)
+ELF_RELOC(R_MIPS_TLS_TPREL_HI16,     49)
+ELF_RELOC(R_MIPS_TLS_TPREL_LO16,     50)
+ELF_RELOC(R_MIPS_GLOB_DAT,           51)
+ELF_RELOC(R_MIPS_PC21_S2,            60)
+ELF_RELOC(R_MIPS_PC26_S2,            61)
+ELF_RELOC(R_MIPS_PC18_S3,            62)
+ELF_RELOC(R_MIPS_PC19_S2,            63)
+ELF_RELOC(R_MIPS_PCHI16,             64)
+ELF_RELOC(R_MIPS_PCLO16,             65)
+ELF_RELOC(R_MIPS16_26,               100)
+ELF_RELOC(R_MIPS16_GPREL,            101)
+ELF_RELOC(R_MIPS16_GOT16,            102)
+ELF_RELOC(R_MIPS16_CALL16,           103)
+ELF_RELOC(R_MIPS16_HI16,             104)
+ELF_RELOC(R_MIPS16_LO16,             105)
+ELF_RELOC(R_MIPS16_TLS_GD,           106)
+ELF_RELOC(R_MIPS16_TLS_LDM,          107)
+ELF_RELOC(R_MIPS16_TLS_DTPREL_HI16,  108)
+ELF_RELOC(R_MIPS16_TLS_DTPREL_LO16,  109)
+ELF_RELOC(R_MIPS16_TLS_GOTTPREL,     110)
+ELF_RELOC(R_MIPS16_TLS_TPREL_HI16,   111)
+ELF_RELOC(R_MIPS16_TLS_TPREL_LO16,   112)
+ELF_RELOC(R_MIPS_COPY,               126)
+ELF_RELOC(R_MIPS_JUMP_SLOT,          127)
+ELF_RELOC(R_MICROMIPS_26_S1,         133)
+ELF_RELOC(R_MICROMIPS_HI16,          134)
+ELF_RELOC(R_MICROMIPS_LO16,          135)
+ELF_RELOC(R_MICROMIPS_GPREL16,       136)
+ELF_RELOC(R_MICROMIPS_LITERAL,       137)
+ELF_RELOC(R_MICROMIPS_GOT16,         138)
+ELF_RELOC(R_MICROMIPS_PC7_S1,        139)
+ELF_RELOC(R_MICROMIPS_PC10_S1,       140)
+ELF_RELOC(R_MICROMIPS_PC16_S1,       141)
+ELF_RELOC(R_MICROMIPS_CALL16,        142)
+ELF_RELOC(R_MICROMIPS_GOT_DISP,      145)
+ELF_RELOC(R_MICROMIPS_GOT_PAGE,      146)
+ELF_RELOC(R_MICROMIPS_GOT_OFST,      147)
+ELF_RELOC(R_MICROMIPS_GOT_HI16,      148)
+ELF_RELOC(R_MICROMIPS_GOT_LO16,      149)
+ELF_RELOC(R_MICROMIPS_SUB,           150)
+ELF_RELOC(R_MICROMIPS_HIGHER,        151)
+ELF_RELOC(R_MICROMIPS_HIGHEST,       152)
+ELF_RELOC(R_MICROMIPS_CALL_HI16,     153)
+ELF_RELOC(R_MICROMIPS_CALL_LO16,     154)
+ELF_RELOC(R_MICROMIPS_SCN_DISP,      155)
+ELF_RELOC(R_MICROMIPS_JALR,          156)
+ELF_RELOC(R_MICROMIPS_HI0_LO16,      157)
+ELF_RELOC(R_MICROMIPS_TLS_GD,           162)
+ELF_RELOC(R_MICROMIPS_TLS_LDM,          163)
+ELF_RELOC(R_MICROMIPS_TLS_DTPREL_HI16,  164)
+ELF_RELOC(R_MICROMIPS_TLS_DTPREL_LO16,  165)
+ELF_RELOC(R_MICROMIPS_TLS_GOTTPREL,     166)
+ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16,   169)
+ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16,   170)
+ELF_RELOC(R_MICROMIPS_GPREL7_S2,        172)
+ELF_RELOC(R_MICROMIPS_PC23_S2,          173)
+ELF_RELOC(R_MICROMIPS_PC21_S1,          174)
+ELF_RELOC(R_MICROMIPS_PC26_S1,          175)
+ELF_RELOC(R_MICROMIPS_PC18_S3,          176)
+ELF_RELOC(R_MICROMIPS_PC19_S2,          177)
+ELF_RELOC(R_MIPS_NUM,                218)
+ELF_RELOC(R_MIPS_PC32,               248)
+ELF_RELOC(R_MIPS_EH,                 249)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC.def
new file mode 100644
index 0000000..e4f8ee0
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC.def
@@ -0,0 +1,123 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// glibc's PowerPC asm/sigcontext.h, when compiling for PPC64, has the
+// unfortunate behavior of including asm/elf.h, which defines R_PPC_NONE, etc.
+// to their corresponding integer values. As a result, we need to undef them
+// here before continuing.
+
+#undef R_PPC_NONE
+#undef R_PPC_ADDR32
+#undef R_PPC_ADDR24
+#undef R_PPC_ADDR16
+#undef R_PPC_ADDR16_LO
+#undef R_PPC_ADDR16_HI
+#undef R_PPC_ADDR16_HA
+#undef R_PPC_ADDR14
+#undef R_PPC_ADDR14_BRTAKEN
+#undef R_PPC_ADDR14_BRNTAKEN
+#undef R_PPC_REL24
+#undef R_PPC_REL14
+#undef R_PPC_REL14_BRTAKEN
+#undef R_PPC_REL14_BRNTAKEN
+#undef R_PPC_GOT16
+#undef R_PPC_GOT16_LO
+#undef R_PPC_GOT16_HI
+#undef R_PPC_GOT16_HA
+#undef R_PPC_PLTREL24
+#undef R_PPC_JMP_SLOT
+#undef R_PPC_LOCAL24PC
+#undef R_PPC_REL32
+#undef R_PPC_TLS
+#undef R_PPC_DTPMOD32
+#undef R_PPC_TPREL16
+#undef R_PPC_TPREL16_LO
+#undef R_PPC_TPREL16_HI
+#undef R_PPC_TPREL16_HA
+#undef R_PPC_TPREL32
+#undef R_PPC_DTPREL16
+#undef R_PPC_DTPREL16_LO
+#undef R_PPC_DTPREL16_HI
+#undef R_PPC_DTPREL16_HA
+#undef R_PPC_DTPREL32
+#undef R_PPC_GOT_TLSGD16
+#undef R_PPC_GOT_TLSGD16_LO
+#undef R_PPC_GOT_TLSGD16_HI
+#undef R_PPC_GOT_TLSGD16_HA
+#undef R_PPC_GOT_TLSLD16
+#undef R_PPC_GOT_TLSLD16_LO
+#undef R_PPC_GOT_TLSLD16_HI
+#undef R_PPC_GOT_TLSLD16_HA
+#undef R_PPC_GOT_TPREL16
+#undef R_PPC_GOT_TPREL16_LO
+#undef R_PPC_GOT_TPREL16_HI
+#undef R_PPC_GOT_TPREL16_HA
+#undef R_PPC_GOT_DTPREL16
+#undef R_PPC_GOT_DTPREL16_LO
+#undef R_PPC_GOT_DTPREL16_HI
+#undef R_PPC_GOT_DTPREL16_HA
+#undef R_PPC_TLSGD
+#undef R_PPC_TLSLD
+#undef R_PPC_REL16
+#undef R_PPC_REL16_LO
+#undef R_PPC_REL16_HI
+#undef R_PPC_REL16_HA
+
+ELF_RELOC(R_PPC_NONE,                   0)      /* No relocation. */
+ELF_RELOC(R_PPC_ADDR32,                 1)
+ELF_RELOC(R_PPC_ADDR24,                 2)
+ELF_RELOC(R_PPC_ADDR16,                 3)
+ELF_RELOC(R_PPC_ADDR16_LO,              4)
+ELF_RELOC(R_PPC_ADDR16_HI,              5)
+ELF_RELOC(R_PPC_ADDR16_HA,              6)
+ELF_RELOC(R_PPC_ADDR14,                 7)
+ELF_RELOC(R_PPC_ADDR14_BRTAKEN,         8)
+ELF_RELOC(R_PPC_ADDR14_BRNTAKEN,        9)
+ELF_RELOC(R_PPC_REL24,                  10)
+ELF_RELOC(R_PPC_REL14,                  11)
+ELF_RELOC(R_PPC_REL14_BRTAKEN,          12)
+ELF_RELOC(R_PPC_REL14_BRNTAKEN,         13)
+ELF_RELOC(R_PPC_GOT16,                  14)
+ELF_RELOC(R_PPC_GOT16_LO,               15)
+ELF_RELOC(R_PPC_GOT16_HI,               16)
+ELF_RELOC(R_PPC_GOT16_HA,               17)
+ELF_RELOC(R_PPC_PLTREL24,               18)
+ELF_RELOC(R_PPC_JMP_SLOT,               21)
+ELF_RELOC(R_PPC_LOCAL24PC,              23)
+ELF_RELOC(R_PPC_REL32,                  26)
+ELF_RELOC(R_PPC_TLS,                    67)
+ELF_RELOC(R_PPC_DTPMOD32,               68)
+ELF_RELOC(R_PPC_TPREL16,                69)
+ELF_RELOC(R_PPC_TPREL16_LO,             70)
+ELF_RELOC(R_PPC_TPREL16_HI,             71)
+ELF_RELOC(R_PPC_TPREL16_HA,             72)
+ELF_RELOC(R_PPC_TPREL32,                73)
+ELF_RELOC(R_PPC_DTPREL16,               74)
+ELF_RELOC(R_PPC_DTPREL16_LO,            75)
+ELF_RELOC(R_PPC_DTPREL16_HI,            76)
+ELF_RELOC(R_PPC_DTPREL16_HA,            77)
+ELF_RELOC(R_PPC_DTPREL32,               78)
+ELF_RELOC(R_PPC_GOT_TLSGD16,            79)
+ELF_RELOC(R_PPC_GOT_TLSGD16_LO,         80)
+ELF_RELOC(R_PPC_GOT_TLSGD16_HI,         81)
+ELF_RELOC(R_PPC_GOT_TLSGD16_HA,         82)
+ELF_RELOC(R_PPC_GOT_TLSLD16,            83)
+ELF_RELOC(R_PPC_GOT_TLSLD16_LO,         84)
+ELF_RELOC(R_PPC_GOT_TLSLD16_HI,         85)
+ELF_RELOC(R_PPC_GOT_TLSLD16_HA,         86)
+ELF_RELOC(R_PPC_GOT_TPREL16,            87)
+ELF_RELOC(R_PPC_GOT_TPREL16_LO,         88)
+ELF_RELOC(R_PPC_GOT_TPREL16_HI,         89)
+ELF_RELOC(R_PPC_GOT_TPREL16_HA,         90)
+ELF_RELOC(R_PPC_GOT_DTPREL16,           91)
+ELF_RELOC(R_PPC_GOT_DTPREL16_LO,        92)
+ELF_RELOC(R_PPC_GOT_DTPREL16_HI,        93)
+ELF_RELOC(R_PPC_GOT_DTPREL16_HA,        94)
+ELF_RELOC(R_PPC_TLSGD,                  95)
+ELF_RELOC(R_PPC_TLSLD,                  96)
+ELF_RELOC(R_PPC_REL16,                  249)
+ELF_RELOC(R_PPC_REL16_LO,               250)
+ELF_RELOC(R_PPC_REL16_HI,               251)
+ELF_RELOC(R_PPC_REL16_HA,               252)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC64.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC64.def
new file mode 100644
index 0000000..3a47c5a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC64.def
@@ -0,0 +1,181 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// glibc's PowerPC asm/sigcontext.h, when compiling for PPC64, has the
+// unfortunate behavior of including asm/elf.h, which defines R_PPC_NONE, etc.
+// to their corresponding integer values. As a result, we need to undef them
+// here before continuing.
+
+#undef R_PPC64_NONE
+#undef R_PPC64_ADDR32
+#undef R_PPC64_ADDR24
+#undef R_PPC64_ADDR16
+#undef R_PPC64_ADDR16_LO
+#undef R_PPC64_ADDR16_HI
+#undef R_PPC64_ADDR16_HA
+#undef R_PPC64_ADDR14
+#undef R_PPC64_ADDR14_BRTAKEN
+#undef R_PPC64_ADDR14_BRNTAKEN
+#undef R_PPC64_REL24
+#undef R_PPC64_REL14
+#undef R_PPC64_REL14_BRTAKEN
+#undef R_PPC64_REL14_BRNTAKEN
+#undef R_PPC64_GOT16
+#undef R_PPC64_GOT16_LO
+#undef R_PPC64_GOT16_HI
+#undef R_PPC64_GOT16_HA
+#undef R_PPC64_GLOB_DAT
+#undef R_PPC64_JMP_SLOT
+#undef R_PPC64_RELATIVE
+#undef R_PPC64_REL32
+#undef R_PPC64_ADDR64
+#undef R_PPC64_ADDR16_HIGHER
+#undef R_PPC64_ADDR16_HIGHERA
+#undef R_PPC64_ADDR16_HIGHEST
+#undef R_PPC64_ADDR16_HIGHESTA
+#undef R_PPC64_REL64
+#undef R_PPC64_TOC16
+#undef R_PPC64_TOC16_LO
+#undef R_PPC64_TOC16_HI
+#undef R_PPC64_TOC16_HA
+#undef R_PPC64_TOC
+#undef R_PPC64_ADDR16_DS
+#undef R_PPC64_ADDR16_LO_DS
+#undef R_PPC64_GOT16_DS
+#undef R_PPC64_GOT16_LO_DS
+#undef R_PPC64_TOC16_DS
+#undef R_PPC64_TOC16_LO_DS
+#undef R_PPC64_TLS
+#undef R_PPC64_DTPMOD64
+#undef R_PPC64_TPREL16
+#undef R_PPC64_TPREL16_LO
+#undef R_PPC64_TPREL16_HI
+#undef R_PPC64_TPREL16_HA
+#undef R_PPC64_TPREL64
+#undef R_PPC64_DTPREL16
+#undef R_PPC64_DTPREL16_LO
+#undef R_PPC64_DTPREL16_HI
+#undef R_PPC64_DTPREL16_HA
+#undef R_PPC64_DTPREL64
+#undef R_PPC64_GOT_TLSGD16
+#undef R_PPC64_GOT_TLSGD16_LO
+#undef R_PPC64_GOT_TLSGD16_HI
+#undef R_PPC64_GOT_TLSGD16_HA
+#undef R_PPC64_GOT_TLSLD16
+#undef R_PPC64_GOT_TLSLD16_LO
+#undef R_PPC64_GOT_TLSLD16_HI
+#undef R_PPC64_GOT_TLSLD16_HA
+#undef R_PPC64_GOT_TPREL16_DS
+#undef R_PPC64_GOT_TPREL16_LO_DS
+#undef R_PPC64_GOT_TPREL16_HI
+#undef R_PPC64_GOT_TPREL16_HA
+#undef R_PPC64_GOT_DTPREL16_DS
+#undef R_PPC64_GOT_DTPREL16_LO_DS
+#undef R_PPC64_GOT_DTPREL16_HI
+#undef R_PPC64_GOT_DTPREL16_HA
+#undef R_PPC64_TPREL16_DS
+#undef R_PPC64_TPREL16_LO_DS
+#undef R_PPC64_TPREL16_HIGHER
+#undef R_PPC64_TPREL16_HIGHERA
+#undef R_PPC64_TPREL16_HIGHEST
+#undef R_PPC64_TPREL16_HIGHESTA
+#undef R_PPC64_DTPREL16_DS
+#undef R_PPC64_DTPREL16_LO_DS
+#undef R_PPC64_DTPREL16_HIGHER
+#undef R_PPC64_DTPREL16_HIGHERA
+#undef R_PPC64_DTPREL16_HIGHEST
+#undef R_PPC64_DTPREL16_HIGHESTA
+#undef R_PPC64_TLSGD
+#undef R_PPC64_TLSLD
+#undef R_PPC64_REL16
+#undef R_PPC64_REL16_LO
+#undef R_PPC64_REL16_HI
+#undef R_PPC64_REL16_HA
+
+ELF_RELOC(R_PPC64_NONE,                 0)
+ELF_RELOC(R_PPC64_ADDR32,               1)
+ELF_RELOC(R_PPC64_ADDR24,               2)
+ELF_RELOC(R_PPC64_ADDR16,               3)
+ELF_RELOC(R_PPC64_ADDR16_LO,            4)
+ELF_RELOC(R_PPC64_ADDR16_HI,            5)
+ELF_RELOC(R_PPC64_ADDR16_HA,            6)
+ELF_RELOC(R_PPC64_ADDR14,               7)
+ELF_RELOC(R_PPC64_ADDR14_BRTAKEN,       8)
+ELF_RELOC(R_PPC64_ADDR14_BRNTAKEN,      9)
+ELF_RELOC(R_PPC64_REL24,                10)
+ELF_RELOC(R_PPC64_REL14,                11)
+ELF_RELOC(R_PPC64_REL14_BRTAKEN,        12)
+ELF_RELOC(R_PPC64_REL14_BRNTAKEN,       13)
+ELF_RELOC(R_PPC64_GOT16,                14)
+ELF_RELOC(R_PPC64_GOT16_LO,             15)
+ELF_RELOC(R_PPC64_GOT16_HI,             16)
+ELF_RELOC(R_PPC64_GOT16_HA,             17)
+ELF_RELOC(R_PPC64_GLOB_DAT,             20)
+ELF_RELOC(R_PPC64_JMP_SLOT,             21)
+ELF_RELOC(R_PPC64_RELATIVE,             22)
+ELF_RELOC(R_PPC64_REL32,                26)
+ELF_RELOC(R_PPC64_ADDR64,               38)
+ELF_RELOC(R_PPC64_ADDR16_HIGHER,        39)
+ELF_RELOC(R_PPC64_ADDR16_HIGHERA,       40)
+ELF_RELOC(R_PPC64_ADDR16_HIGHEST,       41)
+ELF_RELOC(R_PPC64_ADDR16_HIGHESTA,      42)
+ELF_RELOC(R_PPC64_REL64,                44)
+ELF_RELOC(R_PPC64_TOC16,                47)
+ELF_RELOC(R_PPC64_TOC16_LO,             48)
+ELF_RELOC(R_PPC64_TOC16_HI,             49)
+ELF_RELOC(R_PPC64_TOC16_HA,             50)
+ELF_RELOC(R_PPC64_TOC,                  51)
+ELF_RELOC(R_PPC64_ADDR16_DS,            56)
+ELF_RELOC(R_PPC64_ADDR16_LO_DS,         57)
+ELF_RELOC(R_PPC64_GOT16_DS,             58)
+ELF_RELOC(R_PPC64_GOT16_LO_DS,          59)
+ELF_RELOC(R_PPC64_TOC16_DS,             63)
+ELF_RELOC(R_PPC64_TOC16_LO_DS,          64)
+ELF_RELOC(R_PPC64_TLS,                  67)
+ELF_RELOC(R_PPC64_DTPMOD64,             68)
+ELF_RELOC(R_PPC64_TPREL16,              69)
+ELF_RELOC(R_PPC64_TPREL16_LO,           70)
+ELF_RELOC(R_PPC64_TPREL16_HI,           71)
+ELF_RELOC(R_PPC64_TPREL16_HA,           72)
+ELF_RELOC(R_PPC64_TPREL64,              73)
+ELF_RELOC(R_PPC64_DTPREL16,             74)
+ELF_RELOC(R_PPC64_DTPREL16_LO,          75)
+ELF_RELOC(R_PPC64_DTPREL16_HI,          76)
+ELF_RELOC(R_PPC64_DTPREL16_HA,          77)
+ELF_RELOC(R_PPC64_DTPREL64,             78)
+ELF_RELOC(R_PPC64_GOT_TLSGD16,          79)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_LO,       80)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_HI,       81)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_HA,       82)
+ELF_RELOC(R_PPC64_GOT_TLSLD16,          83)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_LO,       84)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_HI,       85)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_HA,       86)
+ELF_RELOC(R_PPC64_GOT_TPREL16_DS,       87)
+ELF_RELOC(R_PPC64_GOT_TPREL16_LO_DS,    88)
+ELF_RELOC(R_PPC64_GOT_TPREL16_HI,       89)
+ELF_RELOC(R_PPC64_GOT_TPREL16_HA,       90)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_DS,      91)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_LO_DS,   92)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_HI,      93)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_HA,      94)
+ELF_RELOC(R_PPC64_TPREL16_DS,           95)
+ELF_RELOC(R_PPC64_TPREL16_LO_DS,        96)
+ELF_RELOC(R_PPC64_TPREL16_HIGHER,       97)
+ELF_RELOC(R_PPC64_TPREL16_HIGHERA,      98)
+ELF_RELOC(R_PPC64_TPREL16_HIGHEST,      99)
+ELF_RELOC(R_PPC64_TPREL16_HIGHESTA,     100)
+ELF_RELOC(R_PPC64_DTPREL16_DS,          101)
+ELF_RELOC(R_PPC64_DTPREL16_LO_DS,       102)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHER,      103)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHERA,     104)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHEST,     105)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHESTA,    106)
+ELF_RELOC(R_PPC64_TLSGD,                107)
+ELF_RELOC(R_PPC64_TLSLD,                108)
+ELF_RELOC(R_PPC64_REL16,                249)
+ELF_RELOC(R_PPC64_REL16_LO,             250)
+ELF_RELOC(R_PPC64_REL16_HI,             251)
+ELF_RELOC(R_PPC64_REL16_HA,             252)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Sparc.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Sparc.def
new file mode 100644
index 0000000..7e01a4a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Sparc.def
@@ -0,0 +1,89 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_SPARC_NONE,         0)
+ELF_RELOC(R_SPARC_8,            1)
+ELF_RELOC(R_SPARC_16,           2)
+ELF_RELOC(R_SPARC_32,           3)
+ELF_RELOC(R_SPARC_DISP8,        4)
+ELF_RELOC(R_SPARC_DISP16,       5)
+ELF_RELOC(R_SPARC_DISP32,       6)
+ELF_RELOC(R_SPARC_WDISP30,      7)
+ELF_RELOC(R_SPARC_WDISP22,      8)
+ELF_RELOC(R_SPARC_HI22,         9)
+ELF_RELOC(R_SPARC_22,           10)
+ELF_RELOC(R_SPARC_13,           11)
+ELF_RELOC(R_SPARC_LO10,         12)
+ELF_RELOC(R_SPARC_GOT10,        13)
+ELF_RELOC(R_SPARC_GOT13,        14)
+ELF_RELOC(R_SPARC_GOT22,        15)
+ELF_RELOC(R_SPARC_PC10,         16)
+ELF_RELOC(R_SPARC_PC22,         17)
+ELF_RELOC(R_SPARC_WPLT30,       18)
+ELF_RELOC(R_SPARC_COPY,         19)
+ELF_RELOC(R_SPARC_GLOB_DAT,     20)
+ELF_RELOC(R_SPARC_JMP_SLOT,     21)
+ELF_RELOC(R_SPARC_RELATIVE,     22)
+ELF_RELOC(R_SPARC_UA32,         23)
+ELF_RELOC(R_SPARC_PLT32,        24)
+ELF_RELOC(R_SPARC_HIPLT22,      25)
+ELF_RELOC(R_SPARC_LOPLT10,      26)
+ELF_RELOC(R_SPARC_PCPLT32,      27)
+ELF_RELOC(R_SPARC_PCPLT22,      28)
+ELF_RELOC(R_SPARC_PCPLT10,      29)
+ELF_RELOC(R_SPARC_10,           30)
+ELF_RELOC(R_SPARC_11,           31)
+ELF_RELOC(R_SPARC_64,           32)
+ELF_RELOC(R_SPARC_OLO10,        33)
+ELF_RELOC(R_SPARC_HH22,         34)
+ELF_RELOC(R_SPARC_HM10,         35)
+ELF_RELOC(R_SPARC_LM22,         36)
+ELF_RELOC(R_SPARC_PC_HH22,      37)
+ELF_RELOC(R_SPARC_PC_HM10,      38)
+ELF_RELOC(R_SPARC_PC_LM22,      39)
+ELF_RELOC(R_SPARC_WDISP16,      40)
+ELF_RELOC(R_SPARC_WDISP19,      41)
+ELF_RELOC(R_SPARC_7,            43)
+ELF_RELOC(R_SPARC_5,            44)
+ELF_RELOC(R_SPARC_6,            45)
+ELF_RELOC(R_SPARC_DISP64,       46)
+ELF_RELOC(R_SPARC_PLT64,        47)
+ELF_RELOC(R_SPARC_HIX22,        48)
+ELF_RELOC(R_SPARC_LOX10,        49)
+ELF_RELOC(R_SPARC_H44,          50)
+ELF_RELOC(R_SPARC_M44,          51)
+ELF_RELOC(R_SPARC_L44,          52)
+ELF_RELOC(R_SPARC_REGISTER,     53)
+ELF_RELOC(R_SPARC_UA64,         54)
+ELF_RELOC(R_SPARC_UA16,         55)
+ELF_RELOC(R_SPARC_TLS_GD_HI22,    56)
+ELF_RELOC(R_SPARC_TLS_GD_LO10,    57)
+ELF_RELOC(R_SPARC_TLS_GD_ADD,     58)
+ELF_RELOC(R_SPARC_TLS_GD_CALL,    59)
+ELF_RELOC(R_SPARC_TLS_LDM_HI22,   60)
+ELF_RELOC(R_SPARC_TLS_LDM_LO10,   61)
+ELF_RELOC(R_SPARC_TLS_LDM_ADD,    62)
+ELF_RELOC(R_SPARC_TLS_LDM_CALL,   63)
+ELF_RELOC(R_SPARC_TLS_LDO_HIX22,  64)
+ELF_RELOC(R_SPARC_TLS_LDO_LOX10,  65)
+ELF_RELOC(R_SPARC_TLS_LDO_ADD,    66)
+ELF_RELOC(R_SPARC_TLS_IE_HI22,    67)
+ELF_RELOC(R_SPARC_TLS_IE_LO10,    68)
+ELF_RELOC(R_SPARC_TLS_IE_LD,      69)
+ELF_RELOC(R_SPARC_TLS_IE_LDX,     70)
+ELF_RELOC(R_SPARC_TLS_IE_ADD,     71)
+ELF_RELOC(R_SPARC_TLS_LE_HIX22,   72)
+ELF_RELOC(R_SPARC_TLS_LE_LOX10,   73)
+ELF_RELOC(R_SPARC_TLS_DTPMOD32,   74)
+ELF_RELOC(R_SPARC_TLS_DTPMOD64,   75)
+ELF_RELOC(R_SPARC_TLS_DTPOFF32,   76)
+ELF_RELOC(R_SPARC_TLS_DTPOFF64,   77)
+ELF_RELOC(R_SPARC_TLS_TPOFF32,    78)
+ELF_RELOC(R_SPARC_TLS_TPOFF64,    79)
+ELF_RELOC(R_SPARC_GOTDATA_HIX22,  80)
+ELF_RELOC(R_SPARC_GOTDATA_LOX10,  81)
+ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22,  82)
+ELF_RELOC(R_SPARC_GOTDATA_OP_LOX10,  83)
+ELF_RELOC(R_SPARC_GOTDATA_OP,     84)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/SystemZ.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/SystemZ.def
new file mode 100644
index 0000000..711f940
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/SystemZ.def
@@ -0,0 +1,67 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_390_NONE,          0)
+ELF_RELOC(R_390_8,             1)
+ELF_RELOC(R_390_12,            2)
+ELF_RELOC(R_390_16,            3)
+ELF_RELOC(R_390_32,            4)
+ELF_RELOC(R_390_PC32,          5)
+ELF_RELOC(R_390_GOT12,         6)
+ELF_RELOC(R_390_GOT32,         7)
+ELF_RELOC(R_390_PLT32,         8)
+ELF_RELOC(R_390_COPY,          9)
+ELF_RELOC(R_390_GLOB_DAT,     10)
+ELF_RELOC(R_390_JMP_SLOT,     11)
+ELF_RELOC(R_390_RELATIVE,     12)
+ELF_RELOC(R_390_GOTOFF,       13)
+ELF_RELOC(R_390_GOTPC,        14)
+ELF_RELOC(R_390_GOT16,        15)
+ELF_RELOC(R_390_PC16,         16)
+ELF_RELOC(R_390_PC16DBL,      17)
+ELF_RELOC(R_390_PLT16DBL,     18)
+ELF_RELOC(R_390_PC32DBL,      19)
+ELF_RELOC(R_390_PLT32DBL,     20)
+ELF_RELOC(R_390_GOTPCDBL,     21)
+ELF_RELOC(R_390_64,           22)
+ELF_RELOC(R_390_PC64,         23)
+ELF_RELOC(R_390_GOT64,        24)
+ELF_RELOC(R_390_PLT64,        25)
+ELF_RELOC(R_390_GOTENT,       26)
+ELF_RELOC(R_390_GOTOFF16,     27)
+ELF_RELOC(R_390_GOTOFF64,     28)
+ELF_RELOC(R_390_GOTPLT12,     29)
+ELF_RELOC(R_390_GOTPLT16,     30)
+ELF_RELOC(R_390_GOTPLT32,     31)
+ELF_RELOC(R_390_GOTPLT64,     32)
+ELF_RELOC(R_390_GOTPLTENT,    33)
+ELF_RELOC(R_390_PLTOFF16,     34)
+ELF_RELOC(R_390_PLTOFF32,     35)
+ELF_RELOC(R_390_PLTOFF64,     36)
+ELF_RELOC(R_390_TLS_LOAD,     37)
+ELF_RELOC(R_390_TLS_GDCALL,   38)
+ELF_RELOC(R_390_TLS_LDCALL,   39)
+ELF_RELOC(R_390_TLS_GD32,     40)
+ELF_RELOC(R_390_TLS_GD64,     41)
+ELF_RELOC(R_390_TLS_GOTIE12,  42)
+ELF_RELOC(R_390_TLS_GOTIE32,  43)
+ELF_RELOC(R_390_TLS_GOTIE64,  44)
+ELF_RELOC(R_390_TLS_LDM32,    45)
+ELF_RELOC(R_390_TLS_LDM64,    46)
+ELF_RELOC(R_390_TLS_IE32,     47)
+ELF_RELOC(R_390_TLS_IE64,     48)
+ELF_RELOC(R_390_TLS_IEENT,    49)
+ELF_RELOC(R_390_TLS_LE32,     50)
+ELF_RELOC(R_390_TLS_LE64,     51)
+ELF_RELOC(R_390_TLS_LDO32,    52)
+ELF_RELOC(R_390_TLS_LDO64,    53)
+ELF_RELOC(R_390_TLS_DTPMOD,   54)
+ELF_RELOC(R_390_TLS_DTPOFF,   55)
+ELF_RELOC(R_390_TLS_TPOFF,    56)
+ELF_RELOC(R_390_20,           57)
+ELF_RELOC(R_390_GOT20,        58)
+ELF_RELOC(R_390_GOTPLT20,     59)
+ELF_RELOC(R_390_TLS_GOTIE20,  60)
+ELF_RELOC(R_390_IRELATIVE,    61)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/WebAssembly.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/WebAssembly.def
new file mode 100644
index 0000000..9a34349
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/WebAssembly.def
@@ -0,0 +1,8 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_WEBASSEMBLY_NONE,          0)
+ELF_RELOC(R_WEBASSEMBLY_DATA,          1)
+ELF_RELOC(R_WEBASSEMBLY_FUNCTION,      2)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/i386.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/i386.def
new file mode 100644
index 0000000..1d28cf5
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/i386.def
@@ -0,0 +1,47 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// TODO: this is just a subset
+ELF_RELOC(R_386_NONE,           0)
+ELF_RELOC(R_386_32,             1)
+ELF_RELOC(R_386_PC32,           2)
+ELF_RELOC(R_386_GOT32,          3)
+ELF_RELOC(R_386_PLT32,          4)
+ELF_RELOC(R_386_COPY,           5)
+ELF_RELOC(R_386_GLOB_DAT,       6)
+ELF_RELOC(R_386_JUMP_SLOT,      7)
+ELF_RELOC(R_386_RELATIVE,       8)
+ELF_RELOC(R_386_GOTOFF,         9)
+ELF_RELOC(R_386_GOTPC,          10)
+ELF_RELOC(R_386_32PLT,          11)
+ELF_RELOC(R_386_TLS_TPOFF,      14)
+ELF_RELOC(R_386_TLS_IE,         15)
+ELF_RELOC(R_386_TLS_GOTIE,      16)
+ELF_RELOC(R_386_TLS_LE,         17)
+ELF_RELOC(R_386_TLS_GD,         18)
+ELF_RELOC(R_386_TLS_LDM,        19)
+ELF_RELOC(R_386_16,             20)
+ELF_RELOC(R_386_PC16,           21)
+ELF_RELOC(R_386_8,              22)
+ELF_RELOC(R_386_PC8,            23)
+ELF_RELOC(R_386_TLS_GD_32,      24)
+ELF_RELOC(R_386_TLS_GD_PUSH,    25)
+ELF_RELOC(R_386_TLS_GD_CALL,    26)
+ELF_RELOC(R_386_TLS_GD_POP,     27)
+ELF_RELOC(R_386_TLS_LDM_32,     28)
+ELF_RELOC(R_386_TLS_LDM_PUSH,   29)
+ELF_RELOC(R_386_TLS_LDM_CALL,   30)
+ELF_RELOC(R_386_TLS_LDM_POP,    31)
+ELF_RELOC(R_386_TLS_LDO_32,     32)
+ELF_RELOC(R_386_TLS_IE_32,      33)
+ELF_RELOC(R_386_TLS_LE_32,      34)
+ELF_RELOC(R_386_TLS_DTPMOD32,   35)
+ELF_RELOC(R_386_TLS_DTPOFF32,   36)
+ELF_RELOC(R_386_TLS_TPOFF32,    37)
+ELF_RELOC(R_386_TLS_GOTDESC,    39)
+ELF_RELOC(R_386_TLS_DESC_CALL,  40)
+ELF_RELOC(R_386_TLS_DESC,       41)
+ELF_RELOC(R_386_IRELATIVE,      42)
+ELF_RELOC(R_386_GOT32X,         43)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/x86_64.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/x86_64.def
new file mode 100644
index 0000000..18fdcf9
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/x86_64.def
@@ -0,0 +1,45 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_X86_64_NONE,        0)
+ELF_RELOC(R_X86_64_64,          1)
+ELF_RELOC(R_X86_64_PC32,        2)
+ELF_RELOC(R_X86_64_GOT32,       3)
+ELF_RELOC(R_X86_64_PLT32,       4)
+ELF_RELOC(R_X86_64_COPY,        5)
+ELF_RELOC(R_X86_64_GLOB_DAT,    6)
+ELF_RELOC(R_X86_64_JUMP_SLOT,   7)
+ELF_RELOC(R_X86_64_RELATIVE,    8)
+ELF_RELOC(R_X86_64_GOTPCREL,    9)
+ELF_RELOC(R_X86_64_32,          10)
+ELF_RELOC(R_X86_64_32S,         11)
+ELF_RELOC(R_X86_64_16,          12)
+ELF_RELOC(R_X86_64_PC16,        13)
+ELF_RELOC(R_X86_64_8,           14)
+ELF_RELOC(R_X86_64_PC8,         15)
+ELF_RELOC(R_X86_64_DTPMOD64,    16)
+ELF_RELOC(R_X86_64_DTPOFF64,    17)
+ELF_RELOC(R_X86_64_TPOFF64,     18)
+ELF_RELOC(R_X86_64_TLSGD,       19)
+ELF_RELOC(R_X86_64_TLSLD,       20)
+ELF_RELOC(R_X86_64_DTPOFF32,    21)
+ELF_RELOC(R_X86_64_GOTTPOFF,    22)
+ELF_RELOC(R_X86_64_TPOFF32,     23)
+ELF_RELOC(R_X86_64_PC64,        24)
+ELF_RELOC(R_X86_64_GOTOFF64,    25)
+ELF_RELOC(R_X86_64_GOTPC32,     26)
+ELF_RELOC(R_X86_64_GOT64,       27)
+ELF_RELOC(R_X86_64_GOTPCREL64,  28)
+ELF_RELOC(R_X86_64_GOTPC64,     29)
+ELF_RELOC(R_X86_64_GOTPLT64,    30)
+ELF_RELOC(R_X86_64_PLTOFF64,    31)
+ELF_RELOC(R_X86_64_SIZE32,      32)
+ELF_RELOC(R_X86_64_SIZE64,      33)
+ELF_RELOC(R_X86_64_GOTPC32_TLSDESC,  34)
+ELF_RELOC(R_X86_64_TLSDESC_CALL,     35)
+ELF_RELOC(R_X86_64_TLSDESC,     36)
+ELF_RELOC(R_X86_64_IRELATIVE,   37)
+ELF_RELOC(R_X86_64_GOTPCRELX,   41)
+ELF_RELOC(R_X86_64_REX_GOTPCRELX,    42)
diff --git a/third_party/llvm-subzero/include/llvm/Support/Endian.h b/third_party/llvm-subzero/include/llvm/Support/Endian.h
new file mode 100644
index 0000000..cb5cd8e
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Endian.h
@@ -0,0 +1,349 @@
+//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares generic functions to read and write endian specific data.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ENDIAN_H
+#define LLVM_SUPPORT_ENDIAN_H
+
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/SwapByteOrder.h"
+
+namespace llvm {
+namespace support {
+enum endianness {big, little, native};
+
+// These are named values for common alignments.
+enum {aligned = 0, unaligned = 1};
+
+namespace detail {
+  /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
+  template<class T, int alignment>
+  struct PickAlignment {
+    enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
+  };
+} // end namespace detail
+
+namespace endian {
+/// Swap the bytes of value to match the given endianness.
+template<typename value_type, endianness endian>
+inline value_type byte_swap(value_type value) {
+  if (endian != native && sys::IsBigEndianHost != (endian == big))
+    sys::swapByteOrder(value);
+  return value;
+}
+
+/// Read a value of a particular endianness from memory.
+template<typename value_type,
+         endianness endian,
+         std::size_t alignment>
+inline value_type read(const void *memory) {
+  value_type ret;
+
+  memcpy(&ret,
+         LLVM_ASSUME_ALIGNED(memory,
+           (detail::PickAlignment<value_type, alignment>::value)),
+         sizeof(value_type));
+  return byte_swap<value_type, endian>(ret);
+}
+
+/// Read a value of a particular endianness from a buffer, and increment the
+/// buffer past that value.
+template<typename value_type, endianness endian, std::size_t alignment,
+         typename CharT>
+inline value_type readNext(const CharT *&memory) {
+  value_type ret = read<value_type, endian, alignment>(memory);
+  memory += sizeof(value_type);
+  return ret;
+}
+
+/// Write a value to memory with a particular endianness.
+template<typename value_type,
+         endianness endian,
+         std::size_t alignment>
+inline void write(void *memory, value_type value) {
+  value = byte_swap<value_type, endian>(value);
+  memcpy(LLVM_ASSUME_ALIGNED(memory,
+           (detail::PickAlignment<value_type, alignment>::value)),
+         &value,
+         sizeof(value_type));
+}
+
+template <typename value_type>
+using make_unsigned_t = typename std::make_unsigned<value_type>::type;
+
+/// Read a value of a particular endianness from memory, for a location
+/// that starts at the given bit offset within the first byte.
+template <typename value_type, endianness endian, std::size_t alignment>
+inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
+  assert(startBit < 8);
+  if (startBit == 0)
+    return read<value_type, endian, alignment>(memory);
+  else {
+    // Read two values and compose the result from them.
+    value_type val[2];
+    memcpy(&val[0],
+           LLVM_ASSUME_ALIGNED(
+               memory, (detail::PickAlignment<value_type, alignment>::value)),
+           sizeof(value_type) * 2);
+    val[0] = byte_swap<value_type, endian>(val[0]);
+    val[1] = byte_swap<value_type, endian>(val[1]);
+
+    // Shift bits from the lower value into place.
+    make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
+    // Mask off upper bits after right shift in case of signed type.
+    make_unsigned_t<value_type> numBitsFirstVal =
+        (sizeof(value_type) * 8) - startBit;
+    lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
+
+    // Get the bits from the upper value.
+    make_unsigned_t<value_type> upperVal =
+        val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1);
+    // Shift them in to place.
+    upperVal <<= numBitsFirstVal;
+
+    return lowerVal | upperVal;
+  }
+}
+
+/// Write a value to memory with a particular endianness, for a location
+/// that starts at the given bit offset within the first byte.
+template <typename value_type, endianness endian, std::size_t alignment>
+inline void writeAtBitAlignment(void *memory, value_type value,
+                                uint64_t startBit) {
+  assert(startBit < 8);
+  if (startBit == 0)
+    write<value_type, endian, alignment>(memory, value);
+  else {
+    // Read two values and shift the result into them.
+    value_type val[2];
+    memcpy(&val[0],
+           LLVM_ASSUME_ALIGNED(
+               memory, (detail::PickAlignment<value_type, alignment>::value)),
+           sizeof(value_type) * 2);
+    val[0] = byte_swap<value_type, endian>(val[0]);
+    val[1] = byte_swap<value_type, endian>(val[1]);
+
+    // Mask off any existing bits in the upper part of the lower value that
+    // we want to replace.
+    val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
+    make_unsigned_t<value_type> numBitsFirstVal =
+        (sizeof(value_type) * 8) - startBit;
+    make_unsigned_t<value_type> lowerVal = value;
+    if (startBit > 0) {
+      // Mask off the upper bits in the new value that are not going to go into
+      // the lower value. This avoids a left shift of a negative value, which
+      // is undefined behavior.
+      lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
+      // Now shift the new bits into place
+      lowerVal <<= startBit;
+    }
+    val[0] |= lowerVal;
+
+    // Mask off any existing bits in the lower part of the upper value that
+    // we want to replace.
+    val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1);
+    // Next shift the bits that go into the upper value into position.
+    make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
+    // Mask off upper bits after right shift in case of signed type.
+    upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
+    val[1] |= upperVal;
+
+    // Finally, rewrite values.
+    val[0] = byte_swap<value_type, endian>(val[0]);
+    val[1] = byte_swap<value_type, endian>(val[1]);
+    memcpy(LLVM_ASSUME_ALIGNED(
+               memory, (detail::PickAlignment<value_type, alignment>::value)),
+           &val[0], sizeof(value_type) * 2);
+  }
+}
+} // end namespace endian
+
+namespace detail {
+template<typename value_type,
+         endianness endian,
+         std::size_t alignment>
+struct packed_endian_specific_integral {
+  packed_endian_specific_integral() = default;
+
+  explicit packed_endian_specific_integral(value_type val) { *this = val; }
+
+  operator value_type() const {
+    return endian::read<value_type, endian, alignment>(
+      (const void*)Value.buffer);
+  }
+
+  void operator=(value_type newValue) {
+    endian::write<value_type, endian, alignment>(
+      (void*)Value.buffer, newValue);
+  }
+
+  packed_endian_specific_integral &operator+=(value_type newValue) {
+    *this = *this + newValue;
+    return *this;
+  }
+
+  packed_endian_specific_integral &operator-=(value_type newValue) {
+    *this = *this - newValue;
+    return *this;
+  }
+
+  packed_endian_specific_integral &operator|=(value_type newValue) {
+    *this = *this | newValue;
+    return *this;
+  }
+
+  packed_endian_specific_integral &operator&=(value_type newValue) {
+    *this = *this & newValue;
+    return *this;
+  }
+
+private:
+  AlignedCharArray<PickAlignment<value_type, alignment>::value,
+                   sizeof(value_type)> Value;
+
+public:
+  struct ref {
+    explicit ref(void *Ptr) : Ptr(Ptr) {}
+
+    operator value_type() const {
+      return endian::read<value_type, endian, alignment>(Ptr);
+    }
+
+    void operator=(value_type NewValue) {
+      endian::write<value_type, endian, alignment>(Ptr, NewValue);
+    }
+
+  private:
+    void *Ptr;
+  };
+};
+
+} // end namespace detail
+
+typedef detail::packed_endian_specific_integral
+                  <uint16_t, little, unaligned> ulittle16_t;
+typedef detail::packed_endian_specific_integral
+                  <uint32_t, little, unaligned> ulittle32_t;
+typedef detail::packed_endian_specific_integral
+                  <uint64_t, little, unaligned> ulittle64_t;
+
+typedef detail::packed_endian_specific_integral
+                   <int16_t, little, unaligned> little16_t;
+typedef detail::packed_endian_specific_integral
+                   <int32_t, little, unaligned> little32_t;
+typedef detail::packed_endian_specific_integral
+                   <int64_t, little, unaligned> little64_t;
+
+typedef detail::packed_endian_specific_integral
+                    <uint16_t, little, aligned> aligned_ulittle16_t;
+typedef detail::packed_endian_specific_integral
+                    <uint32_t, little, aligned> aligned_ulittle32_t;
+typedef detail::packed_endian_specific_integral
+                    <uint64_t, little, aligned> aligned_ulittle64_t;
+
+typedef detail::packed_endian_specific_integral
+                     <int16_t, little, aligned> aligned_little16_t;
+typedef detail::packed_endian_specific_integral
+                     <int32_t, little, aligned> aligned_little32_t;
+typedef detail::packed_endian_specific_integral
+                     <int64_t, little, aligned> aligned_little64_t;
+
+typedef detail::packed_endian_specific_integral
+                  <uint16_t, big, unaligned>    ubig16_t;
+typedef detail::packed_endian_specific_integral
+                  <uint32_t, big, unaligned>    ubig32_t;
+typedef detail::packed_endian_specific_integral
+                  <uint64_t, big, unaligned>    ubig64_t;
+
+typedef detail::packed_endian_specific_integral
+                   <int16_t, big, unaligned>    big16_t;
+typedef detail::packed_endian_specific_integral
+                   <int32_t, big, unaligned>    big32_t;
+typedef detail::packed_endian_specific_integral
+                   <int64_t, big, unaligned>    big64_t;
+
+typedef detail::packed_endian_specific_integral
+                    <uint16_t, big, aligned>    aligned_ubig16_t;
+typedef detail::packed_endian_specific_integral
+                    <uint32_t, big, aligned>    aligned_ubig32_t;
+typedef detail::packed_endian_specific_integral
+                    <uint64_t, big, aligned>    aligned_ubig64_t;
+
+typedef detail::packed_endian_specific_integral
+                     <int16_t, big, aligned>    aligned_big16_t;
+typedef detail::packed_endian_specific_integral
+                     <int32_t, big, aligned>    aligned_big32_t;
+typedef detail::packed_endian_specific_integral
+                     <int64_t, big, aligned>    aligned_big64_t;
+
+typedef detail::packed_endian_specific_integral
+                  <uint16_t, native, unaligned> unaligned_uint16_t;
+typedef detail::packed_endian_specific_integral
+                  <uint32_t, native, unaligned> unaligned_uint32_t;
+typedef detail::packed_endian_specific_integral
+                  <uint64_t, native, unaligned> unaligned_uint64_t;
+
+typedef detail::packed_endian_specific_integral
+                   <int16_t, native, unaligned> unaligned_int16_t;
+typedef detail::packed_endian_specific_integral
+                   <int32_t, native, unaligned> unaligned_int32_t;
+typedef detail::packed_endian_specific_integral
+                   <int64_t, native, unaligned> unaligned_int64_t;
+
+namespace endian {
+template <typename T, endianness E> inline T read(const void *P) {
+  return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
+}
+
+template <endianness E> inline uint16_t read16(const void *P) {
+  return read<uint16_t, E>(P);
+}
+template <endianness E> inline uint32_t read32(const void *P) {
+  return read<uint32_t, E>(P);
+}
+template <endianness E> inline uint64_t read64(const void *P) {
+  return read<uint64_t, E>(P);
+}
+
+inline uint16_t read16le(const void *P) { return read16<little>(P); }
+inline uint32_t read32le(const void *P) { return read32<little>(P); }
+inline uint64_t read64le(const void *P) { return read64<little>(P); }
+inline uint16_t read16be(const void *P) { return read16<big>(P); }
+inline uint32_t read32be(const void *P) { return read32<big>(P); }
+inline uint64_t read64be(const void *P) { return read64<big>(P); }
+
+template <typename T, endianness E> inline void write(void *P, T V) {
+  *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
+}
+
+template <endianness E> inline void write16(void *P, uint16_t V) {
+  write<uint16_t, E>(P, V);
+}
+template <endianness E> inline void write32(void *P, uint32_t V) {
+  write<uint32_t, E>(P, V);
+}
+template <endianness E> inline void write64(void *P, uint64_t V) {
+  write<uint64_t, E>(P, V);
+}
+
+inline void write16le(void *P, uint16_t V) { write16<little>(P, V); }
+inline void write32le(void *P, uint32_t V) { write32<little>(P, V); }
+inline void write64le(void *P, uint64_t V) { write64<little>(P, V); }
+inline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
+inline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
+inline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
+} // end namespace endian
+} // end namespace support
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Errc.h b/third_party/llvm-subzero/include/llvm/Support/Errc.h
new file mode 100644
index 0000000..80bfe2a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Errc.h
@@ -0,0 +1,86 @@
+//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// While std::error_code works OK on all platforms we use, there are some
+// some problems with std::errc that can be avoided by using our own
+// enumeration:
+//
+// * std::errc is a namespace in some implementations. That meas that ADL
+//   doesn't work and it is sometimes necessary to write std::make_error_code
+//   or in templates:
+//   using std::make_error_code;
+//   make_error_code(...);
+//
+//   with this enum it is safe to always just use make_error_code.
+//
+// * Some implementations define fewer names than others. This header has
+//   the intersection of all the ones we support.
+//
+// * std::errc is just marked with is_error_condition_enum. This means that
+//   common patters like AnErrorCode == errc::no_such_file_or_directory take
+//   4 virtual calls instead of two comparisons.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERRC_H
+#define LLVM_SUPPORT_ERRC_H
+
+#include <system_error>
+
+namespace llvm {
+enum class errc {
+  argument_list_too_long = int(std::errc::argument_list_too_long),
+  argument_out_of_domain = int(std::errc::argument_out_of_domain),
+  bad_address = int(std::errc::bad_address),
+  bad_file_descriptor = int(std::errc::bad_file_descriptor),
+  broken_pipe = int(std::errc::broken_pipe),
+  device_or_resource_busy = int(std::errc::device_or_resource_busy),
+  directory_not_empty = int(std::errc::directory_not_empty),
+  executable_format_error = int(std::errc::executable_format_error),
+  file_exists = int(std::errc::file_exists),
+  file_too_large = int(std::errc::file_too_large),
+  filename_too_long = int(std::errc::filename_too_long),
+  function_not_supported = int(std::errc::function_not_supported),
+  illegal_byte_sequence = int(std::errc::illegal_byte_sequence),
+  inappropriate_io_control_operation =
+      int(std::errc::inappropriate_io_control_operation),
+  interrupted = int(std::errc::interrupted),
+  invalid_argument = int(std::errc::invalid_argument),
+  invalid_seek = int(std::errc::invalid_seek),
+  io_error = int(std::errc::io_error),
+  is_a_directory = int(std::errc::is_a_directory),
+  no_child_process = int(std::errc::no_child_process),
+  no_lock_available = int(std::errc::no_lock_available),
+  no_space_on_device = int(std::errc::no_space_on_device),
+  no_such_device_or_address = int(std::errc::no_such_device_or_address),
+  no_such_device = int(std::errc::no_such_device),
+  no_such_file_or_directory = int(std::errc::no_such_file_or_directory),
+  no_such_process = int(std::errc::no_such_process),
+  not_a_directory = int(std::errc::not_a_directory),
+  not_enough_memory = int(std::errc::not_enough_memory),
+  operation_not_permitted = int(std::errc::operation_not_permitted),
+  permission_denied = int(std::errc::permission_denied),
+  read_only_file_system = int(std::errc::read_only_file_system),
+  resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur),
+  resource_unavailable_try_again =
+      int(std::errc::resource_unavailable_try_again),
+  result_out_of_range = int(std::errc::result_out_of_range),
+  too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system),
+  too_many_files_open = int(std::errc::too_many_files_open),
+  too_many_links = int(std::errc::too_many_links)
+};
+
+inline std::error_code make_error_code(errc E) {
+  return std::error_code(static_cast<int>(E), std::generic_category());
+}
+}
+
+namespace std {
+template <> struct is_error_code_enum<llvm::errc> : std::true_type {};
+}
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Errno.h b/third_party/llvm-subzero/include/llvm/Support/Errno.h
new file mode 100644
index 0000000..8e145c7
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Errno.h
@@ -0,0 +1,34 @@
+//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares some portable and convenient functions to deal with errno.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERRNO_H
+#define LLVM_SUPPORT_ERRNO_H
+
+#include <string>
+
+namespace llvm {
+namespace sys {
+
+/// Returns a string representation of the errno value, using whatever
+/// thread-safe variant of strerror() is available.  Be sure to call this
+/// immediately after the function that set errno, or errno may have been
+/// overwritten by an intervening call.
+std::string StrError();
+
+/// Like the no-argument version above, but uses \p errnum instead of errno.
+std::string StrError(int errnum);
+
+}  // namespace sys
+}  // namespace llvm
+
+#endif  // LLVM_SYSTEM_ERRNO_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Error.h b/third_party/llvm-subzero/include/llvm/Support/Error.h
new file mode 100644
index 0000000..afd2660
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Error.h
@@ -0,0 +1,964 @@
+//===----- llvm/Support/Error.h - Recoverable error handling ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an API used to report recoverable errors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERROR_H
+#define LLVM_SUPPORT_ERROR_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+namespace llvm {
+
+class Error;
+class ErrorList;
+
+/// Base class for error info classes. Do not extend this directly: Extend
+/// the ErrorInfo template subclass instead.
+class ErrorInfoBase {
+public:
+  virtual ~ErrorInfoBase() {}
+
+  /// Print an error message to an output stream.
+  virtual void log(raw_ostream &OS) const = 0;
+
+  /// Return the error message as a string.
+  virtual std::string message() const {
+    std::string Msg;
+    raw_string_ostream OS(Msg);
+    log(OS);
+    return OS.str();
+  }
+
+  /// Convert this error to a std::error_code.
+  ///
+  /// This is a temporary crutch to enable interaction with code still
+  /// using std::error_code. It will be removed in the future.
+  virtual std::error_code convertToErrorCode() const = 0;
+
+  // Check whether this instance is a subclass of the class identified by
+  // ClassID.
+  virtual bool isA(const void *const ClassID) const {
+    return ClassID == classID();
+  }
+
+  // Check whether this instance is a subclass of ErrorInfoT.
+  template <typename ErrorInfoT> bool isA() const {
+    return isA(ErrorInfoT::classID());
+  }
+
+  // Returns the class ID for this type.
+  static const void *classID() { return &ID; }
+
+private:
+  virtual void anchor();
+  static char ID;
+};
+
+/// Lightweight error class with error context and mandatory checking.
+///
+/// Instances of this class wrap a ErrorInfoBase pointer. Failure states
+/// are represented by setting the pointer to a ErrorInfoBase subclass
+/// instance containing information describing the failure. Success is
+/// represented by a null pointer value.
+///
+/// Instances of Error also contains a 'Checked' flag, which must be set
+/// before the destructor is called, otherwise the destructor will trigger a
+/// runtime error. This enforces at runtime the requirement that all Error
+/// instances be checked or returned to the caller.
+///
+/// There are two ways to set the checked flag, depending on what state the
+/// Error instance is in. For Error instances indicating success, it
+/// is sufficient to invoke the boolean conversion operator. E.g.:
+///
+///   @code{.cpp}
+///   Error foo(<...>);
+///
+///   if (auto E = foo(<...>))
+///     return E; // <- Return E if it is in the error state.
+///   // We have verified that E was in the success state. It can now be safely
+///   // destroyed.
+///   @endcode
+///
+/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
+/// without testing the return value will raise a runtime error, even if foo
+/// returns success.
+///
+/// For Error instances representing failure, you must use either the
+/// handleErrors or handleAllErrors function with a typed handler. E.g.:
+///
+///   @code{.cpp}
+///   class MyErrorInfo : public ErrorInfo<MyErrorInfo> {
+///     // Custom error info.
+///   };
+///
+///   Error foo(<...>) { return make_error<MyErrorInfo>(...); }
+///
+///   auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
+///   auto NewE =
+///     handleErrors(E,
+///       [](const MyErrorInfo &M) {
+///         // Deal with the error.
+///       },
+///       [](std::unique_ptr<OtherError> M) -> Error {
+///         if (canHandle(*M)) {
+///           // handle error.
+///           return Error::success();
+///         }
+///         // Couldn't handle this error instance. Pass it up the stack.
+///         return Error(std::move(M));
+///       );
+///   // Note - we must check or return NewE in case any of the handlers
+///   // returned a new error.
+///   @endcode
+///
+/// The handleAllErrors function is identical to handleErrors, except
+/// that it has a void return type, and requires all errors to be handled and
+/// no new errors be returned. It prevents errors (assuming they can all be
+/// handled) from having to be bubbled all the way to the top-level.
+///
+/// *All* Error instances must be checked before destruction, even if
+/// they're moved-assigned or constructed from Success values that have already
+/// been checked. This enforces checking through all levels of the call stack.
+class Error {
+
+  // ErrorList needs to be able to yank ErrorInfoBase pointers out of this
+  // class to add to the error list.
+  friend class ErrorList;
+
+  // handleErrors needs to be able to set the Checked flag.
+  template <typename... HandlerTs>
+  friend Error handleErrors(Error E, HandlerTs &&... Handlers);
+
+  // Expected<T> needs to be able to steal the payload when constructed from an
+  // error.
+  template <typename T> class Expected;
+
+public:
+  /// Create a success value. Prefer using 'Error::success()' for readability
+  /// where possible.
+  Error() {
+    setPtr(nullptr);
+    setChecked(false);
+  }
+
+  /// Create a success value. This is equivalent to calling the default
+  /// constructor, but should be preferred for readability where possible.
+  static Error success() { return Error(); }
+
+  // Errors are not copy-constructable.
+  Error(const Error &Other) = delete;
+
+  /// Move-construct an error value. The newly constructed error is considered
+  /// unchecked, even if the source error had been checked. The original error
+  /// becomes a checked Success value, regardless of its original state.
+  Error(Error &&Other) {
+    setChecked(true);
+    *this = std::move(Other);
+  }
+
+  /// Create an error value. Prefer using the 'make_error' function, but
+  /// this constructor can be useful when "re-throwing" errors from handlers.
+  Error(std::unique_ptr<ErrorInfoBase> Payload) {
+    setPtr(Payload.release());
+    setChecked(false);
+  }
+
+  // Errors are not copy-assignable.
+  Error &operator=(const Error &Other) = delete;
+
+  /// Move-assign an error value. The current error must represent success, you
+  /// you cannot overwrite an unhandled error. The current error is then
+  /// considered unchecked. The source error becomes a checked success value,
+  /// regardless of its original state.
+  Error &operator=(Error &&Other) {
+    // Don't allow overwriting of unchecked values.
+    assertIsChecked();
+    setPtr(Other.getPtr());
+
+    // This Error is unchecked, even if the source error was checked.
+    setChecked(false);
+
+    // Null out Other's payload and set its checked bit.
+    Other.setPtr(nullptr);
+    Other.setChecked(true);
+
+    return *this;
+  }
+
+  /// Destroy a Error. Fails with a call to abort() if the error is
+  /// unchecked.
+  ~Error() {
+    assertIsChecked();
+    delete getPtr();
+  }
+
+  /// Bool conversion. Returns true if this Error is in a failure state,
+  /// and false if it is in an accept state. If the error is in a Success state
+  /// it will be considered checked.
+  explicit operator bool() {
+    setChecked(getPtr() == nullptr);
+    return getPtr() != nullptr;
+  }
+
+  /// Check whether one error is a subclass of another.
+  template <typename ErrT> bool isA() const {
+    return getPtr() && getPtr()->isA(ErrT::classID());
+  }
+
+private:
+  void assertIsChecked() {
+#ifndef NDEBUG
+    if (!getChecked() || getPtr()) {
+      dbgs() << "Program aborted due to an unhandled Error:\n";
+      if (getPtr())
+        getPtr()->log(dbgs());
+      else
+        dbgs()
+            << "Error value was Success. (Note: Success values must still be "
+               "checked prior to being destroyed).\n";
+      abort();
+    }
+#endif
+  }
+
+  ErrorInfoBase *getPtr() const {
+#ifndef NDEBUG
+    return PayloadAndCheckedBit.getPointer();
+#else
+    return Payload;
+#endif
+  }
+
+  void setPtr(ErrorInfoBase *EI) {
+#ifndef NDEBUG
+    PayloadAndCheckedBit.setPointer(EI);
+#else
+    Payload = EI;
+#endif
+  }
+
+  bool getChecked() const {
+#ifndef NDEBUG
+    return PayloadAndCheckedBit.getInt();
+#else
+    return true;
+#endif
+  }
+
+  void setChecked(bool V) {
+#ifndef NDEBUG
+    PayloadAndCheckedBit.setInt(V);
+#endif
+  }
+
+  std::unique_ptr<ErrorInfoBase> takePayload() {
+    std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
+    setPtr(nullptr);
+    setChecked(true);
+    return Tmp;
+  }
+
+#ifndef NDEBUG
+  PointerIntPair<ErrorInfoBase *, 1> PayloadAndCheckedBit;
+#else
+  ErrorInfoBase *Payload;
+#endif
+};
+
+/// Make a Error instance representing failure using the given error info
+/// type.
+template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
+  return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
+}
+
+/// Base class for user error types. Users should declare their error types
+/// like:
+///
+/// class MyError : public ErrorInfo<MyError> {
+///   ....
+/// };
+///
+/// This class provides an implementation of the ErrorInfoBase::kind
+/// method, which is used by the Error RTTI system.
+template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
+class ErrorInfo : public ParentErrT {
+public:
+  bool isA(const void *const ClassID) const override {
+    return ClassID == classID() || ParentErrT::isA(ClassID);
+  }
+
+  static const void *classID() { return &ThisErrT::ID; }
+};
+
+/// Special ErrorInfo subclass representing a list of ErrorInfos.
+/// Instances of this class are constructed by joinError.
+class ErrorList final : public ErrorInfo<ErrorList> {
+
+  // handleErrors needs to be able to iterate the payload list of an
+  // ErrorList.
+  template <typename... HandlerTs>
+  friend Error handleErrors(Error E, HandlerTs &&... Handlers);
+
+  // joinErrors is implemented in terms of join.
+  friend Error joinErrors(Error, Error);
+
+public:
+  void log(raw_ostream &OS) const override {
+    OS << "Multiple errors:\n";
+    for (auto &ErrPayload : Payloads) {
+      ErrPayload->log(OS);
+      OS << "\n";
+    }
+  }
+
+  std::error_code convertToErrorCode() const override;
+
+  // Used by ErrorInfo::classID.
+  static char ID;
+
+private:
+  ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
+            std::unique_ptr<ErrorInfoBase> Payload2) {
+    assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&
+           "ErrorList constructor payloads should be singleton errors");
+    Payloads.push_back(std::move(Payload1));
+    Payloads.push_back(std::move(Payload2));
+  }
+
+  static Error join(Error E1, Error E2) {
+    if (!E1)
+      return E2;
+    if (!E2)
+      return E1;
+    if (E1.isA<ErrorList>()) {
+      auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
+      if (E2.isA<ErrorList>()) {
+        auto E2Payload = E2.takePayload();
+        auto &E2List = static_cast<ErrorList &>(*E2Payload);
+        for (auto &Payload : E2List.Payloads)
+          E1List.Payloads.push_back(std::move(Payload));
+      } else
+        E1List.Payloads.push_back(E2.takePayload());
+
+      return E1;
+    }
+    if (E2.isA<ErrorList>()) {
+      auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
+      E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
+      return E2;
+    }
+    return Error(std::unique_ptr<ErrorList>(
+        new ErrorList(E1.takePayload(), E2.takePayload())));
+  }
+
+  std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
+};
+
+/// Concatenate errors. The resulting Error is unchecked, and contains the
+/// ErrorInfo(s), if any, contained in E1, followed by the
+/// ErrorInfo(s), if any, contained in E2.
+inline Error joinErrors(Error E1, Error E2) {
+  return ErrorList::join(std::move(E1), std::move(E2));
+}
+
+/// Helper for testing applicability of, and applying, handlers for
+/// ErrorInfo types.
+template <typename HandlerT>
+class ErrorHandlerTraits
+    : public ErrorHandlerTraits<decltype(
+          &std::remove_reference<HandlerT>::type::operator())> {};
+
+// Specialization functions of the form 'Error (const ErrT&)'.
+template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
+public:
+  static bool appliesTo(const ErrorInfoBase &E) {
+    return E.template isA<ErrT>();
+  }
+
+  template <typename HandlerT>
+  static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+    assert(appliesTo(*E) && "Applying incorrect handler");
+    return H(static_cast<ErrT &>(*E));
+  }
+};
+
+// Specialization functions of the form 'void (const ErrT&)'.
+template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
+public:
+  static bool appliesTo(const ErrorInfoBase &E) {
+    return E.template isA<ErrT>();
+  }
+
+  template <typename HandlerT>
+  static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+    assert(appliesTo(*E) && "Applying incorrect handler");
+    H(static_cast<ErrT &>(*E));
+    return Error::success();
+  }
+};
+
+/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
+template <typename ErrT>
+class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
+public:
+  static bool appliesTo(const ErrorInfoBase &E) {
+    return E.template isA<ErrT>();
+  }
+
+  template <typename HandlerT>
+  static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+    assert(appliesTo(*E) && "Applying incorrect handler");
+    std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
+    return H(std::move(SubE));
+  }
+};
+
+/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
+template <typename ErrT>
+class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
+public:
+  static bool appliesTo(const ErrorInfoBase &E) {
+    return E.template isA<ErrT>();
+  }
+
+  template <typename HandlerT>
+  static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+    assert(appliesTo(*E) && "Applying incorrect handler");
+    std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
+    H(std::move(SubE));
+    return Error::success();
+  }
+};
+
+// Specialization for member functions of the form 'RetT (const ErrT&)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
+    : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
+    : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
+    : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
+    : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+/// Specialization for member functions of the form
+/// 'RetT (std::unique_ptr<ErrT>) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
+    : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
+
+/// Specialization for member functions of the form
+/// 'RetT (std::unique_ptr<ErrT>) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
+    : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
+
+inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
+  return Error(std::move(Payload));
+}
+
+template <typename HandlerT, typename... HandlerTs>
+Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
+                      HandlerT &&Handler, HandlerTs &&... Handlers) {
+  if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
+    return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
+                                               std::move(Payload));
+  return handleErrorImpl(std::move(Payload),
+                         std::forward<HandlerTs>(Handlers)...);
+}
+
+/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
+/// unhandled errors (or Errors returned by handlers) are re-concatenated and
+/// returned.
+/// Because this function returns an error, its result must also be checked
+/// or returned. If you intend to handle all errors use handleAllErrors
+/// (which returns void, and will abort() on unhandled errors) instead.
+template <typename... HandlerTs>
+Error handleErrors(Error E, HandlerTs &&... Hs) {
+  if (!E)
+    return Error::success();
+
+  std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
+
+  if (Payload->isA<ErrorList>()) {
+    ErrorList &List = static_cast<ErrorList &>(*Payload);
+    Error R;
+    for (auto &P : List.Payloads)
+      R = ErrorList::join(
+          std::move(R),
+          handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
+    return R;
+  }
+
+  return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
+}
+
+/// Behaves the same as handleErrors, except that it requires that all
+/// errors be handled by the given handlers. If any unhandled error remains
+/// after the handlers have run, abort() will be called.
+template <typename... HandlerTs>
+void handleAllErrors(Error E, HandlerTs &&... Handlers) {
+  auto F = handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...);
+  // Cast 'F' to bool to set the 'Checked' flag if it's a success value:
+  (void)!F;
+}
+
+/// Check that E is a non-error, then drop it.
+inline void handleAllErrors(Error E) {
+  // Cast 'E' to a bool to set the 'Checked' flag if it's a success value:
+  (void)!E;
+}
+
+/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
+/// will be printed before the first one is logged. A newline will be printed
+/// after each error.
+///
+/// This is useful in the base level of your program to allow clean termination
+/// (allowing clean deallocation of resources, etc.), while reporting error
+/// information to the user.
+void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
+
+/// Write all error messages (if any) in E to a string. The newline character
+/// is used to separate error messages.
+inline std::string toString(Error E) {
+  SmallVector<std::string, 2> Errors;
+  handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
+    Errors.push_back(EI.message());
+  });
+  return join(Errors.begin(), Errors.end(), "\n");
+}
+
+/// Consume a Error without doing anything. This method should be used
+/// only where an error can be considered a reasonable and expected return
+/// value.
+///
+/// Uses of this method are potentially indicative of design problems: If it's
+/// legitimate to do nothing while processing an "error", the error-producer
+/// might be more clearly refactored to return an Optional<T>.
+inline void consumeError(Error Err) {
+  handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
+}
+
+/// Helper for Errors used as out-parameters.
+///
+/// This helper is for use with the Error-as-out-parameter idiom, where an error
+/// is passed to a function or method by reference, rather than being returned.
+/// In such cases it is helpful to set the checked bit on entry to the function
+/// so that the error can be written to (unchecked Errors abort on assignment)
+/// and clear the checked bit on exit so that clients cannot accidentally forget
+/// to check the result. This helper performs these actions automatically using
+/// RAII:
+///
+///   @code{.cpp}
+///   Result foo(Error &Err) {
+///     ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
+///     // <body of foo>
+///     // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
+///   }
+///   @endcode
+///
+/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
+/// used with optional Errors (Error pointers that are allowed to be null). If
+/// ErrorAsOutParameter took an Error reference, an instance would have to be
+/// created inside every condition that verified that Error was non-null. By
+/// taking an Error pointer we can just create one instance at the top of the
+/// function.
+class ErrorAsOutParameter {
+public:
+  ErrorAsOutParameter(Error *Err) : Err(Err) {
+    // Raise the checked bit if Err is success.
+    if (Err)
+      (void)!!*Err;
+  }
+  ~ErrorAsOutParameter() {
+    // Clear the checked bit.
+    if (Err && !*Err)
+      *Err = Error::success();
+  }
+
+private:
+  Error *Err;
+};
+
+/// Tagged union holding either a T or a Error.
+///
+/// This class parallels ErrorOr, but replaces error_code with Error. Since
+/// Error cannot be copied, this class replaces getError() with
+/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
+/// error class type.
+template <class T> class Expected {
+  template <class OtherT> friend class Expected;
+  static const bool isRef = std::is_reference<T>::value;
+  typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap;
+
+  typedef std::unique_ptr<ErrorInfoBase> error_type;
+
+public:
+  typedef typename std::conditional<isRef, wrap, T>::type storage_type;
+  typedef T value_type;
+
+private:
+  typedef typename std::remove_reference<T>::type &reference;
+  typedef const typename std::remove_reference<T>::type &const_reference;
+  typedef typename std::remove_reference<T>::type *pointer;
+  typedef const typename std::remove_reference<T>::type *const_pointer;
+
+public:
+  /// Create an Expected<T> error value from the given Error.
+  Expected(Error Err)
+      : HasError(true)
+#ifndef NDEBUG
+        ,
+        Checked(false)
+#endif
+  {
+    assert(Err && "Cannot create Expected<T> from Error success value.");
+    new (getErrorStorage()) Error(std::move(Err));
+  }
+
+  /// Create an Expected<T> success value from the given OtherT value, which
+  /// must be convertible to T.
+  template <typename OtherT>
+  Expected(OtherT &&Val,
+           typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+               * = nullptr)
+      : HasError(false)
+#ifndef NDEBUG
+        ,
+        Checked(false)
+#endif
+  {
+    new (getStorage()) storage_type(std::forward<OtherT>(Val));
+  }
+
+  /// Move construct an Expected<T> value.
+  Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
+
+  /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
+  /// must be convertible to T.
+  template <class OtherT>
+  Expected(Expected<OtherT> &&Other,
+           typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+               * = nullptr) {
+    moveConstruct(std::move(Other));
+  }
+
+  /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
+  /// isn't convertible to T.
+  template <class OtherT>
+  explicit Expected(
+      Expected<OtherT> &&Other,
+      typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+          nullptr) {
+    moveConstruct(std::move(Other));
+  }
+
+  /// Move-assign from another Expected<T>.
+  Expected &operator=(Expected &&Other) {
+    moveAssign(std::move(Other));
+    return *this;
+  }
+
+  /// Destroy an Expected<T>.
+  ~Expected() {
+    assertIsChecked();
+    if (!HasError)
+      getStorage()->~storage_type();
+    else
+      getErrorStorage()->~error_type();
+  }
+
+  /// \brief Return false if there is an error.
+  explicit operator bool() {
+#ifndef NDEBUG
+    Checked = !HasError;
+#endif
+    return !HasError;
+  }
+
+  /// \brief Returns a reference to the stored T value.
+  reference get() {
+    assertIsChecked();
+    return *getStorage();
+  }
+
+  /// \brief Returns a const reference to the stored T value.
+  const_reference get() const {
+    assertIsChecked();
+    return const_cast<Expected<T> *>(this)->get();
+  }
+
+  /// \brief Check that this Expected<T> is an error of type ErrT.
+  template <typename ErrT> bool errorIsA() const {
+    return HasError && getErrorStorage()->template isA<ErrT>();
+  }
+
+  /// \brief Take ownership of the stored error.
+  /// After calling this the Expected<T> is in an indeterminate state that can
+  /// only be safely destructed. No further calls (beside the destructor) should
+  /// be made on the Expected<T> vaule.
+  Error takeError() {
+#ifndef NDEBUG
+    Checked = true;
+#endif
+    return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
+  }
+
+  /// \brief Returns a pointer to the stored T value.
+  pointer operator->() {
+    assertIsChecked();
+    return toPointer(getStorage());
+  }
+
+  /// \brief Returns a const pointer to the stored T value.
+  const_pointer operator->() const {
+    assertIsChecked();
+    return toPointer(getStorage());
+  }
+
+  /// \brief Returns a reference to the stored T value.
+  reference operator*() {
+    assertIsChecked();
+    return *getStorage();
+  }
+
+  /// \brief Returns a const reference to the stored T value.
+  const_reference operator*() const {
+    assertIsChecked();
+    return *getStorage();
+  }
+
+private:
+  template <class T1>
+  static bool compareThisIfSameType(const T1 &a, const T1 &b) {
+    return &a == &b;
+  }
+
+  template <class T1, class T2>
+  static bool compareThisIfSameType(const T1 &a, const T2 &b) {
+    return false;
+  }
+
+  template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
+    HasError = Other.HasError;
+
+#ifndef NDEBUG
+    Checked = false;
+    Other.Checked = true;
+#endif
+
+    if (!HasError)
+      new (getStorage()) storage_type(std::move(*Other.getStorage()));
+    else
+      new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
+  }
+
+  template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
+    assertIsChecked();
+
+    if (compareThisIfSameType(*this, Other))
+      return;
+
+    this->~Expected();
+    new (this) Expected(std::move(Other));
+  }
+
+  pointer toPointer(pointer Val) { return Val; }
+
+  const_pointer toPointer(const_pointer Val) const { return Val; }
+
+  pointer toPointer(wrap *Val) { return &Val->get(); }
+
+  const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
+
+  storage_type *getStorage() {
+    assert(!HasError && "Cannot get value when an error exists!");
+    return reinterpret_cast<storage_type *>(TStorage.buffer);
+  }
+
+  const storage_type *getStorage() const {
+    assert(!HasError && "Cannot get value when an error exists!");
+    return reinterpret_cast<const storage_type *>(TStorage.buffer);
+  }
+
+  error_type *getErrorStorage() {
+    assert(HasError && "Cannot get error when a value exists!");
+    return reinterpret_cast<error_type *>(ErrorStorage.buffer);
+  }
+
+  void assertIsChecked() {
+#ifndef NDEBUG
+    if (!Checked) {
+      dbgs() << "Expected<T> must be checked before access or destruction.\n";
+      if (HasError) {
+        dbgs() << "Unchecked Expected<T> contained error:\n";
+        (*getErrorStorage())->log(dbgs());
+      } else
+        dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
+                  "values in success mode must still be checked prior to being "
+                  "destroyed).\n";
+      abort();
+    }
+#endif
+  }
+
+  union {
+    AlignedCharArrayUnion<storage_type> TStorage;
+    AlignedCharArrayUnion<error_type> ErrorStorage;
+  };
+  bool HasError : 1;
+#ifndef NDEBUG
+  bool Checked : 1;
+#endif
+};
+
+/// This class wraps a std::error_code in a Error.
+///
+/// This is useful if you're writing an interface that returns a Error
+/// (or Expected) and you want to call code that still returns
+/// std::error_codes.
+class ECError : public ErrorInfo<ECError> {
+  friend Error errorCodeToError(std::error_code);
+public:
+  void setErrorCode(std::error_code EC) { this->EC = EC; }
+  std::error_code convertToErrorCode() const override { return EC; }
+  void log(raw_ostream &OS) const override { OS << EC.message(); }
+
+  // Used by ErrorInfo::classID.
+  static char ID;
+
+protected:
+  ECError() = default;
+  ECError(std::error_code EC) : EC(EC) {}
+  std::error_code EC;
+};
+
+/// The value returned by this function can be returned from convertToErrorCode
+/// for Error values where no sensible translation to std::error_code exists.
+/// It should only be used in this situation, and should never be used where a
+/// sensible conversion to std::error_code is available, as attempts to convert
+/// to/from this error will result in a fatal error. (i.e. it is a programmatic
+///error to try to convert such a value).
+std::error_code inconvertibleErrorCode();
+
+/// Helper for converting an std::error_code to a Error.
+Error errorCodeToError(std::error_code EC);
+
+/// Helper for converting an ECError to a std::error_code.
+///
+/// This method requires that Err be Error() or an ECError, otherwise it
+/// will trigger a call to abort().
+std::error_code errorToErrorCode(Error Err);
+
+/// Convert an ErrorOr<T> to an Expected<T>.
+template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
+  if (auto EC = EO.getError())
+    return errorCodeToError(EC);
+  return std::move(*EO);
+}
+
+/// Convert an Expected<T> to an ErrorOr<T>.
+template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
+  if (auto Err = E.takeError())
+    return errorToErrorCode(std::move(Err));
+  return std::move(*E);
+}
+
+/// This class wraps a string in an Error.
+///
+/// StringError is useful in cases where the client is not expected to be able
+/// to consume the specific error message programmatically (for example, if the
+/// error message is to be presented to the user).
+class StringError : public ErrorInfo<StringError> {
+public:
+  static char ID;
+  StringError(const Twine &S, std::error_code EC);
+  void log(raw_ostream &OS) const override;
+  std::error_code convertToErrorCode() const override;
+private:
+  std::string Msg;
+  std::error_code EC;
+};
+
+/// Helper for check-and-exit error handling.
+///
+/// For tool use only. NOT FOR USE IN LIBRARY CODE.
+///
+class ExitOnError {
+public:
+  /// Create an error on exit helper.
+  ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
+      : Banner(std::move(Banner)),
+        GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
+
+  /// Set the banner string for any errors caught by operator().
+  void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
+
+  /// Set the exit-code mapper function.
+  void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
+    this->GetExitCode = std::move(GetExitCode);
+  }
+
+  /// Check Err. If it's in a failure state log the error(s) and exit.
+  void operator()(Error Err) const { checkError(std::move(Err)); }
+
+  /// Check E. If it's in a success state then return the contained value. If
+  /// it's in a failure state log the error(s) and exit.
+  template <typename T> T operator()(Expected<T> &&E) const {
+    checkError(E.takeError());
+    return std::move(*E);
+  }
+
+  /// Check E. If it's in a success state then return the contained reference. If
+  /// it's in a failure state log the error(s) and exit.
+  template <typename T> T& operator()(Expected<T&> &&E) const {
+    checkError(E.takeError());
+    return *E;
+  }
+
+private:
+  void checkError(Error Err) const {
+    if (Err) {
+      int ExitCode = GetExitCode(Err);
+      logAllUnhandledErrors(std::move(Err), errs(), Banner);
+      exit(ExitCode);
+    }
+  }
+
+  std::string Banner;
+  std::function<int(const Error &)> GetExitCode;
+};
+
+/// Report a serious error, calling any installed error handler. See
+/// ErrorHandling.h.
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err,
+                                                bool gen_crash_diag = true);
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ERROR_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/ErrorHandling.h b/third_party/llvm-subzero/include/llvm/Support/ErrorHandling.h
new file mode 100644
index 0000000..7c1edd8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ErrorHandling.h
@@ -0,0 +1,106 @@
+//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an API used to indicate fatal error conditions.  Non-fatal
+// errors (most of them) should be handled through LLVMContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERRORHANDLING_H
+#define LLVM_SUPPORT_ERRORHANDLING_H
+
+#include "llvm/Support/Compiler.h"
+#include <string>
+
+namespace llvm {
+class StringRef;
+  class Twine;
+
+  /// An error handler callback.
+  typedef void (*fatal_error_handler_t)(void *user_data,
+                                        const std::string& reason,
+                                        bool gen_crash_diag);
+
+  /// install_fatal_error_handler - Installs a new error handler to be used
+  /// whenever a serious (non-recoverable) error is encountered by LLVM.
+  ///
+  /// If no error handler is installed the default is to print the error message
+  /// to stderr, and call exit(1).  If an error handler is installed then it is
+  /// the handler's responsibility to log the message, it will no longer be
+  /// printed to stderr.  If the error handler returns, then exit(1) will be
+  /// called.
+  ///
+  /// It is dangerous to naively use an error handler which throws an exception.
+  /// Even though some applications desire to gracefully recover from arbitrary
+  /// faults, blindly throwing exceptions through unfamiliar code isn't a way to
+  /// achieve this.
+  ///
+  /// \param user_data - An argument which will be passed to the install error
+  /// handler.
+  void install_fatal_error_handler(fatal_error_handler_t handler,
+                                   void *user_data = nullptr);
+
+  /// Restores default error handling behaviour.
+  void remove_fatal_error_handler();
+
+  /// ScopedFatalErrorHandler - This is a simple helper class which just
+  /// calls install_fatal_error_handler in its constructor and
+  /// remove_fatal_error_handler in its destructor.
+  struct ScopedFatalErrorHandler {
+    explicit ScopedFatalErrorHandler(fatal_error_handler_t handler,
+                                     void *user_data = nullptr) {
+      install_fatal_error_handler(handler, user_data);
+    }
+
+    ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); }
+  };
+
+/// Reports a serious error, calling any installed error handler. These
+/// functions are intended to be used for error conditions which are outside
+/// the control of the compiler (I/O errors, invalid user input, etc.)
+///
+/// If no error handler is installed the default is to print the message to
+/// standard error, followed by a newline.
+/// After the error handler is called this function will call exit(1), it
+/// does not return.
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
+                                                bool gen_crash_diag = true);
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
+                                                bool gen_crash_diag = true);
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason,
+                                                bool gen_crash_diag = true);
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason,
+                                                bool gen_crash_diag = true);
+
+  /// This function calls abort(), and prints the optional message to stderr.
+  /// Use the llvm_unreachable macro (that adds location info), instead of
+  /// calling this function directly.
+  LLVM_ATTRIBUTE_NORETURN void
+  llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr,
+                            unsigned line=0);
+}
+
+/// Marks that the current location is not supposed to be reachable.
+/// In !NDEBUG builds, prints the message and location info to stderr.
+/// In NDEBUG builds, becomes an optimizer hint that the current location
+/// is not supposed to be reachable.  On compilers that don't support
+/// such hints, prints a reduced message instead.
+///
+/// Use this instead of assert(0).  It conveys intent more clearly and
+/// allows compilers to omit some unnecessary code.
+#ifndef NDEBUG
+#define llvm_unreachable(msg) \
+  ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
+#elif defined(LLVM_BUILTIN_UNREACHABLE)
+#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
+#else
+#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
+#endif
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ErrorOr.h b/third_party/llvm-subzero/include/llvm/Support/ErrorOr.h
new file mode 100644
index 0000000..877f406
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ErrorOr.h
@@ -0,0 +1,287 @@
+//===- llvm/Support/ErrorOr.h - Error Smart Pointer -------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Provides ErrorOr<T> smart pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERROROR_H
+#define LLVM_SUPPORT_ERROROR_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/AlignOf.h"
+#include <cassert>
+#include <system_error>
+#include <type_traits>
+
+namespace llvm {
+/// \brief Stores a reference that can be changed.
+template <typename T>
+class ReferenceStorage {
+  T *Storage;
+
+public:
+  ReferenceStorage(T &Ref) : Storage(&Ref) {}
+
+  operator T &() const { return *Storage; }
+  T &get() const { return *Storage; }
+};
+
+/// \brief Represents either an error or a value T.
+///
+/// ErrorOr<T> is a pointer-like class that represents the result of an
+/// operation. The result is either an error, or a value of type T. This is
+/// designed to emulate the usage of returning a pointer where nullptr indicates
+/// failure. However instead of just knowing that the operation failed, we also
+/// have an error_code and optional user data that describes why it failed.
+///
+/// It is used like the following.
+/// \code
+///   ErrorOr<Buffer> getBuffer();
+///
+///   auto buffer = getBuffer();
+///   if (error_code ec = buffer.getError())
+///     return ec;
+///   buffer->write("adena");
+/// \endcode
+///
+///
+/// Implicit conversion to bool returns true if there is a usable value. The
+/// unary * and -> operators provide pointer like access to the value. Accessing
+/// the value when there is an error has undefined behavior.
+///
+/// When T is a reference type the behavior is slightly different. The reference
+/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
+/// there is special handling to make operator -> work as if T was not a
+/// reference.
+///
+/// T cannot be a rvalue reference.
+template<class T>
+class ErrorOr {
+  template <class OtherT> friend class ErrorOr;
+  static const bool isRef = std::is_reference<T>::value;
+  typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap;
+
+public:
+  typedef typename std::conditional<isRef, wrap, T>::type storage_type;
+
+private:
+  typedef typename std::remove_reference<T>::type &reference;
+  typedef const typename std::remove_reference<T>::type &const_reference;
+  typedef typename std::remove_reference<T>::type *pointer;
+  typedef const typename std::remove_reference<T>::type *const_pointer;
+
+public:
+  template <class E>
+  ErrorOr(E ErrorCode,
+          typename std::enable_if<std::is_error_code_enum<E>::value ||
+                                      std::is_error_condition_enum<E>::value,
+                                  void *>::type = nullptr)
+      : HasError(true) {
+    new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
+  }
+
+  ErrorOr(std::error_code EC) : HasError(true) {
+    new (getErrorStorage()) std::error_code(EC);
+  }
+
+  template <class OtherT>
+  ErrorOr(OtherT &&Val,
+          typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+              * = nullptr)
+      : HasError(false) {
+    new (getStorage()) storage_type(std::forward<OtherT>(Val));
+  }
+
+  ErrorOr(const ErrorOr &Other) {
+    copyConstruct(Other);
+  }
+
+  template <class OtherT>
+  ErrorOr(
+      const ErrorOr<OtherT> &Other,
+      typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+          nullptr) {
+    copyConstruct(Other);
+  }
+
+  template <class OtherT>
+  explicit ErrorOr(
+      const ErrorOr<OtherT> &Other,
+      typename std::enable_if<
+          !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) {
+    copyConstruct(Other);
+  }
+
+  ErrorOr(ErrorOr &&Other) {
+    moveConstruct(std::move(Other));
+  }
+
+  template <class OtherT>
+  ErrorOr(
+      ErrorOr<OtherT> &&Other,
+      typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+          nullptr) {
+    moveConstruct(std::move(Other));
+  }
+
+  // This might eventually need SFINAE but it's more complex than is_convertible
+  // & I'm too lazy to write it right now.
+  template <class OtherT>
+  explicit ErrorOr(
+      ErrorOr<OtherT> &&Other,
+      typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+          nullptr) {
+    moveConstruct(std::move(Other));
+  }
+
+  ErrorOr &operator=(const ErrorOr &Other) {
+    copyAssign(Other);
+    return *this;
+  }
+
+  ErrorOr &operator=(ErrorOr &&Other) {
+    moveAssign(std::move(Other));
+    return *this;
+  }
+
+  ~ErrorOr() {
+    if (!HasError)
+      getStorage()->~storage_type();
+  }
+
+  /// \brief Return false if there is an error.
+  explicit operator bool() const {
+    return !HasError;
+  }
+
+  reference get() { return *getStorage(); }
+  const_reference get() const { return const_cast<ErrorOr<T> *>(this)->get(); }
+
+  std::error_code getError() const {
+    return HasError ? *getErrorStorage() : std::error_code();
+  }
+
+  pointer operator ->() {
+    return toPointer(getStorage());
+  }
+
+  const_pointer operator->() const { return toPointer(getStorage()); }
+
+  reference operator *() {
+    return *getStorage();
+  }
+
+  const_reference operator*() const { return *getStorage(); }
+
+private:
+  template <class OtherT>
+  void copyConstruct(const ErrorOr<OtherT> &Other) {
+    if (!Other.HasError) {
+      // Get the other value.
+      HasError = false;
+      new (getStorage()) storage_type(*Other.getStorage());
+    } else {
+      // Get other's error.
+      HasError = true;
+      new (getErrorStorage()) std::error_code(Other.getError());
+    }
+  }
+
+  template <class T1>
+  static bool compareThisIfSameType(const T1 &a, const T1 &b) {
+    return &a == &b;
+  }
+
+  template <class T1, class T2>
+  static bool compareThisIfSameType(const T1 &a, const T2 &b) {
+    return false;
+  }
+
+  template <class OtherT>
+  void copyAssign(const ErrorOr<OtherT> &Other) {
+    if (compareThisIfSameType(*this, Other))
+      return;
+
+    this->~ErrorOr();
+    new (this) ErrorOr(Other);
+  }
+
+  template <class OtherT>
+  void moveConstruct(ErrorOr<OtherT> &&Other) {
+    if (!Other.HasError) {
+      // Get the other value.
+      HasError = false;
+      new (getStorage()) storage_type(std::move(*Other.getStorage()));
+    } else {
+      // Get other's error.
+      HasError = true;
+      new (getErrorStorage()) std::error_code(Other.getError());
+    }
+  }
+
+  template <class OtherT>
+  void moveAssign(ErrorOr<OtherT> &&Other) {
+    if (compareThisIfSameType(*this, Other))
+      return;
+
+    this->~ErrorOr();
+    new (this) ErrorOr(std::move(Other));
+  }
+
+  pointer toPointer(pointer Val) {
+    return Val;
+  }
+
+  const_pointer toPointer(const_pointer Val) const { return Val; }
+
+  pointer toPointer(wrap *Val) {
+    return &Val->get();
+  }
+
+  const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
+
+  storage_type *getStorage() {
+    assert(!HasError && "Cannot get value when an error exists!");
+    return reinterpret_cast<storage_type*>(TStorage.buffer);
+  }
+
+  const storage_type *getStorage() const {
+    assert(!HasError && "Cannot get value when an error exists!");
+    return reinterpret_cast<const storage_type*>(TStorage.buffer);
+  }
+
+  std::error_code *getErrorStorage() {
+    assert(HasError && "Cannot get error when a value exists!");
+    return reinterpret_cast<std::error_code *>(ErrorStorage.buffer);
+  }
+
+  const std::error_code *getErrorStorage() const {
+    return const_cast<ErrorOr<T> *>(this)->getErrorStorage();
+  }
+
+  union {
+    AlignedCharArrayUnion<storage_type> TStorage;
+    AlignedCharArrayUnion<std::error_code> ErrorStorage;
+  };
+  bool HasError : 1;
+};
+
+template <class T, class E>
+typename std::enable_if<std::is_error_code_enum<E>::value ||
+                            std::is_error_condition_enum<E>::value,
+                        bool>::type
+operator==(const ErrorOr<T> &Err, E Code) {
+  return Err.getError() == Code;
+}
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ERROROR_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/FileSystem.h b/third_party/llvm-subzero/include/llvm/Support/FileSystem.h
new file mode 100644
index 0000000..42a6180
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/FileSystem.h
@@ -0,0 +1,935 @@
+//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::fs namespace. It is designed after
+// TR2/boost filesystem (v3), but modified to remove exception handling and the
+// path class.
+//
+// All functions return an error_code and their actual work via the last out
+// argument. The out argument is defined if and only if errc::success is
+// returned. A function may return any error code in the generic or system
+// category. However, they shall be equivalent to any error conditions listed
+// in each functions respective documentation if the condition applies. [ note:
+// this does not guarantee that error_code will be in the set of explicitly
+// listed codes, but it does guarantee that if any of the explicitly listed
+// errors occur, the correct error_code will be used ]. All functions may
+// return errc::not_enough_memory if there is not enough memory to complete the
+// operation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILESYSTEM_H
+#define LLVM_SUPPORT_FILESYSTEM_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/TimeValue.h"
+#include <cassert>
+#include <cstdint>
+#include <ctime>
+#include <stack>
+#include <string>
+#include <system_error>
+#include <tuple>
+#include <vector>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+namespace llvm {
+namespace sys {
+namespace fs {
+
+/// An enumeration for the file system's view of the type.
+enum class file_type {
+  status_error,
+  file_not_found,
+  regular_file,
+  directory_file,
+  symlink_file,
+  block_file,
+  character_file,
+  fifo_file,
+  socket_file,
+  type_unknown
+};
+
+/// space_info - Self explanatory.
+struct space_info {
+  uint64_t capacity;
+  uint64_t free;
+  uint64_t available;
+};
+
+enum perms {
+  no_perms = 0,
+  owner_read = 0400,
+  owner_write = 0200,
+  owner_exe = 0100,
+  owner_all = owner_read | owner_write | owner_exe,
+  group_read = 040,
+  group_write = 020,
+  group_exe = 010,
+  group_all = group_read | group_write | group_exe,
+  others_read = 04,
+  others_write = 02,
+  others_exe = 01,
+  others_all = others_read | others_write | others_exe,
+  all_read = owner_read | group_read | others_read,
+  all_write = owner_write | group_write | others_write,
+  all_exe = owner_exe | group_exe | others_exe,
+  all_all = owner_all | group_all | others_all,
+  set_uid_on_exe = 04000,
+  set_gid_on_exe = 02000,
+  sticky_bit = 01000,
+  perms_not_known = 0xFFFF
+};
+
+// Helper functions so that you can use & and | to manipulate perms bits:
+inline perms operator|(perms l, perms r) {
+  return static_cast<perms>(static_cast<unsigned short>(l) |
+                            static_cast<unsigned short>(r));
+}
+inline perms operator&(perms l, perms r) {
+  return static_cast<perms>(static_cast<unsigned short>(l) &
+                            static_cast<unsigned short>(r));
+}
+inline perms &operator|=(perms &l, perms r) {
+  l = l | r;
+  return l;
+}
+inline perms &operator&=(perms &l, perms r) {
+  l = l & r;
+  return l;
+}
+inline perms operator~(perms x) {
+  return static_cast<perms>(~static_cast<unsigned short>(x));
+}
+
+class UniqueID {
+  uint64_t Device;
+  uint64_t File;
+
+public:
+  UniqueID() = default;
+  UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
+  bool operator==(const UniqueID &Other) const {
+    return Device == Other.Device && File == Other.File;
+  }
+  bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
+  bool operator<(const UniqueID &Other) const {
+    return std::tie(Device, File) < std::tie(Other.Device, Other.File);
+  }
+  uint64_t getDevice() const { return Device; }
+  uint64_t getFile() const { return File; }
+};
+
+/// file_status - Represents the result of a call to stat and friends. It has
+///               a platform-specific member to store the result.
+class file_status
+{
+  #if defined(LLVM_ON_UNIX)
+  dev_t fs_st_dev;
+  ino_t fs_st_ino;
+  time_t fs_st_atime;
+  time_t fs_st_mtime;
+  uid_t fs_st_uid;
+  gid_t fs_st_gid;
+  off_t fs_st_size;
+  #elif defined (LLVM_ON_WIN32)
+  uint32_t LastAccessedTimeHigh;
+  uint32_t LastAccessedTimeLow;
+  uint32_t LastWriteTimeHigh;
+  uint32_t LastWriteTimeLow;
+  uint32_t VolumeSerialNumber;
+  uint32_t FileSizeHigh;
+  uint32_t FileSizeLow;
+  uint32_t FileIndexHigh;
+  uint32_t FileIndexLow;
+  #endif
+  friend bool equivalent(file_status A, file_status B);
+  file_type Type;
+  perms Perms;
+
+public:
+  #if defined(LLVM_ON_UNIX)
+  file_status()
+      : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
+        fs_st_uid(0), fs_st_gid(0), fs_st_size(0),
+        Type(file_type::status_error), Perms(perms_not_known) {}
+
+  file_status(file_type Type)
+      : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
+        fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type),
+        Perms(perms_not_known) {}
+
+  file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime,
+              time_t MTime, uid_t UID, gid_t GID, off_t Size)
+      : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), fs_st_mtime(MTime),
+        fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type),
+        Perms(Perms) {}
+  #elif defined(LLVM_ON_WIN32)
+  file_status()
+      : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
+        LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
+        FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0),
+        Type(file_type::status_error), Perms(perms_not_known) {}
+
+  file_status(file_type Type)
+      : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
+        LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
+        FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), Type(Type),
+        Perms(perms_not_known) {}
+
+  file_status(file_type Type, uint32_t LastAccessTimeHigh,
+              uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
+              uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
+              uint32_t FileSizeHigh, uint32_t FileSizeLow,
+              uint32_t FileIndexHigh, uint32_t FileIndexLow)
+      : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow),
+        LastWriteTimeHigh(LastWriteTimeHigh),
+        LastWriteTimeLow(LastWriteTimeLow),
+        VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
+        FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
+        FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {}
+  #endif
+
+  // getters
+  file_type type() const { return Type; }
+  perms permissions() const { return Perms; }
+  TimeValue getLastAccessedTime() const;
+  TimeValue getLastModificationTime() const;
+  UniqueID getUniqueID() const;
+
+  #if defined(LLVM_ON_UNIX)
+  uint32_t getUser() const { return fs_st_uid; }
+  uint32_t getGroup() const { return fs_st_gid; }
+  uint64_t getSize() const { return fs_st_size; }
+  #elif defined (LLVM_ON_WIN32)
+  uint32_t getUser() const {
+    return 9999; // Not applicable to Windows, so...
+  }
+  uint32_t getGroup() const {
+    return 9999; // Not applicable to Windows, so...
+  }
+  uint64_t getSize() const {
+    return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
+  }
+  #endif
+
+  // setters
+  void type(file_type v) { Type = v; }
+  void permissions(perms p) { Perms = p; }
+};
+
+/// file_magic - An "enum class" enumeration of file types based on magic (the first
+///         N bytes of the file).
+struct file_magic {
+  enum Impl {
+    unknown = 0,              ///< Unrecognized file
+    bitcode,                  ///< Bitcode file
+    archive,                  ///< ar style archive file
+    elf,                      ///< ELF Unknown type
+    elf_relocatable,          ///< ELF Relocatable object file
+    elf_executable,           ///< ELF Executable image
+    elf_shared_object,        ///< ELF dynamically linked shared lib
+    elf_core,                 ///< ELF core image
+    macho_object,             ///< Mach-O Object file
+    macho_executable,         ///< Mach-O Executable
+    macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM
+    macho_core,               ///< Mach-O Core File
+    macho_preload_executable, ///< Mach-O Preloaded Executable
+    macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib
+    macho_dynamic_linker,     ///< The Mach-O dynamic linker
+    macho_bundle,             ///< Mach-O Bundle file
+    macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub
+    macho_dsym_companion,     ///< Mach-O dSYM companion file
+    macho_kext_bundle,        ///< Mach-O kext bundle file
+    macho_universal_binary,   ///< Mach-O universal binary
+    coff_object,              ///< COFF object file
+    coff_import_library,      ///< COFF import library
+    pecoff_executable,        ///< PECOFF executable file
+    windows_resource          ///< Windows compiled resource file (.rc)
+  };
+
+  bool is_object() const {
+    return V != unknown;
+  }
+
+  file_magic() : V(unknown) {}
+  file_magic(Impl V) : V(V) {}
+  operator Impl() const { return V; }
+
+private:
+  Impl V;
+};
+
+/// @}
+/// @name Physical Operators
+/// @{
+
+/// @brief Make \a path an absolute path.
+///
+/// Makes \a path absolute using the \a current_directory if it is not already.
+/// An empty \a path will result in the \a current_directory.
+///
+/// /absolute/path   => /absolute/path
+/// relative/../path => <current-directory>/relative/../path
+///
+/// @param path A path that is modified to be an absolute path.
+/// @returns errc::success if \a path has been made absolute, otherwise a
+///          platform-specific error_code.
+std::error_code make_absolute(const Twine &current_directory,
+                              SmallVectorImpl<char> &path);
+
+/// @brief Make \a path an absolute path.
+///
+/// Makes \a path absolute using the current directory if it is not already. An
+/// empty \a path will result in the current directory.
+///
+/// /absolute/path   => /absolute/path
+/// relative/../path => <current-directory>/relative/../path
+///
+/// @param path A path that is modified to be an absolute path.
+/// @returns errc::success if \a path has been made absolute, otherwise a
+///          platform-specific error_code.
+std::error_code make_absolute(SmallVectorImpl<char> &path);
+
+/// @brief Create all the non-existent directories in path.
+///
+/// @param path Directories to create.
+/// @returns errc::success if is_directory(path), otherwise a platform
+///          specific error_code. If IgnoreExisting is false, also returns
+///          error if the directory already existed.
+std::error_code create_directories(const Twine &path,
+                                   bool IgnoreExisting = true,
+                                   perms Perms = owner_all | group_all);
+
+/// @brief Create the directory in path.
+///
+/// @param path Directory to create.
+/// @returns errc::success if is_directory(path), otherwise a platform
+///          specific error_code. If IgnoreExisting is false, also returns
+///          error if the directory already existed.
+std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
+                                 perms Perms = owner_all | group_all);
+
+/// @brief Create a link from \a from to \a to.
+///
+/// The link may be a soft or a hard link, depending on the platform. The caller
+/// may not assume which one. Currently on windows it creates a hard link since
+/// soft links require extra privileges. On unix, it creates a soft link since
+/// hard links don't work on SMB file systems.
+///
+/// @param to The path to hard link to.
+/// @param from The path to hard link from. This is created.
+/// @returns errc::success if the link was created, otherwise a platform
+/// specific error_code.
+std::error_code create_link(const Twine &to, const Twine &from);
+
+/// @brief Get the current path.
+///
+/// @param result Holds the current path on return.
+/// @returns errc::success if the current path has been stored in result,
+///          otherwise a platform-specific error_code.
+std::error_code current_path(SmallVectorImpl<char> &result);
+
+/// @brief Remove path. Equivalent to POSIX remove().
+///
+/// @param path Input path.
+/// @returns errc::success if path has been removed or didn't exist, otherwise a
+///          platform-specific error code. If IgnoreNonExisting is false, also
+///          returns error if the file didn't exist.
+std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
+
+/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename().
+///
+/// @param from The path to rename from.
+/// @param to The path to rename to. This is created.
+std::error_code rename(const Twine &from, const Twine &to);
+
+/// @brief Copy the contents of \a From to \a To.
+///
+/// @param From The path to copy from.
+/// @param To The path to copy to. This is created.
+std::error_code copy_file(const Twine &From, const Twine &To);
+
+/// @brief Resize path to size. File is resized as if by POSIX truncate().
+///
+/// @param FD Input file descriptor.
+/// @param Size Size to resize to.
+/// @returns errc::success if \a path has been resized to \a size, otherwise a
+///          platform-specific error_code.
+std::error_code resize_file(int FD, uint64_t Size);
+
+/// @}
+/// @name Physical Observers
+/// @{
+
+/// @brief Does file exist?
+///
+/// @param status A file_status previously returned from stat.
+/// @returns True if the file represented by status exists, false if it does
+///          not.
+bool exists(file_status status);
+
+enum class AccessMode { Exist, Write, Execute };
+
+/// @brief Can the file be accessed?
+///
+/// @param Path Input path.
+/// @returns errc::success if the path can be accessed, otherwise a
+///          platform-specific error_code.
+std::error_code access(const Twine &Path, AccessMode Mode);
+
+/// @brief Does file exist?
+///
+/// @param Path Input path.
+/// @returns True if it exists, false otherwise.
+inline bool exists(const Twine &Path) {
+  return !access(Path, AccessMode::Exist);
+}
+
+/// @brief Can we execute this file?
+///
+/// @param Path Input path.
+/// @returns True if we can execute it, false otherwise.
+bool can_execute(const Twine &Path);
+
+/// @brief Can we write this file?
+///
+/// @param Path Input path.
+/// @returns True if we can write to it, false otherwise.
+inline bool can_write(const Twine &Path) {
+  return !access(Path, AccessMode::Write);
+}
+
+/// @brief Do file_status's represent the same thing?
+///
+/// @param A Input file_status.
+/// @param B Input file_status.
+///
+/// assert(status_known(A) || status_known(B));
+///
+/// @returns True if A and B both represent the same file system entity, false
+///          otherwise.
+bool equivalent(file_status A, file_status B);
+
+/// @brief Do paths represent the same thing?
+///
+/// assert(status_known(A) || status_known(B));
+///
+/// @param A Input path A.
+/// @param B Input path B.
+/// @param result Set to true if stat(A) and stat(B) have the same device and
+///               inode (or equivalent).
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
+
+/// @brief Simpler version of equivalent for clients that don't need to
+///        differentiate between an error and false.
+inline bool equivalent(const Twine &A, const Twine &B) {
+  bool result;
+  return !equivalent(A, B, result) && result;
+}
+
+/// @brief Does status represent a directory?
+///
+/// @param status A file_status previously returned from status.
+/// @returns status.type() == file_type::directory_file.
+bool is_directory(file_status status);
+
+/// @brief Is path a directory?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is a directory, false if it is not.
+///               Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code is_directory(const Twine &path, bool &result);
+
+/// @brief Simpler version of is_directory for clients that don't need to
+///        differentiate between an error and false.
+inline bool is_directory(const Twine &Path) {
+  bool Result;
+  return !is_directory(Path, Result) && Result;
+}
+
+/// @brief Does status represent a regular file?
+///
+/// @param status A file_status previously returned from status.
+/// @returns status_known(status) && status.type() == file_type::regular_file.
+bool is_regular_file(file_status status);
+
+/// @brief Is path a regular file?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is a regular file, false if it is not.
+///               Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code is_regular_file(const Twine &path, bool &result);
+
+/// @brief Simpler version of is_regular_file for clients that don't need to
+///        differentiate between an error and false.
+inline bool is_regular_file(const Twine &Path) {
+  bool Result;
+  if (is_regular_file(Path, Result))
+    return false;
+  return Result;
+}
+
+/// @brief Does this status represent something that exists but is not a
+///        directory, regular file, or symlink?
+///
+/// @param status A file_status previously returned from status.
+/// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
+bool is_other(file_status status);
+
+/// @brief Is path something that exists but is not a directory,
+///        regular file, or symlink?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path exists, but is not a directory, regular
+///               file, or a symlink, false if it does not. Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code is_other(const Twine &path, bool &result);
+
+/// @brief Get file status as if by POSIX stat().
+///
+/// @param path Input path.
+/// @param result Set to the file status.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code status(const Twine &path, file_status &result);
+
+/// @brief A version for when a file descriptor is already available.
+std::error_code status(int FD, file_status &Result);
+
+/// @brief Get file size.
+///
+/// @param Path Input path.
+/// @param Result Set to the size of the file in \a Path.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
+  file_status Status;
+  std::error_code EC = status(Path, Status);
+  if (EC)
+    return EC;
+  Result = Status.getSize();
+  return std::error_code();
+}
+
+/// @brief Set the file modification and access time.
+///
+/// @returns errc::success if the file times were successfully set, otherwise a
+///          platform-specific error_code or errc::function_not_supported on
+///          platforms where the functionality isn't available.
+std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time);
+
+/// @brief Is status available?
+///
+/// @param s Input file status.
+/// @returns True if status() != status_error.
+bool status_known(file_status s);
+
+/// @brief Is status available?
+///
+/// @param path Input path.
+/// @param result Set to true if status() != status_error.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code status_known(const Twine &path, bool &result);
+
+/// @brief Create a uniquely named file.
+///
+/// Generates a unique path suitable for a temporary file and then opens it as a
+/// file. The name is based on \a model with '%' replaced by a random char in
+/// [0-9a-f]. If \a model is not an absolute path, the temporary file will be
+/// created in the current directory.
+///
+/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
+///
+/// This is an atomic operation. Either the file is created and opened, or the
+/// file system is left untouched.
+///
+/// The intended use is for files that are to be kept, possibly after
+/// renaming them. For example, when running 'clang -c foo.o', the file can
+/// be first created as foo-abc123.o and then renamed.
+///
+/// @param Model Name to base unique path off of.
+/// @param ResultFD Set to the opened file's file descriptor.
+/// @param ResultPath Set to the opened file's absolute path.
+/// @returns errc::success if Result{FD,Path} have been successfully set,
+///          otherwise a platform-specific error_code.
+std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
+                                 SmallVectorImpl<char> &ResultPath,
+                                 unsigned Mode = all_read | all_write);
+
+/// @brief Simpler version for clients that don't want an open file.
+std::error_code createUniqueFile(const Twine &Model,
+                                 SmallVectorImpl<char> &ResultPath);
+
+/// @brief Create a file in the system temporary directory.
+///
+/// The filename is of the form prefix-random_chars.suffix. Since the directory
+/// is not know to the caller, Prefix and Suffix cannot have path separators.
+/// The files are created with mode 0600.
+///
+/// This should be used for things like a temporary .s that is removed after
+/// running the assembler.
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+                                    int &ResultFD,
+                                    SmallVectorImpl<char> &ResultPath);
+
+/// @brief Simpler version for clients that don't want an open file.
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+                                    SmallVectorImpl<char> &ResultPath);
+
+std::error_code createUniqueDirectory(const Twine &Prefix,
+                                      SmallVectorImpl<char> &ResultPath);
+
+/// @brief Fetch a path to an open file, as specified by a file descriptor
+///
+/// @param FD File descriptor to a currently open file
+/// @param ResultPath The buffer into which to write the path
+std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath);
+
+enum OpenFlags : unsigned {
+  F_None = 0,
+
+  /// F_Excl - When opening a file, this flag makes raw_fd_ostream
+  /// report an error if the file already exists.
+  F_Excl = 1,
+
+  /// F_Append - When opening a file, if it already exists append to the
+  /// existing file instead of returning an error.  This may not be specified
+  /// with F_Excl.
+  F_Append = 2,
+
+  /// The file should be opened in text mode on platforms that make this
+  /// distinction.
+  F_Text = 4,
+
+  /// Open the file for read and write.
+  F_RW = 8
+};
+
+inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
+  return OpenFlags(unsigned(A) | unsigned(B));
+}
+
+inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
+  A = A | B;
+  return A;
+}
+
+std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
+                                 OpenFlags Flags, unsigned Mode = 0666);
+
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+                                SmallVectorImpl<char> *RealPath = nullptr);
+
+/// @brief Identify the type of a binary file based on how magical it is.
+file_magic identify_magic(StringRef magic);
+
+/// @brief Get and identify \a path's type based on its content.
+///
+/// @param path Input path.
+/// @param result Set to the type of file, or file_magic::unknown.
+/// @returns errc::success if result has been successfully set, otherwise a
+///          platform-specific error_code.
+std::error_code identify_magic(const Twine &path, file_magic &result);
+
+std::error_code getUniqueID(const Twine Path, UniqueID &Result);
+
+/// @brief Get disk space usage information.
+///
+/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
+/// Note: Windows reports results according to the quota allocated to the user.
+///
+/// @param Path Input path.
+/// @returns a space_info structure filled with the capacity, free, and
+/// available space on the device \a Path is on. A platform specific error_code
+/// is returned on error.
+ErrorOr<space_info> disk_space(const Twine &Path);
+
+/// This class represents a memory mapped file. It is based on
+/// boost::iostreams::mapped_file.
+class mapped_file_region {
+  mapped_file_region() = delete;
+  mapped_file_region(mapped_file_region&) = delete;
+  mapped_file_region &operator =(mapped_file_region&) = delete;
+
+public:
+  enum mapmode {
+    readonly, ///< May only access map via const_data as read only.
+    readwrite, ///< May access map via data and modify it. Written to path.
+    priv ///< May modify via data, but changes are lost on destruction.
+  };
+
+private:
+  /// Platform-specific mapping state.
+  uint64_t Size;
+  void *Mapping;
+
+  std::error_code init(int FD, uint64_t Offset, mapmode Mode);
+
+public:
+  /// \param fd An open file descriptor to map. mapped_file_region takes
+  ///   ownership if closefd is true. It must have been opended in the correct
+  ///   mode.
+  mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset,
+                     std::error_code &ec);
+
+  ~mapped_file_region();
+
+  uint64_t size() const;
+  char *data() const;
+
+  /// Get a const view of the data. Modifying this memory has undefined
+  /// behavior.
+  const char *const_data() const;
+
+  /// \returns The minimum alignment offset must be.
+  static int alignment();
+};
+
+/// Return the path to the main executable, given the value of argv[0] from
+/// program startup and the address of main itself. In extremis, this function
+/// may fail and return an empty path.
+std::string getMainExecutable(const char *argv0, void *MainExecAddr);
+
+/// @}
+/// @name Iterators
+/// @{
+
+/// directory_entry - A single entry in a directory. Caches the status either
+/// from the result of the iteration syscall, or the first time status is
+/// called.
+class directory_entry {
+  std::string Path;
+  mutable file_status Status;
+
+public:
+  explicit directory_entry(const Twine &path, file_status st = file_status())
+    : Path(path.str())
+    , Status(st) {}
+
+  directory_entry() {}
+
+  void assign(const Twine &path, file_status st = file_status()) {
+    Path = path.str();
+    Status = st;
+  }
+
+  void replace_filename(const Twine &filename, file_status st = file_status());
+
+  const std::string &path() const { return Path; }
+  std::error_code status(file_status &result) const;
+
+  bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
+  bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
+  bool operator< (const directory_entry& rhs) const;
+  bool operator<=(const directory_entry& rhs) const;
+  bool operator> (const directory_entry& rhs) const;
+  bool operator>=(const directory_entry& rhs) const;
+};
+
+namespace detail {
+  struct DirIterState;
+
+  std::error_code directory_iterator_construct(DirIterState &, StringRef);
+  std::error_code directory_iterator_increment(DirIterState &);
+  std::error_code directory_iterator_destruct(DirIterState &);
+
+  /// DirIterState - Keeps state for the directory_iterator. It is reference
+  /// counted in order to preserve InputIterator semantics on copy.
+  struct DirIterState : public RefCountedBase<DirIterState> {
+    DirIterState()
+      : IterationHandle(0) {}
+
+    ~DirIterState() {
+      directory_iterator_destruct(*this);
+    }
+
+    intptr_t IterationHandle;
+    directory_entry CurrentEntry;
+  };
+} // end namespace detail
+
+/// directory_iterator - Iterates through the entries in path. There is no
+/// operator++ because we need an error_code. If it's really needed we can make
+/// it call report_fatal_error on error.
+class directory_iterator {
+  IntrusiveRefCntPtr<detail::DirIterState> State;
+
+public:
+  explicit directory_iterator(const Twine &path, std::error_code &ec) {
+    State = new detail::DirIterState;
+    SmallString<128> path_storage;
+    ec = detail::directory_iterator_construct(*State,
+            path.toStringRef(path_storage));
+  }
+
+  explicit directory_iterator(const directory_entry &de, std::error_code &ec) {
+    State = new detail::DirIterState;
+    ec = detail::directory_iterator_construct(*State, de.path());
+  }
+
+  /// Construct end iterator.
+  directory_iterator() : State(nullptr) {}
+
+  // No operator++ because we need error_code.
+  directory_iterator &increment(std::error_code &ec) {
+    ec = directory_iterator_increment(*State);
+    return *this;
+  }
+
+  const directory_entry &operator*() const { return State->CurrentEntry; }
+  const directory_entry *operator->() const { return &State->CurrentEntry; }
+
+  bool operator==(const directory_iterator &RHS) const {
+    if (State == RHS.State)
+      return true;
+    if (!RHS.State)
+      return State->CurrentEntry == directory_entry();
+    if (!State)
+      return RHS.State->CurrentEntry == directory_entry();
+    return State->CurrentEntry == RHS.State->CurrentEntry;
+  }
+
+  bool operator!=(const directory_iterator &RHS) const {
+    return !(*this == RHS);
+  }
+  // Other members as required by
+  // C++ Std, 24.1.1 Input iterators [input.iterators]
+};
+
+namespace detail {
+  /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is
+  /// reference counted in order to preserve InputIterator semantics on copy.
+  struct RecDirIterState : public RefCountedBase<RecDirIterState> {
+    RecDirIterState()
+      : Level(0)
+      , HasNoPushRequest(false) {}
+
+    std::stack<directory_iterator, std::vector<directory_iterator> > Stack;
+    uint16_t Level;
+    bool HasNoPushRequest;
+  };
+} // end namespace detail
+
+/// recursive_directory_iterator - Same as directory_iterator except for it
+/// recurses down into child directories.
+class recursive_directory_iterator {
+  IntrusiveRefCntPtr<detail::RecDirIterState> State;
+
+public:
+  recursive_directory_iterator() {}
+  explicit recursive_directory_iterator(const Twine &path, std::error_code &ec)
+      : State(new detail::RecDirIterState) {
+    State->Stack.push(directory_iterator(path, ec));
+    if (State->Stack.top() == directory_iterator())
+      State.reset();
+  }
+  // No operator++ because we need error_code.
+  recursive_directory_iterator &increment(std::error_code &ec) {
+    const directory_iterator end_itr;
+
+    if (State->HasNoPushRequest)
+      State->HasNoPushRequest = false;
+    else {
+      file_status st;
+      if ((ec = State->Stack.top()->status(st))) return *this;
+      if (is_directory(st)) {
+        State->Stack.push(directory_iterator(*State->Stack.top(), ec));
+        if (ec) return *this;
+        if (State->Stack.top() != end_itr) {
+          ++State->Level;
+          return *this;
+        }
+        State->Stack.pop();
+      }
+    }
+
+    while (!State->Stack.empty()
+           && State->Stack.top().increment(ec) == end_itr) {
+      State->Stack.pop();
+      --State->Level;
+    }
+
+    // Check if we are done. If so, create an end iterator.
+    if (State->Stack.empty())
+      State.reset();
+
+    return *this;
+  }
+
+  const directory_entry &operator*() const { return *State->Stack.top(); }
+  const directory_entry *operator->() const { return &*State->Stack.top(); }
+
+  // observers
+  /// Gets the current level. Starting path is at level 0.
+  int level() const { return State->Level; }
+
+  /// Returns true if no_push has been called for this directory_entry.
+  bool no_push_request() const { return State->HasNoPushRequest; }
+
+  // modifiers
+  /// Goes up one level if Level > 0.
+  void pop() {
+    assert(State && "Cannot pop an end iterator!");
+    assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
+
+    const directory_iterator end_itr;
+    std::error_code ec;
+    do {
+      if (ec)
+        report_fatal_error("Error incrementing directory iterator.");
+      State->Stack.pop();
+      --State->Level;
+    } while (!State->Stack.empty()
+             && State->Stack.top().increment(ec) == end_itr);
+
+    // Check if we are done. If so, create an end iterator.
+    if (State->Stack.empty())
+      State.reset();
+  }
+
+  /// Does not go down into the current directory_entry.
+  void no_push() { State->HasNoPushRequest = true; }
+
+  bool operator==(const recursive_directory_iterator &RHS) const {
+    return State == RHS.State;
+  }
+
+  bool operator!=(const recursive_directory_iterator &RHS) const {
+    return !(*this == RHS);
+  }
+  // Other members as required by
+  // C++ Std, 24.1.1 Input iterators [input.iterators]
+};
+
+/// @}
+
+} // end namespace fs
+} // end namespace sys
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_FILESYSTEM_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/FileUtilities.h b/third_party/llvm-subzero/include/llvm/Support/FileUtilities.h
new file mode 100644
index 0000000..2ee2c60
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/FileUtilities.h
@@ -0,0 +1,78 @@
+//===- llvm/Support/FileUtilities.h - File System Utilities -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a family of utility functions which are useful for doing
+// various things with files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILEUTILITIES_H
+#define LLVM_SUPPORT_FILEUTILITIES_H
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+
+  /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if
+  /// the files match, 1 if they are different, and 2 if there is a file error.
+  /// This function allows you to specify an absolute and relative FP error that
+  /// is allowed to exist.  If you specify a string to fill in for the error
+  /// option, it will set the string to an error message if an error occurs, or
+  /// if the files are different.
+  ///
+  int DiffFilesWithTolerance(StringRef FileA,
+                             StringRef FileB,
+                             double AbsTol, double RelTol,
+                             std::string *Error = nullptr);
+
+
+  /// FileRemover - This class is a simple object meant to be stack allocated.
+  /// If an exception is thrown from a region, the object removes the filename
+  /// specified (if deleteIt is true).
+  ///
+  class FileRemover {
+    SmallString<128> Filename;
+    bool DeleteIt;
+  public:
+    FileRemover() : DeleteIt(false) {}
+
+    explicit FileRemover(const Twine& filename, bool deleteIt = true)
+      : DeleteIt(deleteIt) {
+      filename.toVector(Filename);
+    }
+
+    ~FileRemover() {
+      if (DeleteIt) {
+        // Ignore problems deleting the file.
+        sys::fs::remove(Filename);
+      }
+    }
+
+    /// setFile - Give ownership of the file to the FileRemover so it will
+    /// be removed when the object is destroyed.  If the FileRemover already
+    /// had ownership of a file, remove it first.
+    void setFile(const Twine& filename, bool deleteIt = true) {
+      if (DeleteIt) {
+        // Ignore problems deleting the file.
+        sys::fs::remove(Filename);
+      }
+
+      Filename.clear();
+      filename.toVector(Filename);
+      DeleteIt = deleteIt;
+    }
+
+    /// releaseFile - Take ownership of the file away from the FileRemover so it
+    /// will not be removed when the object is destroyed.
+    void releaseFile() { DeleteIt = false; }
+  };
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Format.h b/third_party/llvm-subzero/include/llvm/Support/Format.h
new file mode 100644
index 0000000..d5c301c
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Format.h
@@ -0,0 +1,195 @@
+//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the format() function, which can be used with other
+// LLVM subsystems to provide printf-style formatting.  This gives all the power
+// and risk of printf.  This can be used like this (with raw_ostreams as an
+// example):
+//
+//    OS << "mynumber: " << format("%4.5f", 1234.412) << '\n';
+//
+// Or if you prefer:
+//
+//  OS << format("mynumber: %4.5f\n", 1234.412);
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FORMAT_H
+#define LLVM_SUPPORT_FORMAT_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstdio>
+#include <tuple>
+
+namespace llvm {
+
+/// This is a helper class used for handling formatted output.  It is the
+/// abstract base class of a templated derived class.
+class format_object_base {
+protected:
+  const char *Fmt;
+  ~format_object_base() = default; // Disallow polymorphic deletion.
+  format_object_base(const format_object_base &) = default;
+  virtual void home(); // Out of line virtual method.
+
+  /// Call snprintf() for this object, on the given buffer and size.
+  virtual int snprint(char *Buffer, unsigned BufferSize) const = 0;
+
+public:
+  format_object_base(const char *fmt) : Fmt(fmt) {}
+
+  /// Format the object into the specified buffer.  On success, this returns
+  /// the length of the formatted string.  If the buffer is too small, this
+  /// returns a length to retry with, which will be larger than BufferSize.
+  unsigned print(char *Buffer, unsigned BufferSize) const {
+    assert(BufferSize && "Invalid buffer size!");
+
+    // Print the string, leaving room for the terminating null.
+    int N = snprint(Buffer, BufferSize);
+
+    // VC++ and old GlibC return negative on overflow, just double the size.
+    if (N < 0)
+      return BufferSize * 2;
+
+    // Other implementations yield number of bytes needed, not including the
+    // final '\0'.
+    if (unsigned(N) >= BufferSize)
+      return N + 1;
+
+    // Otherwise N is the length of output (not including the final '\0').
+    return N;
+  }
+};
+
+/// These are templated helper classes used by the format function that
+/// capture the object to be formated and the format string. When actually
+/// printed, this synthesizes the string into a temporary buffer provided and
+/// returns whether or not it is big enough.
+
+template <typename... Ts>
+class format_object final : public format_object_base {
+  std::tuple<Ts...> Vals;
+
+  template <std::size_t... Is>
+  int snprint_tuple(char *Buffer, unsigned BufferSize,
+                    index_sequence<Is...>) const {
+#ifdef _MSC_VER
+    return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#else
+    return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#endif
+  }
+
+public:
+  format_object(const char *fmt, const Ts &... vals)
+      : format_object_base(fmt), Vals(vals...) {}
+
+  int snprint(char *Buffer, unsigned BufferSize) const override {
+    return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>());
+  }
+};
+
+/// These are helper functions used to produce formatted output.  They use
+/// template type deduction to construct the appropriate instance of the
+/// format_object class to simplify their construction.
+///
+/// This is typically used like:
+/// \code
+///   OS << format("%0.4f", myfloat) << '\n';
+/// \endcode
+
+template <typename... Ts>
+inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) {
+  return format_object<Ts...>(Fmt, Vals...);
+}
+
+/// This is a helper class used for left_justify() and right_justify().
+class FormattedString {
+  StringRef Str;
+  unsigned Width;
+  bool RightJustify;
+  friend class raw_ostream;
+
+public:
+    FormattedString(StringRef S, unsigned W, bool R)
+      : Str(S), Width(W), RightJustify(R) { }
+};
+
+/// left_justify - append spaces after string so total output is
+/// \p Width characters.  If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString left_justify(StringRef Str, unsigned Width) {
+  return FormattedString(Str, Width, false);
+}
+
+/// right_justify - add spaces before string so total output is
+/// \p Width characters.  If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString right_justify(StringRef Str, unsigned Width) {
+  return FormattedString(Str, Width, true);
+}
+
+/// This is a helper class used for format_hex() and format_decimal().
+class FormattedNumber {
+  uint64_t HexValue;
+  int64_t DecValue;
+  unsigned Width;
+  bool Hex;
+  bool Upper;
+  bool HexPrefix;
+  friend class raw_ostream;
+
+public:
+  FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U,
+                  bool Prefix)
+      : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U),
+        HexPrefix(Prefix) {}
+};
+
+/// format_hex - Output \p N as a fixed width hexadecimal. If number will not
+/// fit in width, full number is still printed.  Examples:
+///   OS << format_hex(255, 4)              => 0xff
+///   OS << format_hex(255, 4, true)        => 0xFF
+///   OS << format_hex(255, 6)              => 0x00ff
+///   OS << format_hex(255, 2)              => 0xff
+inline FormattedNumber format_hex(uint64_t N, unsigned Width,
+                                  bool Upper = false) {
+  assert(Width <= 18 && "hex width must be <= 18");
+  return FormattedNumber(N, 0, Width, true, Upper, true);
+}
+
+/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not
+/// prepend '0x' to the outputted string.  If number will not fit in width,
+/// full number is still printed.  Examples:
+///   OS << format_hex_no_prefix(255, 2)              => ff
+///   OS << format_hex_no_prefix(255, 2, true)        => FF
+///   OS << format_hex_no_prefix(255, 4)              => 00ff
+///   OS << format_hex_no_prefix(255, 1)              => ff
+inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width,
+                                            bool Upper = false) {
+  assert(Width <= 16 && "hex width must be <= 16");
+  return FormattedNumber(N, 0, Width, true, Upper, false);
+}
+
+/// format_decimal - Output \p N as a right justified, fixed-width decimal. If
+/// number will not fit in width, full number is still printed.  Examples:
+///   OS << format_decimal(0, 5)     => "    0"
+///   OS << format_decimal(255, 5)   => "  255"
+///   OS << format_decimal(-1, 3)    => " -1"
+///   OS << format_decimal(12345, 3) => "12345"
+inline FormattedNumber format_decimal(int64_t N, unsigned Width) {
+  return FormattedNumber(0, N, Width, false, false, false);
+}
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Host.h b/third_party/llvm-subzero/include/llvm/Support/Host.h
new file mode 100644
index 0000000..9e59a94
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Host.h
@@ -0,0 +1,76 @@
+//===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Methods for querying the nature of the host machine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_HOST_H
+#define LLVM_SUPPORT_HOST_H
+
+#include "llvm/ADT/StringMap.h"
+
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
+#include <endian.h>
+#elif defined(_AIX)
+#include <sys/machine.h>
+#else
+#if !defined(BYTE_ORDER) && !defined(LLVM_ON_WIN32)
+#include <machine/endian.h>
+#endif
+#endif
+
+#include <string>
+
+namespace llvm {
+namespace sys {
+
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+  static const bool IsBigEndianHost = true;
+#else
+  static const bool IsBigEndianHost = false;
+#endif
+
+  static const bool IsLittleEndianHost = !IsBigEndianHost;
+
+  /// getDefaultTargetTriple() - Return the default target triple the compiler
+  /// has been configured to produce code for.
+  ///
+  /// The target triple is a string in the format of:
+  ///   CPU_TYPE-VENDOR-OPERATING_SYSTEM
+  /// or
+  ///   CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM
+  std::string getDefaultTargetTriple();
+
+  /// getProcessTriple() - Return an appropriate target triple for generating
+  /// code to be loaded into the current process, e.g. when using the JIT.
+  std::string getProcessTriple();
+
+  /// getHostCPUName - Get the LLVM name for the host CPU. The particular format
+  /// of the name is target dependent, and suitable for passing as -mcpu to the
+  /// target which matches the host.
+  ///
+  /// \return - The host CPU name, or empty if the CPU could not be determined.
+  StringRef getHostCPUName();
+
+  /// getHostCPUFeatures - Get the LLVM names for the host CPU features.
+  /// The particular format of the names are target dependent, and suitable for
+  /// passing as -mattr to the target which matches the host.
+  ///
+  /// \param Features - A string mapping feature names to either
+  /// true (if enabled) or false (if disabled). This routine makes no guarantees
+  /// about exactly which features may appear in this map, except that they are
+  /// all valid LLVM feature names.
+  ///
+  /// \return - True on success.
+  bool getHostCPUFeatures(StringMap<bool> &Features);
+}
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MD5.h b/third_party/llvm-subzero/include/llvm/Support/MD5.h
new file mode 100644
index 0000000..42d8ca8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MD5.h
@@ -0,0 +1,83 @@
+/*
+ * This code is derived from (original license follows):
+ *
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001.  No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md5.c for more information.
+ */
+
+#ifndef LLVM_SUPPORT_MD5_H
+#define LLVM_SUPPORT_MD5_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+template <typename T> class ArrayRef;
+
+class MD5 {
+  // Any 32-bit or wider unsigned integer data type will do.
+  typedef uint32_t MD5_u32plus;
+
+  MD5_u32plus a, b, c, d;
+  MD5_u32plus hi, lo;
+  uint8_t buffer[64];
+  MD5_u32plus block[16];
+
+public:
+  typedef uint8_t MD5Result[16];
+
+  MD5();
+
+  /// \brief Updates the hash for the byte stream provided.
+  void update(ArrayRef<uint8_t> Data);
+
+  /// \brief Updates the hash for the StringRef provided.
+  void update(StringRef Str);
+
+  /// \brief Finishes off the hash and puts the result in result.
+  void final(MD5Result &Result);
+
+  /// \brief Translates the bytes in \p Res to a hex string that is
+  /// deposited into \p Str. The result will be of length 32.
+  static void stringifyResult(MD5Result &Result, SmallString<32> &Str);
+
+private:
+  const uint8_t *body(ArrayRef<uint8_t> Data);
+};
+
+/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
+inline uint64_t MD5Hash(StringRef Str) {
+  MD5 Hash;
+  Hash.update(Str);
+  llvm::MD5::MD5Result Result;
+  Hash.final(Result);
+  // Return the least significant 8 bytes. Our MD5 implementation returns the
+  // result in little endian, so we may need to swap bytes.
+  using namespace llvm::support;
+  return endian::read<uint64_t, little, unaligned>(Result);
+}
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MachO.def b/third_party/llvm-subzero/include/llvm/Support/MachO.def
new file mode 100644
index 0000000..9ca6440
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MachO.def
@@ -0,0 +1,106 @@
+//,,,-- llvm/Support/MachO.def - The MachO file definitions -----*- C++ -*-,,,//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//,,,----------------------------------------------------------------------,,,//
+//
+// Definitions for MachO files
+//
+//,,,----------------------------------------------------------------------,,,//
+
+#ifdef HANDLE_LOAD_COMMAND
+
+HANDLE_LOAD_COMMAND(LC_SEGMENT, 0x00000001u, segment_command)
+HANDLE_LOAD_COMMAND(LC_SYMTAB, 0x00000002u, symtab_command)
+HANDLE_LOAD_COMMAND(LC_SYMSEG, 0x00000003u, symseg_command)
+HANDLE_LOAD_COMMAND(LC_THREAD, 0x00000004u, thread_command)
+HANDLE_LOAD_COMMAND(LC_UNIXTHREAD, 0x00000005u, thread_command)
+HANDLE_LOAD_COMMAND(LC_LOADFVMLIB, 0x00000006u, fvmlib_command)
+HANDLE_LOAD_COMMAND(LC_IDFVMLIB, 0x00000007u, fvmlib_command)
+HANDLE_LOAD_COMMAND(LC_IDENT, 0x00000008u, ident_command)
+HANDLE_LOAD_COMMAND(LC_FVMFILE, 0x00000009u, fvmfile_command)
+HANDLE_LOAD_COMMAND(LC_PREPAGE, 0x0000000Au, load_command)
+HANDLE_LOAD_COMMAND(LC_DYSYMTAB, 0x0000000Bu, dysymtab_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_DYLIB, 0x0000000Cu, dylib_command)
+HANDLE_LOAD_COMMAND(LC_ID_DYLIB, 0x0000000Du, dylib_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_DYLINKER, 0x0000000Eu, dylinker_command)
+HANDLE_LOAD_COMMAND(LC_ID_DYLINKER, 0x0000000Fu, dylinker_command)
+HANDLE_LOAD_COMMAND(LC_PREBOUND_DYLIB, 0x00000010u, prebound_dylib_command)
+HANDLE_LOAD_COMMAND(LC_ROUTINES, 0x00000011u, routines_command)
+HANDLE_LOAD_COMMAND(LC_SUB_FRAMEWORK, 0x00000012u, sub_framework_command)
+HANDLE_LOAD_COMMAND(LC_SUB_UMBRELLA, 0x00000013u, sub_umbrella_command)
+HANDLE_LOAD_COMMAND(LC_SUB_CLIENT, 0x00000014u, sub_client_command)
+HANDLE_LOAD_COMMAND(LC_SUB_LIBRARY, 0x00000015u, sub_library_command)
+HANDLE_LOAD_COMMAND(LC_TWOLEVEL_HINTS, 0x00000016u, twolevel_hints_command)
+HANDLE_LOAD_COMMAND(LC_PREBIND_CKSUM, 0x00000017u, prebind_cksum_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_WEAK_DYLIB, 0x80000018u, dylib_command)
+HANDLE_LOAD_COMMAND(LC_SEGMENT_64, 0x00000019u, segment_command_64)
+HANDLE_LOAD_COMMAND(LC_ROUTINES_64, 0x0000001Au, routines_command_64)
+HANDLE_LOAD_COMMAND(LC_UUID, 0x0000001Bu, uuid_command)
+HANDLE_LOAD_COMMAND(LC_RPATH, 0x8000001Cu, rpath_command)
+HANDLE_LOAD_COMMAND(LC_CODE_SIGNATURE, 0x0000001Du, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_SEGMENT_SPLIT_INFO, 0x0000001Eu, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_REEXPORT_DYLIB, 0x8000001Fu, dylib_command)
+HANDLE_LOAD_COMMAND(LC_LAZY_LOAD_DYLIB, 0x00000020u, dylib_command)
+HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO, 0x00000021u, encryption_info_command)
+HANDLE_LOAD_COMMAND(LC_DYLD_INFO, 0x00000022u, dyld_info_command)
+HANDLE_LOAD_COMMAND(LC_DYLD_INFO_ONLY, 0x80000022u, dyld_info_command)
+HANDLE_LOAD_COMMAND(LC_LOAD_UPWARD_DYLIB, 0x80000023u, dylib_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_MACOSX, 0x00000024u, version_min_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_IPHONEOS, 0x00000025u, version_min_command)
+HANDLE_LOAD_COMMAND(LC_FUNCTION_STARTS, 0x00000026u, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_DYLD_ENVIRONMENT, 0x00000027u, dylinker_command)
+HANDLE_LOAD_COMMAND(LC_MAIN, 0x80000028u, entry_point_command)
+HANDLE_LOAD_COMMAND(LC_DATA_IN_CODE, 0x00000029u, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_SOURCE_VERSION, 0x0000002Au, source_version_command)
+HANDLE_LOAD_COMMAND(LC_DYLIB_CODE_SIGN_DRS, 0x0000002Bu, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO_64, 0x0000002Cu,
+                    encryption_info_command_64)
+HANDLE_LOAD_COMMAND(LC_LINKER_OPTION, 0x0000002Du, linker_option_command)
+HANDLE_LOAD_COMMAND(LC_LINKER_OPTIMIZATION_HINT, 0x0000002Eu, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_TVOS, 0x0000002Fu, version_min_command)
+HANDLE_LOAD_COMMAND(LC_VERSION_MIN_WATCHOS, 0x00000030u, version_min_command)
+
+#endif
+
+#ifdef LOAD_COMMAND_STRUCT
+
+LOAD_COMMAND_STRUCT(dyld_info_command)
+LOAD_COMMAND_STRUCT(dylib_command)
+LOAD_COMMAND_STRUCT(dylinker_command)
+LOAD_COMMAND_STRUCT(dysymtab_command)
+LOAD_COMMAND_STRUCT(encryption_info_command)
+LOAD_COMMAND_STRUCT(encryption_info_command_64)
+LOAD_COMMAND_STRUCT(entry_point_command)
+LOAD_COMMAND_STRUCT(fvmfile_command)
+LOAD_COMMAND_STRUCT(fvmlib_command)
+LOAD_COMMAND_STRUCT(ident_command)
+LOAD_COMMAND_STRUCT(linkedit_data_command)
+LOAD_COMMAND_STRUCT(linker_option_command)
+LOAD_COMMAND_STRUCT(load_command)
+LOAD_COMMAND_STRUCT(prebind_cksum_command)
+LOAD_COMMAND_STRUCT(prebound_dylib_command)
+LOAD_COMMAND_STRUCT(routines_command)
+LOAD_COMMAND_STRUCT(routines_command_64)
+LOAD_COMMAND_STRUCT(rpath_command)
+LOAD_COMMAND_STRUCT(segment_command)
+LOAD_COMMAND_STRUCT(segment_command_64)
+LOAD_COMMAND_STRUCT(source_version_command)
+LOAD_COMMAND_STRUCT(sub_client_command)
+LOAD_COMMAND_STRUCT(sub_framework_command)
+LOAD_COMMAND_STRUCT(sub_library_command)
+LOAD_COMMAND_STRUCT(sub_umbrella_command)
+LOAD_COMMAND_STRUCT(symseg_command)
+LOAD_COMMAND_STRUCT(symtab_command)
+LOAD_COMMAND_STRUCT(thread_command)
+LOAD_COMMAND_STRUCT(twolevel_hints_command)
+LOAD_COMMAND_STRUCT(uuid_command)
+LOAD_COMMAND_STRUCT(version_min_command)
+
+#endif
+
+#undef HANDLE_LOAD_COMMAND
+#undef LOAD_COMMAND_STRUCT
diff --git a/third_party/llvm-subzero/include/llvm/Support/MachO.h b/third_party/llvm-subzero/include/llvm/Support/MachO.h
new file mode 100644
index 0000000..ebaaa7e
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MachO.h
@@ -0,0 +1,1723 @@
+//===-- llvm/Support/MachO.h - The MachO file format ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines manifest constants for the MachO object file format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MACHO_H
+#define LLVM_SUPPORT_MACHO_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Host.h"
+
+namespace llvm {
+  namespace MachO {
+    // Enums from <mach-o/loader.h>
+    enum : uint32_t {
+      // Constants for the "magic" field in llvm::MachO::mach_header and
+      // llvm::MachO::mach_header_64
+      MH_MAGIC    = 0xFEEDFACEu,
+      MH_CIGAM    = 0xCEFAEDFEu,
+      MH_MAGIC_64 = 0xFEEDFACFu,
+      MH_CIGAM_64 = 0xCFFAEDFEu,
+      FAT_MAGIC   = 0xCAFEBABEu,
+      FAT_CIGAM   = 0xBEBAFECAu,
+      FAT_MAGIC_64 = 0xCAFEBABFu,
+      FAT_CIGAM_64 = 0xBFBAFECAu
+    };
+
+    enum HeaderFileType {
+      // Constants for the "filetype" field in llvm::MachO::mach_header and
+      // llvm::MachO::mach_header_64
+      MH_OBJECT      = 0x1u,
+      MH_EXECUTE     = 0x2u,
+      MH_FVMLIB      = 0x3u,
+      MH_CORE        = 0x4u,
+      MH_PRELOAD     = 0x5u,
+      MH_DYLIB       = 0x6u,
+      MH_DYLINKER    = 0x7u,
+      MH_BUNDLE      = 0x8u,
+      MH_DYLIB_STUB  = 0x9u,
+      MH_DSYM        = 0xAu,
+      MH_KEXT_BUNDLE = 0xBu
+    };
+
+    enum {
+      // Constant bits for the "flags" field in llvm::MachO::mach_header and
+      // llvm::MachO::mach_header_64
+      MH_NOUNDEFS                = 0x00000001u,
+      MH_INCRLINK                = 0x00000002u,
+      MH_DYLDLINK                = 0x00000004u,
+      MH_BINDATLOAD              = 0x00000008u,
+      MH_PREBOUND                = 0x00000010u,
+      MH_SPLIT_SEGS              = 0x00000020u,
+      MH_LAZY_INIT               = 0x00000040u,
+      MH_TWOLEVEL                = 0x00000080u,
+      MH_FORCE_FLAT              = 0x00000100u,
+      MH_NOMULTIDEFS             = 0x00000200u,
+      MH_NOFIXPREBINDING         = 0x00000400u,
+      MH_PREBINDABLE             = 0x00000800u,
+      MH_ALLMODSBOUND            = 0x00001000u,
+      MH_SUBSECTIONS_VIA_SYMBOLS = 0x00002000u,
+      MH_CANONICAL               = 0x00004000u,
+      MH_WEAK_DEFINES            = 0x00008000u,
+      MH_BINDS_TO_WEAK           = 0x00010000u,
+      MH_ALLOW_STACK_EXECUTION   = 0x00020000u,
+      MH_ROOT_SAFE               = 0x00040000u,
+      MH_SETUID_SAFE             = 0x00080000u,
+      MH_NO_REEXPORTED_DYLIBS    = 0x00100000u,
+      MH_PIE                     = 0x00200000u,
+      MH_DEAD_STRIPPABLE_DYLIB   = 0x00400000u,
+      MH_HAS_TLV_DESCRIPTORS     = 0x00800000u,
+      MH_NO_HEAP_EXECUTION       = 0x01000000u,
+      MH_APP_EXTENSION_SAFE      = 0x02000000u
+    };
+
+    enum : uint32_t {
+      // Flags for the "cmd" field in llvm::MachO::load_command
+      LC_REQ_DYLD    = 0x80000000u
+    };
+
+#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
+    LCName = LCValue,
+
+    enum LoadCommandType : uint32_t {
+      #include "llvm/Support/MachO.def"
+    };
+
+#undef HANDLE_LOAD_COMMAND
+
+    enum : uint32_t {
+      // Constant bits for the "flags" field in llvm::MachO::segment_command
+      SG_HIGHVM              = 0x1u,
+      SG_FVMLIB              = 0x2u,
+      SG_NORELOC             = 0x4u,
+      SG_PROTECTED_VERSION_1 = 0x8u,
+
+      // Constant masks for the "flags" field in llvm::MachO::section and
+      // llvm::MachO::section_64
+      SECTION_TYPE           = 0x000000ffu, // SECTION_TYPE
+      SECTION_ATTRIBUTES     = 0xffffff00u, // SECTION_ATTRIBUTES
+      SECTION_ATTRIBUTES_USR = 0xff000000u, // SECTION_ATTRIBUTES_USR
+      SECTION_ATTRIBUTES_SYS = 0x00ffff00u  // SECTION_ATTRIBUTES_SYS
+    };
+
+    /// These are the section type and attributes fields.  A MachO section can
+    /// have only one Type, but can have any of the attributes specified.
+    enum SectionType : uint32_t {
+      // Constant masks for the "flags[7:0]" field in llvm::MachO::section and
+      // llvm::MachO::section_64 (mask "flags" with SECTION_TYPE)
+
+      /// S_REGULAR - Regular section.
+      S_REGULAR                             = 0x00u,
+      /// S_ZEROFILL - Zero fill on demand section.
+      S_ZEROFILL                            = 0x01u,
+      /// S_CSTRING_LITERALS - Section with literal C strings.
+      S_CSTRING_LITERALS                    = 0x02u,
+      /// S_4BYTE_LITERALS - Section with 4 byte literals.
+      S_4BYTE_LITERALS                      = 0x03u,
+      /// S_8BYTE_LITERALS - Section with 8 byte literals.
+      S_8BYTE_LITERALS                      = 0x04u,
+      /// S_LITERAL_POINTERS - Section with pointers to literals.
+      S_LITERAL_POINTERS                    = 0x05u,
+      /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers.
+      S_NON_LAZY_SYMBOL_POINTERS            = 0x06u,
+      /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers.
+      S_LAZY_SYMBOL_POINTERS                = 0x07u,
+      /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in
+      /// the Reserved2 field.
+      S_SYMBOL_STUBS                        = 0x08u,
+      /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for
+      /// initialization.
+      S_MOD_INIT_FUNC_POINTERS              = 0x09u,
+      /// S_MOD_TERM_FUNC_POINTERS - Section with only function pointers for
+      /// termination.
+      S_MOD_TERM_FUNC_POINTERS              = 0x0au,
+      /// S_COALESCED - Section contains symbols that are to be coalesced.
+      S_COALESCED                           = 0x0bu,
+      /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4
+      /// gigabytes).
+      S_GB_ZEROFILL                         = 0x0cu,
+      /// S_INTERPOSING - Section with only pairs of function pointers for
+      /// interposing.
+      S_INTERPOSING                         = 0x0du,
+      /// S_16BYTE_LITERALS - Section with only 16 byte literals.
+      S_16BYTE_LITERALS                     = 0x0eu,
+      /// S_DTRACE_DOF - Section contains DTrace Object Format.
+      S_DTRACE_DOF                          = 0x0fu,
+      /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to
+      /// lazy loaded dylibs.
+      S_LAZY_DYLIB_SYMBOL_POINTERS          = 0x10u,
+      /// S_THREAD_LOCAL_REGULAR - Thread local data section.
+      S_THREAD_LOCAL_REGULAR                = 0x11u,
+      /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section.
+      S_THREAD_LOCAL_ZEROFILL               = 0x12u,
+      /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable
+      /// structure data.
+      S_THREAD_LOCAL_VARIABLES              = 0x13u,
+      /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with pointers to thread
+      /// local structures.
+      S_THREAD_LOCAL_VARIABLE_POINTERS      = 0x14u,
+      /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local
+      /// variable initialization pointers to functions.
+      S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u,
+
+      LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS
+    };
+
+    enum : uint32_t {
+      // Constant masks for the "flags[31:24]" field in llvm::MachO::section and
+      // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR)
+
+      /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine
+      /// instructions.
+      S_ATTR_PURE_INSTRUCTIONS   = 0x80000000u,
+      /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be
+      /// in a ranlib table of contents.
+      S_ATTR_NO_TOC              = 0x40000000u,
+      /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section
+      /// in files with the MY_DYLDLINK flag.
+      S_ATTR_STRIP_STATIC_SYMS   = 0x20000000u,
+      /// S_ATTR_NO_DEAD_STRIP - No dead stripping.
+      S_ATTR_NO_DEAD_STRIP       = 0x10000000u,
+      /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks.
+      S_ATTR_LIVE_SUPPORT        = 0x08000000u,
+      /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by
+      /// dyld.
+      S_ATTR_SELF_MODIFYING_CODE = 0x04000000u,
+      /// S_ATTR_DEBUG - A debug section.
+      S_ATTR_DEBUG               = 0x02000000u,
+
+      // Constant masks for the "flags[23:8]" field in llvm::MachO::section and
+      // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_SYS)
+
+      /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions.
+      S_ATTR_SOME_INSTRUCTIONS   = 0x00000400u,
+      /// S_ATTR_EXT_RELOC - Section has external relocation entries.
+      S_ATTR_EXT_RELOC           = 0x00000200u,
+      /// S_ATTR_LOC_RELOC - Section has local relocation entries.
+      S_ATTR_LOC_RELOC           = 0x00000100u,
+
+      // Constant masks for the value of an indirect symbol in an indirect
+      // symbol table
+      INDIRECT_SYMBOL_LOCAL = 0x80000000u,
+      INDIRECT_SYMBOL_ABS   = 0x40000000u
+    };
+
+    enum DataRegionType {
+      // Constants for the "kind" field in a data_in_code_entry structure
+      DICE_KIND_DATA             = 1u,
+      DICE_KIND_JUMP_TABLE8      = 2u,
+      DICE_KIND_JUMP_TABLE16     = 3u,
+      DICE_KIND_JUMP_TABLE32     = 4u,
+      DICE_KIND_ABS_JUMP_TABLE32 = 5u
+    };
+
+    enum RebaseType {
+      REBASE_TYPE_POINTER         = 1u,
+      REBASE_TYPE_TEXT_ABSOLUTE32 = 2u,
+      REBASE_TYPE_TEXT_PCREL32    = 3u
+    };
+
+    enum {
+      REBASE_OPCODE_MASK    = 0xF0u,
+      REBASE_IMMEDIATE_MASK = 0x0Fu
+    };
+
+    enum RebaseOpcode {
+      REBASE_OPCODE_DONE                               = 0x00u,
+      REBASE_OPCODE_SET_TYPE_IMM                       = 0x10u,
+      REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB        = 0x20u,
+      REBASE_OPCODE_ADD_ADDR_ULEB                      = 0x30u,
+      REBASE_OPCODE_ADD_ADDR_IMM_SCALED                = 0x40u,
+      REBASE_OPCODE_DO_REBASE_IMM_TIMES                = 0x50u,
+      REBASE_OPCODE_DO_REBASE_ULEB_TIMES               = 0x60u,
+      REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB            = 0x70u,
+      REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80u
+    };
+
+    enum BindType {
+      BIND_TYPE_POINTER         = 1u,
+      BIND_TYPE_TEXT_ABSOLUTE32 = 2u,
+      BIND_TYPE_TEXT_PCREL32    = 3u
+    };
+
+    enum BindSpecialDylib {
+      BIND_SPECIAL_DYLIB_SELF            =  0,
+      BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1,
+      BIND_SPECIAL_DYLIB_FLAT_LOOKUP     = -2
+    };
+
+    enum {
+      BIND_SYMBOL_FLAGS_WEAK_IMPORT         = 0x1u,
+      BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8u,
+
+      BIND_OPCODE_MASK                      = 0xF0u,
+      BIND_IMMEDIATE_MASK                   = 0x0Fu
+    };
+
+    enum BindOpcode {
+      BIND_OPCODE_DONE                             = 0x00u,
+      BIND_OPCODE_SET_DYLIB_ORDINAL_IMM            = 0x10u,
+      BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB           = 0x20u,
+      BIND_OPCODE_SET_DYLIB_SPECIAL_IMM            = 0x30u,
+      BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM    = 0x40u,
+      BIND_OPCODE_SET_TYPE_IMM                     = 0x50u,
+      BIND_OPCODE_SET_ADDEND_SLEB                  = 0x60u,
+      BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB      = 0x70u,
+      BIND_OPCODE_ADD_ADDR_ULEB                    = 0x80u,
+      BIND_OPCODE_DO_BIND                          = 0x90u,
+      BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB            = 0xA0u,
+      BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED      = 0xB0u,
+      BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0u
+    };
+
+    enum {
+      EXPORT_SYMBOL_FLAGS_KIND_MASK           = 0x03u,
+      EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION     = 0x04u,
+      EXPORT_SYMBOL_FLAGS_REEXPORT            = 0x08u,
+      EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER   = 0x10u
+    };
+
+    enum ExportSymbolKind {
+      EXPORT_SYMBOL_FLAGS_KIND_REGULAR        = 0x00u,
+      EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL   = 0x01u,
+      EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE       = 0x02u
+    };
+
+    enum {
+      // Constant masks for the "n_type" field in llvm::MachO::nlist and
+      // llvm::MachO::nlist_64
+      N_STAB = 0xe0,
+      N_PEXT = 0x10,
+      N_TYPE = 0x0e,
+      N_EXT  = 0x01
+    };
+
+    enum NListType : uint8_t {
+      // Constants for the "n_type & N_TYPE" llvm::MachO::nlist and
+      // llvm::MachO::nlist_64
+      N_UNDF = 0x0u,
+      N_ABS  = 0x2u,
+      N_SECT = 0xeu,
+      N_PBUD = 0xcu,
+      N_INDR = 0xau
+    };
+
+    enum SectionOrdinal {
+      // Constants for the "n_sect" field in llvm::MachO::nlist and
+      // llvm::MachO::nlist_64
+      NO_SECT  = 0u,
+      MAX_SECT = 0xffu
+    };
+
+    enum {
+      // Constant masks for the "n_desc" field in llvm::MachO::nlist and
+      // llvm::MachO::nlist_64
+      // The low 3 bits are the for the REFERENCE_TYPE.
+      REFERENCE_TYPE                            = 0x7,
+      REFERENCE_FLAG_UNDEFINED_NON_LAZY         = 0,
+      REFERENCE_FLAG_UNDEFINED_LAZY             = 1,
+      REFERENCE_FLAG_DEFINED                    = 2,
+      REFERENCE_FLAG_PRIVATE_DEFINED            = 3,
+      REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
+      REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY     = 5,
+      // Flag bits (some overlap with the library ordinal bits).
+      N_ARM_THUMB_DEF   = 0x0008u,
+      REFERENCED_DYNAMICALLY = 0x0010u,
+      N_NO_DEAD_STRIP   = 0x0020u,
+      N_WEAK_REF        = 0x0040u,
+      N_WEAK_DEF        = 0x0080u,
+      N_SYMBOL_RESOLVER = 0x0100u,
+      N_ALT_ENTRY       = 0x0200u,
+      // For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL()
+      // as these are in the top 8 bits.
+      SELF_LIBRARY_ORDINAL   = 0x0,
+      MAX_LIBRARY_ORDINAL    = 0xfd,
+      DYNAMIC_LOOKUP_ORDINAL = 0xfe,
+      EXECUTABLE_ORDINAL     = 0xff
+    };
+
+    enum StabType {
+      // Constant values for the "n_type" field in llvm::MachO::nlist and
+      // llvm::MachO::nlist_64 when "(n_type & N_STAB) != 0"
+      N_GSYM    = 0x20u,
+      N_FNAME   = 0x22u,
+      N_FUN     = 0x24u,
+      N_STSYM   = 0x26u,
+      N_LCSYM   = 0x28u,
+      N_BNSYM   = 0x2Eu,
+      N_PC      = 0x30u,
+      N_AST     = 0x32u,
+      N_OPT     = 0x3Cu,
+      N_RSYM    = 0x40u,
+      N_SLINE   = 0x44u,
+      N_ENSYM   = 0x4Eu,
+      N_SSYM    = 0x60u,
+      N_SO      = 0x64u,
+      N_OSO     = 0x66u,
+      N_LSYM    = 0x80u,
+      N_BINCL   = 0x82u,
+      N_SOL     = 0x84u,
+      N_PARAMS  = 0x86u,
+      N_VERSION = 0x88u,
+      N_OLEVEL  = 0x8Au,
+      N_PSYM    = 0xA0u,
+      N_EINCL   = 0xA2u,
+      N_ENTRY   = 0xA4u,
+      N_LBRAC   = 0xC0u,
+      N_EXCL    = 0xC2u,
+      N_RBRAC   = 0xE0u,
+      N_BCOMM   = 0xE2u,
+      N_ECOMM   = 0xE4u,
+      N_ECOML   = 0xE8u,
+      N_LENG    = 0xFEu
+    };
+
+    enum : uint32_t {
+      // Constant values for the r_symbolnum field in an
+      // llvm::MachO::relocation_info structure when r_extern is 0.
+      R_ABS = 0,
+
+      // Constant bits for the r_address field in an
+      // llvm::MachO::relocation_info structure.
+      R_SCATTERED = 0x80000000
+    };
+
+    enum RelocationInfoType {
+      // Constant values for the r_type field in an
+      // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info
+      // structure.
+      GENERIC_RELOC_VANILLA        = 0,
+      GENERIC_RELOC_PAIR           = 1,
+      GENERIC_RELOC_SECTDIFF       = 2,
+      GENERIC_RELOC_PB_LA_PTR      = 3,
+      GENERIC_RELOC_LOCAL_SECTDIFF = 4,
+      GENERIC_RELOC_TLV            = 5,
+
+      // Constant values for the r_type field in a PowerPC architecture
+      // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info
+      // structure.
+      PPC_RELOC_VANILLA            = GENERIC_RELOC_VANILLA,
+      PPC_RELOC_PAIR               = GENERIC_RELOC_PAIR,
+      PPC_RELOC_BR14               = 2,
+      PPC_RELOC_BR24               = 3,
+      PPC_RELOC_HI16               = 4,
+      PPC_RELOC_LO16               = 5,
+      PPC_RELOC_HA16               = 6,
+      PPC_RELOC_LO14               = 7,
+      PPC_RELOC_SECTDIFF           = 8,
+      PPC_RELOC_PB_LA_PTR          = 9,
+      PPC_RELOC_HI16_SECTDIFF      = 10,
+      PPC_RELOC_LO16_SECTDIFF      = 11,
+      PPC_RELOC_HA16_SECTDIFF      = 12,
+      PPC_RELOC_JBSR               = 13,
+      PPC_RELOC_LO14_SECTDIFF      = 14,
+      PPC_RELOC_LOCAL_SECTDIFF     = 15,
+
+      // Constant values for the r_type field in an ARM architecture
+      // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info
+      // structure.
+      ARM_RELOC_VANILLA            = GENERIC_RELOC_VANILLA,
+      ARM_RELOC_PAIR               = GENERIC_RELOC_PAIR,
+      ARM_RELOC_SECTDIFF           = GENERIC_RELOC_SECTDIFF,
+      ARM_RELOC_LOCAL_SECTDIFF     = 3,
+      ARM_RELOC_PB_LA_PTR          = 4,
+      ARM_RELOC_BR24               = 5,
+      ARM_THUMB_RELOC_BR22         = 6,
+      ARM_THUMB_32BIT_BRANCH       = 7, // obsolete
+      ARM_RELOC_HALF               = 8,
+      ARM_RELOC_HALF_SECTDIFF      = 9,
+
+      // Constant values for the r_type field in an ARM64 architecture
+      // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info
+      // structure.
+
+      // For pointers.
+      ARM64_RELOC_UNSIGNED            = 0,
+      // Must be followed by an ARM64_RELOC_UNSIGNED
+      ARM64_RELOC_SUBTRACTOR          = 1,
+      // A B/BL instruction with 26-bit displacement.
+      ARM64_RELOC_BRANCH26            = 2,
+      // PC-rel distance to page of target.
+      ARM64_RELOC_PAGE21              = 3,
+      // Offset within page, scaled by r_length.
+      ARM64_RELOC_PAGEOFF12           = 4,
+      // PC-rel distance to page of GOT slot.
+      ARM64_RELOC_GOT_LOAD_PAGE21     = 5,
+      // Offset within page of GOT slot, scaled by r_length.
+      ARM64_RELOC_GOT_LOAD_PAGEOFF12  = 6,
+      // For pointers to GOT slots.
+      ARM64_RELOC_POINTER_TO_GOT      = 7,
+      // PC-rel distance to page of TLVP slot.
+      ARM64_RELOC_TLVP_LOAD_PAGE21    = 8,
+      // Offset within page of TLVP slot, scaled by r_length.
+      ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9,
+      // Must be followed by ARM64_RELOC_PAGE21 or ARM64_RELOC_PAGEOFF12.
+      ARM64_RELOC_ADDEND              = 10,
+
+      // Constant values for the r_type field in an x86_64 architecture
+      // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info
+      // structure
+      X86_64_RELOC_UNSIGNED        = 0,
+      X86_64_RELOC_SIGNED          = 1,
+      X86_64_RELOC_BRANCH          = 2,
+      X86_64_RELOC_GOT_LOAD        = 3,
+      X86_64_RELOC_GOT             = 4,
+      X86_64_RELOC_SUBTRACTOR      = 5,
+      X86_64_RELOC_SIGNED_1        = 6,
+      X86_64_RELOC_SIGNED_2        = 7,
+      X86_64_RELOC_SIGNED_4        = 8,
+      X86_64_RELOC_TLV             = 9
+    };
+
+    // Values for segment_command.initprot.
+    // From <mach/vm_prot.h>
+    enum {
+      VM_PROT_READ    = 0x1,
+      VM_PROT_WRITE   = 0x2,
+      VM_PROT_EXECUTE = 0x4
+    };
+
+    // Structs from <mach-o/loader.h>
+
+    struct mach_header {
+      uint32_t magic;
+      uint32_t cputype;
+      uint32_t cpusubtype;
+      uint32_t filetype;
+      uint32_t ncmds;
+      uint32_t sizeofcmds;
+      uint32_t flags;
+    };
+
+    struct mach_header_64 {
+      uint32_t magic;
+      uint32_t cputype;
+      uint32_t cpusubtype;
+      uint32_t filetype;
+      uint32_t ncmds;
+      uint32_t sizeofcmds;
+      uint32_t flags;
+      uint32_t reserved;
+    };
+
+    struct load_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+    };
+
+    struct segment_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      char segname[16];
+      uint32_t vmaddr;
+      uint32_t vmsize;
+      uint32_t fileoff;
+      uint32_t filesize;
+      uint32_t maxprot;
+      uint32_t initprot;
+      uint32_t nsects;
+      uint32_t flags;
+    };
+
+    struct segment_command_64 {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      char segname[16];
+      uint64_t vmaddr;
+      uint64_t vmsize;
+      uint64_t fileoff;
+      uint64_t filesize;
+      uint32_t maxprot;
+      uint32_t initprot;
+      uint32_t nsects;
+      uint32_t flags;
+    };
+
+    struct section {
+      char sectname[16];
+      char segname[16];
+      uint32_t addr;
+      uint32_t size;
+      uint32_t offset;
+      uint32_t align;
+      uint32_t reloff;
+      uint32_t nreloc;
+      uint32_t flags;
+      uint32_t reserved1;
+      uint32_t reserved2;
+    };
+
+    struct section_64 {
+      char sectname[16];
+      char segname[16];
+      uint64_t addr;
+      uint64_t size;
+      uint32_t offset;
+      uint32_t align;
+      uint32_t reloff;
+      uint32_t nreloc;
+      uint32_t flags;
+      uint32_t reserved1;
+      uint32_t reserved2;
+      uint32_t reserved3;
+    };
+
+    struct fvmlib {
+      uint32_t name;
+      uint32_t minor_version;
+      uint32_t header_addr;
+    };
+
+    struct fvmlib_command {
+      uint32_t  cmd;
+      uint32_t cmdsize;
+      struct fvmlib fvmlib;
+    };
+
+    struct dylib {
+      uint32_t name;
+      uint32_t timestamp;
+      uint32_t current_version;
+      uint32_t compatibility_version;
+    };
+
+    struct dylib_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      struct dylib dylib;
+    };
+
+    struct sub_framework_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t umbrella;
+    };
+
+    struct sub_client_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t client;
+    };
+
+    struct sub_umbrella_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t sub_umbrella;
+    };
+
+    struct sub_library_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t sub_library;
+    };
+
+    struct prebound_dylib_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t name;
+      uint32_t nmodules;
+      uint32_t linked_modules;
+    };
+
+    struct dylinker_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t name;
+    };
+
+    struct thread_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+    };
+
+    struct routines_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t init_address;
+      uint32_t init_module;
+      uint32_t reserved1;
+      uint32_t reserved2;
+      uint32_t reserved3;
+      uint32_t reserved4;
+      uint32_t reserved5;
+      uint32_t reserved6;
+    };
+
+    struct routines_command_64 {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint64_t init_address;
+      uint64_t init_module;
+      uint64_t reserved1;
+      uint64_t reserved2;
+      uint64_t reserved3;
+      uint64_t reserved4;
+      uint64_t reserved5;
+      uint64_t reserved6;
+    };
+
+    struct symtab_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t symoff;
+      uint32_t nsyms;
+      uint32_t stroff;
+      uint32_t strsize;
+    };
+
+    struct dysymtab_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t ilocalsym;
+      uint32_t nlocalsym;
+      uint32_t iextdefsym;
+      uint32_t nextdefsym;
+      uint32_t iundefsym;
+      uint32_t nundefsym;
+      uint32_t tocoff;
+      uint32_t ntoc;
+      uint32_t modtaboff;
+      uint32_t nmodtab;
+      uint32_t extrefsymoff;
+      uint32_t nextrefsyms;
+      uint32_t indirectsymoff;
+      uint32_t nindirectsyms;
+      uint32_t extreloff;
+      uint32_t nextrel;
+      uint32_t locreloff;
+      uint32_t nlocrel;
+    };
+
+    struct dylib_table_of_contents {
+      uint32_t symbol_index;
+      uint32_t module_index;
+    };
+
+    struct dylib_module {
+      uint32_t module_name;
+      uint32_t iextdefsym;
+      uint32_t nextdefsym;
+      uint32_t irefsym;
+      uint32_t nrefsym;
+      uint32_t ilocalsym;
+      uint32_t nlocalsym;
+      uint32_t iextrel;
+      uint32_t nextrel;
+      uint32_t iinit_iterm;
+      uint32_t ninit_nterm;
+      uint32_t objc_module_info_addr;
+      uint32_t objc_module_info_size;
+    };
+
+    struct dylib_module_64 {
+      uint32_t module_name;
+      uint32_t iextdefsym;
+      uint32_t nextdefsym;
+      uint32_t irefsym;
+      uint32_t nrefsym;
+      uint32_t ilocalsym;
+      uint32_t nlocalsym;
+      uint32_t iextrel;
+      uint32_t nextrel;
+      uint32_t iinit_iterm;
+      uint32_t ninit_nterm;
+      uint32_t objc_module_info_size;
+      uint64_t objc_module_info_addr;
+    };
+
+    struct dylib_reference {
+      uint32_t isym:24,
+               flags:8;
+    };
+
+    struct twolevel_hints_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t offset;
+      uint32_t nhints;
+    };
+
+    struct twolevel_hint {
+      uint32_t isub_image:8,
+               itoc:24;
+    };
+
+    struct prebind_cksum_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t cksum;
+    };
+
+    struct uuid_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint8_t uuid[16];
+    };
+
+    struct rpath_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t path;
+    };
+
+    struct linkedit_data_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t dataoff;
+      uint32_t datasize;
+    };
+
+    struct data_in_code_entry {
+      uint32_t offset;
+      uint16_t length;
+      uint16_t kind;
+    };
+
+    struct source_version_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint64_t version;
+    };
+
+    struct encryption_info_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t cryptoff;
+      uint32_t cryptsize;
+      uint32_t cryptid;
+    };
+
+    struct encryption_info_command_64 {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t cryptoff;
+      uint32_t cryptsize;
+      uint32_t cryptid;
+      uint32_t pad;
+    };
+
+    struct version_min_command {
+      uint32_t cmd;       // LC_VERSION_MIN_MACOSX or
+                          // LC_VERSION_MIN_IPHONEOS
+      uint32_t cmdsize;   // sizeof(struct version_min_command)
+      uint32_t version;   // X.Y.Z is encoded in nibbles xxxx.yy.zz
+      uint32_t sdk;       // X.Y.Z is encoded in nibbles xxxx.yy.zz
+    };
+
+    struct dyld_info_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t rebase_off;
+      uint32_t rebase_size;
+      uint32_t bind_off;
+      uint32_t bind_size;
+      uint32_t weak_bind_off;
+      uint32_t weak_bind_size;
+      uint32_t lazy_bind_off;
+      uint32_t lazy_bind_size;
+      uint32_t export_off;
+      uint32_t export_size;
+    };
+
+    struct linker_option_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t count;
+    };
+
+    struct symseg_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t offset;
+      uint32_t size;
+    };
+
+    struct ident_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+    };
+
+    struct fvmfile_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint32_t name;
+      uint32_t header_addr;
+    };
+
+    struct tlv_descriptor_32 {
+      uint32_t thunk;
+      uint32_t key;
+      uint32_t offset;
+    };
+
+    struct tlv_descriptor_64 {
+      uint64_t thunk;
+      uint64_t key;
+      uint64_t offset;
+    };
+
+    struct tlv_descriptor {
+      uintptr_t thunk;
+      uintptr_t key;
+      uintptr_t offset;
+    };
+
+    struct entry_point_command {
+      uint32_t cmd;
+      uint32_t cmdsize;
+      uint64_t entryoff;
+      uint64_t stacksize;
+    };
+
+    // Structs from <mach-o/fat.h>
+    struct fat_header {
+      uint32_t magic;
+      uint32_t nfat_arch;
+    };
+
+    struct fat_arch {
+      uint32_t cputype;
+      uint32_t cpusubtype;
+      uint32_t offset;
+      uint32_t size;
+      uint32_t align;
+    };
+
+    struct fat_arch_64 {
+      uint32_t cputype;
+      uint32_t cpusubtype;
+      uint64_t offset;
+      uint64_t size;
+      uint32_t align;
+      uint32_t reserved;
+    };
+
+    // Structs from <mach-o/reloc.h>
+    struct relocation_info {
+      int32_t r_address;
+      uint32_t r_symbolnum:24,
+               r_pcrel:1,
+               r_length:2,
+               r_extern:1,
+               r_type:4;
+    };
+
+    struct scattered_relocation_info {
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN)
+      uint32_t r_scattered:1,
+               r_pcrel:1,
+               r_length:2,
+               r_type:4,
+               r_address:24;
+#else
+      uint32_t r_address:24,
+               r_type:4,
+               r_length:2,
+               r_pcrel:1,
+               r_scattered:1;
+#endif
+      int32_t r_value;
+    };
+
+    // Structs NOT from <mach-o/reloc.h>, but that make LLVM's life easier
+    struct any_relocation_info {
+      uint32_t r_word0, r_word1;
+    };
+
+    // Structs from <mach-o/nlist.h>
+    struct nlist_base {
+      uint32_t n_strx;
+      uint8_t n_type;
+      uint8_t n_sect;
+      uint16_t n_desc;
+    };
+
+    struct nlist {
+      uint32_t n_strx;
+      uint8_t n_type;
+      uint8_t n_sect;
+      int16_t n_desc;
+      uint32_t n_value;
+    };
+
+    struct nlist_64 {
+      uint32_t n_strx;
+      uint8_t n_type;
+      uint8_t n_sect;
+      uint16_t n_desc;
+      uint64_t n_value;
+    };
+
+    // Byte order swapping functions for MachO structs
+
+    inline void swapStruct(fat_header &mh) {
+      sys::swapByteOrder(mh.magic);
+      sys::swapByteOrder(mh.nfat_arch);
+    }
+
+    inline void swapStruct(fat_arch &mh) {
+      sys::swapByteOrder(mh.cputype);
+      sys::swapByteOrder(mh.cpusubtype);
+      sys::swapByteOrder(mh.offset);
+      sys::swapByteOrder(mh.size);
+      sys::swapByteOrder(mh.align);
+    }
+
+    inline void swapStruct(fat_arch_64 &mh) {
+      sys::swapByteOrder(mh.cputype);
+      sys::swapByteOrder(mh.cpusubtype);
+      sys::swapByteOrder(mh.offset);
+      sys::swapByteOrder(mh.size);
+      sys::swapByteOrder(mh.align);
+      sys::swapByteOrder(mh.reserved);
+    }
+
+    inline void swapStruct(mach_header &mh) {
+      sys::swapByteOrder(mh.magic);
+      sys::swapByteOrder(mh.cputype);
+      sys::swapByteOrder(mh.cpusubtype);
+      sys::swapByteOrder(mh.filetype);
+      sys::swapByteOrder(mh.ncmds);
+      sys::swapByteOrder(mh.sizeofcmds);
+      sys::swapByteOrder(mh.flags);
+    }
+
+    inline void swapStruct(mach_header_64 &H) {
+      sys::swapByteOrder(H.magic);
+      sys::swapByteOrder(H.cputype);
+      sys::swapByteOrder(H.cpusubtype);
+      sys::swapByteOrder(H.filetype);
+      sys::swapByteOrder(H.ncmds);
+      sys::swapByteOrder(H.sizeofcmds);
+      sys::swapByteOrder(H.flags);
+      sys::swapByteOrder(H.reserved);
+    }
+
+    inline void swapStruct(load_command &lc) {
+      sys::swapByteOrder(lc.cmd);
+      sys::swapByteOrder(lc.cmdsize);
+    }
+
+    inline void swapStruct(symtab_command &lc) {
+      sys::swapByteOrder(lc.cmd);
+      sys::swapByteOrder(lc.cmdsize);
+      sys::swapByteOrder(lc.symoff);
+      sys::swapByteOrder(lc.nsyms);
+      sys::swapByteOrder(lc.stroff);
+      sys::swapByteOrder(lc.strsize);
+    }
+
+    inline void swapStruct(segment_command_64 &seg) {
+      sys::swapByteOrder(seg.cmd);
+      sys::swapByteOrder(seg.cmdsize);
+      sys::swapByteOrder(seg.vmaddr);
+      sys::swapByteOrder(seg.vmsize);
+      sys::swapByteOrder(seg.fileoff);
+      sys::swapByteOrder(seg.filesize);
+      sys::swapByteOrder(seg.maxprot);
+      sys::swapByteOrder(seg.initprot);
+      sys::swapByteOrder(seg.nsects);
+      sys::swapByteOrder(seg.flags);
+    }
+
+    inline void swapStruct(segment_command &seg) {
+      sys::swapByteOrder(seg.cmd);
+      sys::swapByteOrder(seg.cmdsize);
+      sys::swapByteOrder(seg.vmaddr);
+      sys::swapByteOrder(seg.vmsize);
+      sys::swapByteOrder(seg.fileoff);
+      sys::swapByteOrder(seg.filesize);
+      sys::swapByteOrder(seg.maxprot);
+      sys::swapByteOrder(seg.initprot);
+      sys::swapByteOrder(seg.nsects);
+      sys::swapByteOrder(seg.flags);
+    }
+
+    inline void swapStruct(section_64 &sect) {
+      sys::swapByteOrder(sect.addr);
+      sys::swapByteOrder(sect.size);
+      sys::swapByteOrder(sect.offset);
+      sys::swapByteOrder(sect.align);
+      sys::swapByteOrder(sect.reloff);
+      sys::swapByteOrder(sect.nreloc);
+      sys::swapByteOrder(sect.flags);
+      sys::swapByteOrder(sect.reserved1);
+      sys::swapByteOrder(sect.reserved2);
+    }
+
+    inline void swapStruct(section &sect) {
+      sys::swapByteOrder(sect.addr);
+      sys::swapByteOrder(sect.size);
+      sys::swapByteOrder(sect.offset);
+      sys::swapByteOrder(sect.align);
+      sys::swapByteOrder(sect.reloff);
+      sys::swapByteOrder(sect.nreloc);
+      sys::swapByteOrder(sect.flags);
+      sys::swapByteOrder(sect.reserved1);
+      sys::swapByteOrder(sect.reserved2);
+    }
+
+    inline void swapStruct(dyld_info_command &info) {
+      sys::swapByteOrder(info.cmd);
+      sys::swapByteOrder(info.cmdsize);
+      sys::swapByteOrder(info.rebase_off);
+      sys::swapByteOrder(info.rebase_size);
+      sys::swapByteOrder(info.bind_off);
+      sys::swapByteOrder(info.bind_size);
+      sys::swapByteOrder(info.weak_bind_off);
+      sys::swapByteOrder(info.weak_bind_size);
+      sys::swapByteOrder(info.lazy_bind_off);
+      sys::swapByteOrder(info.lazy_bind_size);
+      sys::swapByteOrder(info.export_off);
+      sys::swapByteOrder(info.export_size);
+    }
+
+    inline void swapStruct(dylib_command &d) {
+      sys::swapByteOrder(d.cmd);
+      sys::swapByteOrder(d.cmdsize);
+      sys::swapByteOrder(d.dylib.name);
+      sys::swapByteOrder(d.dylib.timestamp);
+      sys::swapByteOrder(d.dylib.current_version);
+      sys::swapByteOrder(d.dylib.compatibility_version);
+    }
+
+    inline void swapStruct(sub_framework_command &s) {
+      sys::swapByteOrder(s.cmd);
+      sys::swapByteOrder(s.cmdsize);
+      sys::swapByteOrder(s.umbrella);
+    }
+
+    inline void swapStruct(sub_umbrella_command &s) {
+      sys::swapByteOrder(s.cmd);
+      sys::swapByteOrder(s.cmdsize);
+      sys::swapByteOrder(s.sub_umbrella);
+    }
+
+    inline void swapStruct(sub_library_command &s) {
+      sys::swapByteOrder(s.cmd);
+      sys::swapByteOrder(s.cmdsize);
+      sys::swapByteOrder(s.sub_library);
+    }
+
+    inline void swapStruct(sub_client_command &s) {
+      sys::swapByteOrder(s.cmd);
+      sys::swapByteOrder(s.cmdsize);
+      sys::swapByteOrder(s.client);
+    }
+
+    inline void swapStruct(routines_command &r) {
+      sys::swapByteOrder(r.cmd);
+      sys::swapByteOrder(r.cmdsize);
+      sys::swapByteOrder(r.init_address);
+      sys::swapByteOrder(r.init_module);
+      sys::swapByteOrder(r.reserved1);
+      sys::swapByteOrder(r.reserved2);
+      sys::swapByteOrder(r.reserved3);
+      sys::swapByteOrder(r.reserved4);
+      sys::swapByteOrder(r.reserved5);
+      sys::swapByteOrder(r.reserved6);
+    }
+
+    inline void swapStruct(routines_command_64 &r) {
+      sys::swapByteOrder(r.cmd);
+      sys::swapByteOrder(r.cmdsize);
+      sys::swapByteOrder(r.init_address);
+      sys::swapByteOrder(r.init_module);
+      sys::swapByteOrder(r.reserved1);
+      sys::swapByteOrder(r.reserved2);
+      sys::swapByteOrder(r.reserved3);
+      sys::swapByteOrder(r.reserved4);
+      sys::swapByteOrder(r.reserved5);
+      sys::swapByteOrder(r.reserved6);
+    }
+
+    inline void swapStruct(thread_command &t) {
+      sys::swapByteOrder(t.cmd);
+      sys::swapByteOrder(t.cmdsize);
+    }
+
+    inline void swapStruct(dylinker_command &d) {
+      sys::swapByteOrder(d.cmd);
+      sys::swapByteOrder(d.cmdsize);
+      sys::swapByteOrder(d.name);
+    }
+
+    inline void swapStruct(uuid_command &u) {
+      sys::swapByteOrder(u.cmd);
+      sys::swapByteOrder(u.cmdsize);
+    }
+
+    inline void swapStruct(rpath_command &r) {
+      sys::swapByteOrder(r.cmd);
+      sys::swapByteOrder(r.cmdsize);
+      sys::swapByteOrder(r.path);
+    }
+
+    inline void swapStruct(source_version_command &s) {
+      sys::swapByteOrder(s.cmd);
+      sys::swapByteOrder(s.cmdsize);
+      sys::swapByteOrder(s.version);
+    }
+
+    inline void swapStruct(entry_point_command &e) {
+      sys::swapByteOrder(e.cmd);
+      sys::swapByteOrder(e.cmdsize);
+      sys::swapByteOrder(e.entryoff);
+      sys::swapByteOrder(e.stacksize);
+    }
+
+    inline void swapStruct(encryption_info_command &e) {
+      sys::swapByteOrder(e.cmd);
+      sys::swapByteOrder(e.cmdsize);
+      sys::swapByteOrder(e.cryptoff);
+      sys::swapByteOrder(e.cryptsize);
+      sys::swapByteOrder(e.cryptid);
+    }
+
+    inline void swapStruct(encryption_info_command_64 &e) {
+      sys::swapByteOrder(e.cmd);
+      sys::swapByteOrder(e.cmdsize);
+      sys::swapByteOrder(e.cryptoff);
+      sys::swapByteOrder(e.cryptsize);
+      sys::swapByteOrder(e.cryptid);
+      sys::swapByteOrder(e.pad);
+    }
+
+    inline void swapStruct(dysymtab_command &dst) {
+      sys::swapByteOrder(dst.cmd);
+      sys::swapByteOrder(dst.cmdsize);
+      sys::swapByteOrder(dst.ilocalsym);
+      sys::swapByteOrder(dst.nlocalsym);
+      sys::swapByteOrder(dst.iextdefsym);
+      sys::swapByteOrder(dst.nextdefsym);
+      sys::swapByteOrder(dst.iundefsym);
+      sys::swapByteOrder(dst.nundefsym);
+      sys::swapByteOrder(dst.tocoff);
+      sys::swapByteOrder(dst.ntoc);
+      sys::swapByteOrder(dst.modtaboff);
+      sys::swapByteOrder(dst.nmodtab);
+      sys::swapByteOrder(dst.extrefsymoff);
+      sys::swapByteOrder(dst.nextrefsyms);
+      sys::swapByteOrder(dst.indirectsymoff);
+      sys::swapByteOrder(dst.nindirectsyms);
+      sys::swapByteOrder(dst.extreloff);
+      sys::swapByteOrder(dst.nextrel);
+      sys::swapByteOrder(dst.locreloff);
+      sys::swapByteOrder(dst.nlocrel);
+    }
+
+    inline void swapStruct(any_relocation_info &reloc) {
+      sys::swapByteOrder(reloc.r_word0);
+      sys::swapByteOrder(reloc.r_word1);
+    }
+
+    inline void swapStruct(nlist_base &S) {
+      sys::swapByteOrder(S.n_strx);
+      sys::swapByteOrder(S.n_desc);
+    }
+
+    inline void swapStruct(nlist &sym) {
+      sys::swapByteOrder(sym.n_strx);
+      sys::swapByteOrder(sym.n_desc);
+      sys::swapByteOrder(sym.n_value);
+    }
+
+    inline void swapStruct(nlist_64 &sym) {
+      sys::swapByteOrder(sym.n_strx);
+      sys::swapByteOrder(sym.n_desc);
+      sys::swapByteOrder(sym.n_value);
+    }
+
+    inline void swapStruct(linkedit_data_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.dataoff);
+      sys::swapByteOrder(C.datasize);
+    }
+
+    inline void swapStruct(linker_option_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.count);
+    }
+
+    inline void swapStruct(version_min_command&C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.version);
+      sys::swapByteOrder(C.sdk);
+    }
+
+    inline void swapStruct(data_in_code_entry &C) {
+      sys::swapByteOrder(C.offset);
+      sys::swapByteOrder(C.length);
+      sys::swapByteOrder(C.kind);
+    }
+
+    inline void swapStruct(uint32_t &C) {
+      sys::swapByteOrder(C);
+    }
+
+    inline void swapStruct(prebind_cksum_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.cksum);
+    }
+
+    inline void swapStruct(twolevel_hints_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.offset);
+      sys::swapByteOrder(C.nhints);
+    }
+
+    inline void swapStruct(prebound_dylib_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.name);
+      sys::swapByteOrder(C.nmodules);
+      sys::swapByteOrder(C.linked_modules);
+    }
+
+    inline void swapStruct(fvmfile_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.name);
+      sys::swapByteOrder(C.header_addr);
+    }
+
+    inline void swapStruct(symseg_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      sys::swapByteOrder(C.offset);
+      sys::swapByteOrder(C.size);
+    }
+
+    inline void swapStruct(ident_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+    }
+
+    inline void swapStruct(fvmlib &C) {
+      sys::swapByteOrder(C.name);
+      sys::swapByteOrder(C.minor_version);
+      sys::swapByteOrder(C.header_addr);
+    }
+
+    inline void swapStruct(fvmlib_command &C) {
+      sys::swapByteOrder(C.cmd);
+      sys::swapByteOrder(C.cmdsize);
+      swapStruct(C.fvmlib);
+    }
+
+    // Get/Set functions from <mach-o/nlist.h>
+
+    static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) {
+      return (((n_desc) >> 8u) & 0xffu);
+    }
+
+    static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) {
+      n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8));
+    }
+
+    static inline uint8_t GET_COMM_ALIGN (uint16_t n_desc) {
+      return (n_desc >> 8u) & 0x0fu;
+    }
+
+    static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) {
+      n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u));
+    }
+
+    // Enums from <mach/machine.h>
+    enum : uint32_t {
+      // Capability bits used in the definition of cpu_type.
+      CPU_ARCH_MASK  = 0xff000000,   // Mask for architecture bits
+      CPU_ARCH_ABI64 = 0x01000000    // 64 bit ABI
+    };
+
+    // Constants for the cputype field.
+    enum CPUType {
+      CPU_TYPE_ANY       = -1,
+      CPU_TYPE_X86       = 7,
+      CPU_TYPE_I386      = CPU_TYPE_X86,
+      CPU_TYPE_X86_64    = CPU_TYPE_X86 | CPU_ARCH_ABI64,
+   /* CPU_TYPE_MIPS      = 8, */
+      CPU_TYPE_MC98000   = 10, // Old Motorola PowerPC
+      CPU_TYPE_ARM       = 12,
+      CPU_TYPE_ARM64     = CPU_TYPE_ARM | CPU_ARCH_ABI64,
+      CPU_TYPE_SPARC     = 14,
+      CPU_TYPE_POWERPC   = 18,
+      CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64
+    };
+
+    enum : uint32_t {
+      // Capability bits used in the definition of cpusubtype.
+      CPU_SUBTYPE_MASK  = 0xff000000,   // Mask for architecture bits
+      CPU_SUBTYPE_LIB64 = 0x80000000,   // 64 bit libraries
+
+      // Special CPU subtype constants.
+      CPU_SUBTYPE_MULTIPLE = ~0u
+    };
+
+    // Constants for the cpusubtype field.
+    enum CPUSubTypeX86 {
+      CPU_SUBTYPE_I386_ALL       = 3,
+      CPU_SUBTYPE_386            = 3,
+      CPU_SUBTYPE_486            = 4,
+      CPU_SUBTYPE_486SX          = 0x84,
+      CPU_SUBTYPE_586            = 5,
+      CPU_SUBTYPE_PENT           = CPU_SUBTYPE_586,
+      CPU_SUBTYPE_PENTPRO        = 0x16,
+      CPU_SUBTYPE_PENTII_M3      = 0x36,
+      CPU_SUBTYPE_PENTII_M5      = 0x56,
+      CPU_SUBTYPE_CELERON        = 0x67,
+      CPU_SUBTYPE_CELERON_MOBILE = 0x77,
+      CPU_SUBTYPE_PENTIUM_3      = 0x08,
+      CPU_SUBTYPE_PENTIUM_3_M    = 0x18,
+      CPU_SUBTYPE_PENTIUM_3_XEON = 0x28,
+      CPU_SUBTYPE_PENTIUM_M      = 0x09,
+      CPU_SUBTYPE_PENTIUM_4      = 0x0a,
+      CPU_SUBTYPE_PENTIUM_4_M    = 0x1a,
+      CPU_SUBTYPE_ITANIUM        = 0x0b,
+      CPU_SUBTYPE_ITANIUM_2      = 0x1b,
+      CPU_SUBTYPE_XEON           = 0x0c,
+      CPU_SUBTYPE_XEON_MP        = 0x1c,
+
+      CPU_SUBTYPE_X86_ALL     = 3,
+      CPU_SUBTYPE_X86_64_ALL  = 3,
+      CPU_SUBTYPE_X86_ARCH1   = 4,
+      CPU_SUBTYPE_X86_64_H    = 8
+    };
+    static inline int CPU_SUBTYPE_INTEL(int Family, int Model) {
+      return Family | (Model << 4);
+    }
+    static inline int CPU_SUBTYPE_INTEL_FAMILY(CPUSubTypeX86 ST) {
+      return ((int)ST) & 0x0f;
+    }
+    static inline int CPU_SUBTYPE_INTEL_MODEL(CPUSubTypeX86 ST) {
+      return ((int)ST) >> 4;
+    }
+    enum {
+      CPU_SUBTYPE_INTEL_FAMILY_MAX = 15,
+      CPU_SUBTYPE_INTEL_MODEL_ALL  = 0
+    };
+
+    enum CPUSubTypeARM {
+      CPU_SUBTYPE_ARM_ALL     = 0,
+      CPU_SUBTYPE_ARM_V4T     = 5,
+      CPU_SUBTYPE_ARM_V6      = 6,
+      CPU_SUBTYPE_ARM_V5      = 7,
+      CPU_SUBTYPE_ARM_V5TEJ   = 7,
+      CPU_SUBTYPE_ARM_XSCALE  = 8,
+      CPU_SUBTYPE_ARM_V7      = 9,
+      //  unused  ARM_V7F     = 10,
+      CPU_SUBTYPE_ARM_V7S     = 11,
+      CPU_SUBTYPE_ARM_V7K     = 12,
+      CPU_SUBTYPE_ARM_V6M     = 14,
+      CPU_SUBTYPE_ARM_V7M     = 15,
+      CPU_SUBTYPE_ARM_V7EM    = 16
+    };
+
+    enum CPUSubTypeARM64 {
+      CPU_SUBTYPE_ARM64_ALL   = 0
+    };
+
+    enum CPUSubTypeSPARC {
+      CPU_SUBTYPE_SPARC_ALL   = 0
+    };
+
+    enum CPUSubTypePowerPC {
+      CPU_SUBTYPE_POWERPC_ALL   = 0,
+      CPU_SUBTYPE_POWERPC_601   = 1,
+      CPU_SUBTYPE_POWERPC_602   = 2,
+      CPU_SUBTYPE_POWERPC_603   = 3,
+      CPU_SUBTYPE_POWERPC_603e  = 4,
+      CPU_SUBTYPE_POWERPC_603ev = 5,
+      CPU_SUBTYPE_POWERPC_604   = 6,
+      CPU_SUBTYPE_POWERPC_604e  = 7,
+      CPU_SUBTYPE_POWERPC_620   = 8,
+      CPU_SUBTYPE_POWERPC_750   = 9,
+      CPU_SUBTYPE_POWERPC_7400  = 10,
+      CPU_SUBTYPE_POWERPC_7450  = 11,
+      CPU_SUBTYPE_POWERPC_970   = 100,
+
+      CPU_SUBTYPE_MC980000_ALL  = CPU_SUBTYPE_POWERPC_ALL,
+      CPU_SUBTYPE_MC98601       = CPU_SUBTYPE_POWERPC_601
+    };
+
+    struct x86_thread_state64_t {
+      uint64_t rax;
+      uint64_t rbx;
+      uint64_t rcx;
+      uint64_t rdx;
+      uint64_t rdi;
+      uint64_t rsi;
+      uint64_t rbp;
+      uint64_t rsp;
+      uint64_t r8;
+      uint64_t r9;
+      uint64_t r10;
+      uint64_t r11;
+      uint64_t r12;
+      uint64_t r13;
+      uint64_t r14;
+      uint64_t r15;
+      uint64_t rip;
+      uint64_t rflags;
+      uint64_t cs;
+      uint64_t fs;
+      uint64_t gs;
+    };
+
+    enum x86_fp_control_precis {
+      x86_FP_PREC_24B = 0,
+      x86_FP_PREC_53B = 2,
+      x86_FP_PREC_64B = 3
+    };
+
+    enum x86_fp_control_rc {
+      x86_FP_RND_NEAR = 0,
+      x86_FP_RND_DOWN = 1,
+      x86_FP_RND_UP = 2,
+      x86_FP_CHOP = 3
+    };
+
+    struct fp_control_t {
+      unsigned short
+       invalid :1,
+       denorm  :1,
+       zdiv    :1,
+       ovrfl   :1,
+       undfl   :1,
+       precis  :1,
+               :2,
+       pc      :2,
+       rc      :2,
+               :1,
+               :3;
+    };
+
+    struct fp_status_t {
+      unsigned short
+        invalid :1,
+        denorm  :1,
+        zdiv    :1,
+        ovrfl   :1,
+        undfl   :1,
+        precis  :1,
+        stkflt  :1,
+        errsumm :1,
+        c0      :1,
+        c1      :1,
+        c2      :1,
+        tos     :3,
+        c3      :1,
+        busy    :1;
+    };
+
+    struct mmst_reg_t {
+      char mmst_reg[10];
+      char mmst_rsrv[6];
+    };
+
+    struct xmm_reg_t {
+      char xmm_reg[16];
+    };
+
+    struct x86_float_state64_t {
+      int32_t fpu_reserved[2];
+      fp_control_t fpu_fcw;
+      fp_status_t fpu_fsw;
+      uint8_t fpu_ftw;
+      uint8_t fpu_rsrv1;
+      uint16_t fpu_fop;
+      uint32_t fpu_ip;
+      uint16_t fpu_cs;
+      uint16_t fpu_rsrv2;
+      uint32_t fpu_dp;
+      uint16_t fpu_ds;
+      uint16_t fpu_rsrv3;
+      uint32_t fpu_mxcsr;
+      uint32_t fpu_mxcsrmask;
+      mmst_reg_t fpu_stmm0;
+      mmst_reg_t fpu_stmm1;
+      mmst_reg_t fpu_stmm2;
+      mmst_reg_t fpu_stmm3;
+      mmst_reg_t fpu_stmm4;
+      mmst_reg_t fpu_stmm5;
+      mmst_reg_t fpu_stmm6;
+      mmst_reg_t fpu_stmm7;
+      xmm_reg_t fpu_xmm0;
+      xmm_reg_t fpu_xmm1;
+      xmm_reg_t fpu_xmm2;
+      xmm_reg_t fpu_xmm3;
+      xmm_reg_t fpu_xmm4;
+      xmm_reg_t fpu_xmm5;
+      xmm_reg_t fpu_xmm6;
+      xmm_reg_t fpu_xmm7;
+      xmm_reg_t fpu_xmm8;
+      xmm_reg_t fpu_xmm9;
+      xmm_reg_t fpu_xmm10;
+      xmm_reg_t fpu_xmm11;
+      xmm_reg_t fpu_xmm12;
+      xmm_reg_t fpu_xmm13;
+      xmm_reg_t fpu_xmm14;
+      xmm_reg_t fpu_xmm15;
+      char fpu_rsrv4[6*16];
+      uint32_t fpu_reserved1;
+    };
+
+    struct x86_exception_state64_t {
+      uint16_t trapno;
+      uint16_t cpu;
+      uint32_t err;
+      uint64_t faultvaddr;
+    };
+
+    inline void swapStruct(x86_thread_state64_t &x) {
+      sys::swapByteOrder(x.rax);
+      sys::swapByteOrder(x.rbx);
+      sys::swapByteOrder(x.rcx);
+      sys::swapByteOrder(x.rdx);
+      sys::swapByteOrder(x.rdi);
+      sys::swapByteOrder(x.rsi);
+      sys::swapByteOrder(x.rbp);
+      sys::swapByteOrder(x.rsp);
+      sys::swapByteOrder(x.r8);
+      sys::swapByteOrder(x.r9);
+      sys::swapByteOrder(x.r10);
+      sys::swapByteOrder(x.r11);
+      sys::swapByteOrder(x.r12);
+      sys::swapByteOrder(x.r13);
+      sys::swapByteOrder(x.r14);
+      sys::swapByteOrder(x.r15);
+      sys::swapByteOrder(x.rip);
+      sys::swapByteOrder(x.rflags);
+      sys::swapByteOrder(x.cs);
+      sys::swapByteOrder(x.fs);
+      sys::swapByteOrder(x.gs);
+    }
+
+    inline void swapStruct(x86_float_state64_t &x) {
+      sys::swapByteOrder(x.fpu_reserved[0]);
+      sys::swapByteOrder(x.fpu_reserved[1]);
+      // TODO swap: fp_control_t fpu_fcw;
+      // TODO swap: fp_status_t fpu_fsw;
+      sys::swapByteOrder(x.fpu_fop);
+      sys::swapByteOrder(x.fpu_ip);
+      sys::swapByteOrder(x.fpu_cs);
+      sys::swapByteOrder(x.fpu_rsrv2);
+      sys::swapByteOrder(x.fpu_dp);
+      sys::swapByteOrder(x.fpu_ds);
+      sys::swapByteOrder(x.fpu_rsrv3);
+      sys::swapByteOrder(x.fpu_mxcsr);
+      sys::swapByteOrder(x.fpu_mxcsrmask);
+      sys::swapByteOrder(x.fpu_reserved1);
+    }
+
+    inline void swapStruct(x86_exception_state64_t &x) {
+      sys::swapByteOrder(x.trapno);
+      sys::swapByteOrder(x.cpu);
+      sys::swapByteOrder(x.err);
+      sys::swapByteOrder(x.faultvaddr);
+    }
+
+    struct x86_state_hdr_t {
+      uint32_t flavor;
+      uint32_t count;
+    };
+
+    struct x86_thread_state_t {
+      x86_state_hdr_t tsh;
+      union {
+        x86_thread_state64_t ts64;
+      } uts;
+    };
+
+    struct x86_float_state_t {
+      x86_state_hdr_t fsh;
+      union {
+        x86_float_state64_t fs64;
+      } ufs;
+    };
+
+    struct x86_exception_state_t {
+      x86_state_hdr_t esh;
+      union {
+        x86_exception_state64_t es64;
+      } ues;
+    };
+
+    inline void swapStruct(x86_state_hdr_t &x) {
+      sys::swapByteOrder(x.flavor);
+      sys::swapByteOrder(x.count);
+    }
+
+    enum X86ThreadFlavors {
+      x86_THREAD_STATE32    = 1,
+      x86_FLOAT_STATE32     = 2,
+      x86_EXCEPTION_STATE32 = 3,
+      x86_THREAD_STATE64    = 4,
+      x86_FLOAT_STATE64     = 5,
+      x86_EXCEPTION_STATE64 = 6,
+      x86_THREAD_STATE      = 7,
+      x86_FLOAT_STATE       = 8,
+      x86_EXCEPTION_STATE   = 9,
+      x86_DEBUG_STATE32     = 10,
+      x86_DEBUG_STATE64     = 11,
+      x86_DEBUG_STATE       = 12
+    };
+
+    inline void swapStruct(x86_thread_state_t &x) {
+      swapStruct(x.tsh);
+      if (x.tsh.flavor == x86_THREAD_STATE64)
+        swapStruct(x.uts.ts64);
+    }
+
+    inline void swapStruct(x86_float_state_t &x) {
+      swapStruct(x.fsh);
+      if (x.fsh.flavor == x86_FLOAT_STATE64)
+        swapStruct(x.ufs.fs64);
+    }
+
+    inline void swapStruct(x86_exception_state_t &x) {
+      swapStruct(x.esh);
+      if (x.esh.flavor == x86_EXCEPTION_STATE64)
+        swapStruct(x.ues.es64);
+    }
+
+    const uint32_t x86_THREAD_STATE64_COUNT =
+      sizeof(x86_thread_state64_t) / sizeof(uint32_t);
+    const uint32_t x86_FLOAT_STATE64_COUNT =
+      sizeof(x86_float_state64_t) / sizeof(uint32_t);
+    const uint32_t x86_EXCEPTION_STATE64_COUNT =
+      sizeof(x86_exception_state64_t) / sizeof(uint32_t);
+
+    const uint32_t x86_THREAD_STATE_COUNT =
+      sizeof(x86_thread_state_t) / sizeof(uint32_t);
+    const uint32_t x86_FLOAT_STATE_COUNT =
+      sizeof(x86_float_state_t) / sizeof(uint32_t);
+    const uint32_t x86_EXCEPTION_STATE_COUNT =
+      sizeof(x86_exception_state_t) / sizeof(uint32_t);
+
+    // Define a union of all load command structs
+    #define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data;
+
+    union macho_load_command {
+      #include "llvm/Support/MachO.def"
+    };
+
+  } // end namespace MachO
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ManagedStatic.h b/third_party/llvm-subzero/include/llvm/Support/ManagedStatic.h
new file mode 100644
index 0000000..ec8154b
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/ManagedStatic.h
@@ -0,0 +1,98 @@
+//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ManagedStatic class and the llvm_shutdown() function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
+#define LLVM_SUPPORT_MANAGEDSTATIC_H
+
+#include "llvm/Support/Compiler.h"
+#include <atomic>
+#include <cstddef>
+
+namespace llvm {
+
+/// object_creator - Helper method for ManagedStatic.
+template<class C>
+LLVM_LIBRARY_VISIBILITY void* object_creator() {
+  return new C();
+}
+
+/// object_deleter - Helper method for ManagedStatic.
+///
+template <typename T> struct LLVM_LIBRARY_VISIBILITY object_deleter {
+  static void call(void *Ptr) { delete (T *)Ptr; }
+};
+template <typename T, size_t N>
+struct LLVM_LIBRARY_VISIBILITY object_deleter<T[N]> {
+  static void call(void *Ptr) { delete[](T *)Ptr; }
+};
+
+/// ManagedStaticBase - Common base class for ManagedStatic instances.
+class ManagedStaticBase {
+protected:
+  // This should only be used as a static variable, which guarantees that this
+  // will be zero initialized.
+  mutable std::atomic<void *> Ptr;
+  mutable void (*DeleterFn)(void*);
+  mutable const ManagedStaticBase *Next;
+
+  void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
+public:
+  /// isConstructed - Return true if this object has not been created yet.
+  bool isConstructed() const { return Ptr != nullptr; }
+
+  void destroy() const;
+};
+
+/// ManagedStatic - This transparently changes the behavior of global statics to
+/// be lazily constructed on demand (good for reducing startup times of dynamic
+/// libraries that link in LLVM components) and for making destruction be
+/// explicit through the llvm_shutdown() function call.
+///
+template<class C>
+class ManagedStatic : public ManagedStaticBase {
+public:
+  // Accessors.
+  C &operator*() {
+    void *Tmp = Ptr.load(std::memory_order_acquire);
+    if (!Tmp)
+      RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
+
+    return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
+  }
+
+  C *operator->() { return &**this; }
+
+  const C &operator*() const {
+    void *Tmp = Ptr.load(std::memory_order_acquire);
+    if (!Tmp)
+      RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
+
+    return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
+  }
+
+  const C *operator->() const { return &**this; }
+};
+
+/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
+void llvm_shutdown();
+
+/// llvm_shutdown_obj - This is a simple helper class that calls
+/// llvm_shutdown() when it is destroyed.
+struct llvm_shutdown_obj {
+  llvm_shutdown_obj() { }
+  ~llvm_shutdown_obj() { llvm_shutdown(); }
+};
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MathExtras.h b/third_party/llvm-subzero/include/llvm/Support/MathExtras.h
new file mode 100644
index 0000000..fdf7f27
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MathExtras.h
@@ -0,0 +1,836 @@
+//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some functions that are useful for math stuff.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MATHEXTRAS_H
+#define LLVM_SUPPORT_MATHEXTRAS_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <type_traits>
+#include <limits>
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+#ifdef __ANDROID_NDK__
+#include <android/api-level.h>
+#endif
+
+namespace llvm {
+/// \brief The behavior an operation has on an input of 0.
+enum ZeroBehavior {
+  /// \brief The returned value is undefined.
+  ZB_Undefined,
+  /// \brief The returned value is numeric_limits<T>::max()
+  ZB_Max,
+  /// \brief The returned value is numeric_limits<T>::digits
+  ZB_Width
+};
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
+  static std::size_t count(T Val, ZeroBehavior) {
+    if (!Val)
+      return std::numeric_limits<T>::digits;
+    if (Val & 0x1)
+      return 0;
+
+    // Bisection method.
+    std::size_t ZeroBits = 0;
+    T Shift = std::numeric_limits<T>::digits >> 1;
+    T Mask = std::numeric_limits<T>::max() >> Shift;
+    while (Shift) {
+      if ((Val & Mask) == 0) {
+        Val >>= Shift;
+        ZeroBits |= Shift;
+      }
+      Shift >>= 1;
+      Mask >>= Shift;
+    }
+    return ZeroBits;
+  }
+};
+
+#if __GNUC__ >= 4 || defined(_MSC_VER)
+template <typename T> struct TrailingZerosCounter<T, 4> {
+  static std::size_t count(T Val, ZeroBehavior ZB) {
+    if (ZB != ZB_Undefined && Val == 0)
+      return 32;
+
+#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
+    return __builtin_ctz(Val);
+#elif defined(_MSC_VER)
+    unsigned long Index;
+    _BitScanForward(&Index, Val);
+    return Index;
+#endif
+  }
+};
+
+#if !defined(_MSC_VER) || defined(_M_X64)
+template <typename T> struct TrailingZerosCounter<T, 8> {
+  static std::size_t count(T Val, ZeroBehavior ZB) {
+    if (ZB != ZB_Undefined && Val == 0)
+      return 64;
+
+#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
+    return __builtin_ctzll(Val);
+#elif defined(_MSC_VER)
+    unsigned long Index;
+    _BitScanForward64(&Index, Val);
+    return Index;
+#endif
+  }
+};
+#endif
+#endif
+} // namespace detail
+
+/// \brief Count number of 0's from the least significant bit to the most
+///   stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
+///   valid arguments.
+template <typename T>
+std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+  static_assert(std::numeric_limits<T>::is_integer &&
+                    !std::numeric_limits<T>::is_signed,
+                "Only unsigned integral types are allowed.");
+  return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
+  static std::size_t count(T Val, ZeroBehavior) {
+    if (!Val)
+      return std::numeric_limits<T>::digits;
+
+    // Bisection method.
+    std::size_t ZeroBits = 0;
+    for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
+      T Tmp = Val >> Shift;
+      if (Tmp)
+        Val = Tmp;
+      else
+        ZeroBits |= Shift;
+    }
+    return ZeroBits;
+  }
+};
+
+#if __GNUC__ >= 4 || defined(_MSC_VER)
+template <typename T> struct LeadingZerosCounter<T, 4> {
+  static std::size_t count(T Val, ZeroBehavior ZB) {
+    if (ZB != ZB_Undefined && Val == 0)
+      return 32;
+
+#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
+    return __builtin_clz(Val);
+#elif defined(_MSC_VER)
+    unsigned long Index;
+    _BitScanReverse(&Index, Val);
+    return Index ^ 31;
+#endif
+  }
+};
+
+#if !defined(_MSC_VER) || defined(_M_X64)
+template <typename T> struct LeadingZerosCounter<T, 8> {
+  static std::size_t count(T Val, ZeroBehavior ZB) {
+    if (ZB != ZB_Undefined && Val == 0)
+      return 64;
+
+#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
+    return __builtin_clzll(Val);
+#elif defined(_MSC_VER)
+    unsigned long Index;
+    _BitScanReverse64(&Index, Val);
+    return Index ^ 63;
+#endif
+  }
+};
+#endif
+#endif
+} // namespace detail
+
+/// \brief Count number of 0's from the most significant bit to the least
+///   stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
+///   valid arguments.
+template <typename T>
+std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+  static_assert(std::numeric_limits<T>::is_integer &&
+                    !std::numeric_limits<T>::is_signed,
+                "Only unsigned integral types are allowed.");
+  return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
+
+/// \brief Get the index of the first set bit starting from the least
+///   significant bit.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
+///   valid arguments.
+template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
+  if (ZB == ZB_Max && Val == 0)
+    return std::numeric_limits<T>::max();
+
+  return countTrailingZeros(Val, ZB_Undefined);
+}
+
+/// \brief Get the index of the last set bit starting from the least
+///   significant bit.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
+///   valid arguments.
+template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
+  if (ZB == ZB_Max && Val == 0)
+    return std::numeric_limits<T>::max();
+
+  // Use ^ instead of - because both gcc and llvm can remove the associated ^
+  // in the __builtin_clz intrinsic on x86.
+  return countLeadingZeros(Val, ZB_Undefined) ^
+         (std::numeric_limits<T>::digits - 1);
+}
+
+/// \brief Macro compressed bit reversal table for 256 bits.
+///
+/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
+static const unsigned char BitReverseTable256[256] = {
+#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64
+#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16)
+#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4)
+  R6(0), R6(2), R6(1), R6(3)
+#undef R2
+#undef R4
+#undef R6
+};
+
+/// \brief Reverse the bits in \p Val.
+template <typename T>
+T reverseBits(T Val) {
+  unsigned char in[sizeof(Val)];
+  unsigned char out[sizeof(Val)];
+  std::memcpy(in, &Val, sizeof(Val));
+  for (unsigned i = 0; i < sizeof(Val); ++i)
+    out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]];
+  std::memcpy(&Val, out, sizeof(Val));
+  return Val;
+}
+
+// NOTE: The following support functions use the _32/_64 extensions instead of
+// type overloading so that signed and unsigned integers can be used without
+// ambiguity.
+
+/// Hi_32 - This function returns the high 32 bits of a 64 bit value.
+LLVM_CONSTEXPR inline uint32_t Hi_32(uint64_t Value) {
+  return static_cast<uint32_t>(Value >> 32);
+}
+
+/// Lo_32 - This function returns the low 32 bits of a 64 bit value.
+LLVM_CONSTEXPR inline uint32_t Lo_32(uint64_t Value) {
+  return static_cast<uint32_t>(Value);
+}
+
+/// Make_64 - This functions makes a 64-bit integer from a high / low pair of
+///           32-bit integers.
+LLVM_CONSTEXPR inline uint64_t Make_64(uint32_t High, uint32_t Low) {
+  return ((uint64_t)High << 32) | (uint64_t)Low;
+}
+
+/// isInt - Checks if an integer fits into the given bit width.
+template<unsigned N>
+LLVM_CONSTEXPR inline bool isInt(int64_t x) {
+  return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
+}
+// Template specializations to get better code for common cases.
+template<>
+LLVM_CONSTEXPR inline bool isInt<8>(int64_t x) {
+  return static_cast<int8_t>(x) == x;
+}
+template<>
+LLVM_CONSTEXPR inline bool isInt<16>(int64_t x) {
+  return static_cast<int16_t>(x) == x;
+}
+template<>
+LLVM_CONSTEXPR inline bool isInt<32>(int64_t x) {
+  return static_cast<int32_t>(x) == x;
+}
+
+/// isShiftedInt<N,S> - Checks if a signed integer is an N bit number shifted
+///                     left by S.
+template<unsigned N, unsigned S>
+LLVM_CONSTEXPR inline bool isShiftedInt(int64_t x) {
+  static_assert(
+      N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
+  static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide.");
+  return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
+}
+
+/// isUInt - Checks if an unsigned integer fits into the given bit width.
+///
+/// This is written as two functions rather than as simply
+///
+///   return N >= 64 || X < (UINT64_C(1) << N);
+///
+/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
+/// left too many places.
+template <unsigned N>
+LLVM_CONSTEXPR inline typename std::enable_if<(N < 64), bool>::type
+isUInt(uint64_t X) {
+  static_assert(N > 0, "isUInt<0> doesn't make sense");
+  return X < (UINT64_C(1) << (N));
+}
+template <unsigned N>
+LLVM_CONSTEXPR inline typename std::enable_if<N >= 64, bool>::type
+isUInt(uint64_t X) {
+  return true;
+}
+
+// Template specializations to get better code for common cases.
+template<>
+LLVM_CONSTEXPR inline bool isUInt<8>(uint64_t x) {
+  return static_cast<uint8_t>(x) == x;
+}
+template<>
+LLVM_CONSTEXPR inline bool isUInt<16>(uint64_t x) {
+  return static_cast<uint16_t>(x) == x;
+}
+template<>
+LLVM_CONSTEXPR inline bool isUInt<32>(uint64_t x) {
+  return static_cast<uint32_t>(x) == x;
+}
+
+/// Checks if a unsigned integer is an N bit number shifted left by S.
+template<unsigned N, unsigned S>
+LLVM_CONSTEXPR inline bool isShiftedUInt(uint64_t x) {
+  static_assert(
+      N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
+  static_assert(N + S <= 64,
+                "isShiftedUInt<N, S> with N + S > 64 is too wide.");
+  // Per the two static_asserts above, S must be strictly less than 64.  So
+  // 1 << S is not undefined behavior.
+  return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
+}
+
+/// Gets the maximum value for a N-bit unsigned integer.
+inline uint64_t maxUIntN(uint64_t N) {
+  assert(N > 0 && N <= 64 && "integer width out of range");
+
+  // uint64_t(1) << 64 is undefined behavior, so we can't do
+  //   (uint64_t(1) << N) - 1
+  // without checking first that N != 64.  But this works and doesn't have a
+  // branch.
+  return UINT64_MAX >> (64 - N);
+}
+
+/// Gets the minimum value for a N-bit signed integer.
+inline int64_t minIntN(int64_t N) {
+  assert(N > 0 && N <= 64 && "integer width out of range");
+
+  return -(UINT64_C(1)<<(N-1));
+}
+
+/// Gets the maximum value for a N-bit signed integer.
+inline int64_t maxIntN(int64_t N) {
+  assert(N > 0 && N <= 64 && "integer width out of range");
+
+  // This relies on two's complement wraparound when N == 64, so we convert to
+  // int64_t only at the very end to avoid UB.
+  return (UINT64_C(1) << (N - 1)) - 1;
+}
+
+/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
+/// bit width.
+inline bool isUIntN(unsigned N, uint64_t x) {
+  return N >= 64 || x <= maxUIntN(N);
+}
+
+/// isIntN - Checks if an signed integer fits into the given (dynamic)
+/// bit width.
+inline bool isIntN(unsigned N, int64_t x) {
+  return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N));
+}
+
+/// isMask_32 - This function returns true if the argument is a non-empty
+/// sequence of ones starting at the least significant bit with the remainder
+/// zero (32 bit version).  Ex. isMask_32(0x0000FFFFU) == true.
+LLVM_CONSTEXPR inline bool isMask_32(uint32_t Value) {
+  return Value && ((Value + 1) & Value) == 0;
+}
+
+/// isMask_64 - This function returns true if the argument is a non-empty
+/// sequence of ones starting at the least significant bit with the remainder
+/// zero (64 bit version).
+LLVM_CONSTEXPR inline bool isMask_64(uint64_t Value) {
+  return Value && ((Value + 1) & Value) == 0;
+}
+
+/// isShiftedMask_32 - This function returns true if the argument contains a
+/// non-empty sequence of ones with the remainder zero (32 bit version.)
+/// Ex. isShiftedMask_32(0x0000FF00U) == true.
+LLVM_CONSTEXPR inline bool isShiftedMask_32(uint32_t Value) {
+  return Value && isMask_32((Value - 1) | Value);
+}
+
+/// isShiftedMask_64 - This function returns true if the argument contains a
+/// non-empty sequence of ones with the remainder zero (64 bit version.)
+LLVM_CONSTEXPR inline bool isShiftedMask_64(uint64_t Value) {
+  return Value && isMask_64((Value - 1) | Value);
+}
+
+/// isPowerOf2_32 - This function returns true if the argument is a power of
+/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
+LLVM_CONSTEXPR inline bool isPowerOf2_32(uint32_t Value) {
+  return Value && !(Value & (Value - 1));
+}
+
+/// isPowerOf2_64 - This function returns true if the argument is a power of two
+/// > 0 (64 bit edition.)
+LLVM_CONSTEXPR inline bool isPowerOf2_64(uint64_t Value) {
+  return Value && !(Value & (Value - int64_t(1L)));
+}
+
+/// ByteSwap_16 - This function returns a byte-swapped representation of the
+/// 16-bit argument, Value.
+inline uint16_t ByteSwap_16(uint16_t Value) {
+  return sys::SwapByteOrder_16(Value);
+}
+
+/// ByteSwap_32 - This function returns a byte-swapped representation of the
+/// 32-bit argument, Value.
+inline uint32_t ByteSwap_32(uint32_t Value) {
+  return sys::SwapByteOrder_32(Value);
+}
+
+/// ByteSwap_64 - This function returns a byte-swapped representation of the
+/// 64-bit argument, Value.
+inline uint64_t ByteSwap_64(uint64_t Value) {
+  return sys::SwapByteOrder_64(Value);
+}
+
+/// \brief Count the number of ones from the most significant bit to the first
+/// zero bit.
+///
+/// Ex. CountLeadingOnes(0xFF0FFF00) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+  static_assert(std::numeric_limits<T>::is_integer &&
+                    !std::numeric_limits<T>::is_signed,
+                "Only unsigned integral types are allowed.");
+  return countLeadingZeros(~Value, ZB);
+}
+
+/// \brief Count the number of ones from the least significant bit to the first
+/// zero bit.
+///
+/// Ex. countTrailingOnes(0x00FF00FF) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+  static_assert(std::numeric_limits<T>::is_integer &&
+                    !std::numeric_limits<T>::is_signed,
+                "Only unsigned integral types are allowed.");
+  return countTrailingZeros(~Value, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct PopulationCounter {
+  static unsigned count(T Value) {
+    // Generic version, forward to 32 bits.
+    static_assert(SizeOfT <= 4, "Not implemented!");
+#if __GNUC__ >= 4
+    return __builtin_popcount(Value);
+#else
+    uint32_t v = Value;
+    v = v - ((v >> 1) & 0x55555555);
+    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+    return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
+#endif
+  }
+};
+
+template <typename T> struct PopulationCounter<T, 8> {
+  static unsigned count(T Value) {
+#if __GNUC__ >= 4
+    return __builtin_popcountll(Value);
+#else
+    uint64_t v = Value;
+    v = v - ((v >> 1) & 0x5555555555555555ULL);
+    v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
+    v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+    return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
+#endif
+  }
+};
+} // namespace detail
+
+/// \brief Count the number of set bits in a value.
+/// Ex. countPopulation(0xF000F000) = 8
+/// Returns 0 if the word is zero.
+template <typename T>
+inline unsigned countPopulation(T Value) {
+  static_assert(std::numeric_limits<T>::is_integer &&
+                    !std::numeric_limits<T>::is_signed,
+                "Only unsigned integral types are allowed.");
+  return detail::PopulationCounter<T, sizeof(T)>::count(Value);
+}
+
+/// Log2 - This function returns the log base 2 of the specified value
+inline double Log2(double Value) {
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
+  return __builtin_log(Value) / __builtin_log(2.0);
+#else
+  return log2(Value);
+#endif
+}
+
+/// Log2_32 - This function returns the floor log base 2 of the specified value,
+/// -1 if the value is zero. (32 bit edition.)
+/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
+inline unsigned Log2_32(uint32_t Value) {
+  return 31 - countLeadingZeros(Value);
+}
+
+/// Log2_64 - This function returns the floor log base 2 of the specified value,
+/// -1 if the value is zero. (64 bit edition.)
+inline unsigned Log2_64(uint64_t Value) {
+  return 63 - countLeadingZeros(Value);
+}
+
+/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified
+/// value, 32 if the value is zero. (32 bit edition).
+/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
+inline unsigned Log2_32_Ceil(uint32_t Value) {
+  return 32 - countLeadingZeros(Value - 1);
+}
+
+/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified
+/// value, 64 if the value is zero. (64 bit edition.)
+inline unsigned Log2_64_Ceil(uint64_t Value) {
+  return 64 - countLeadingZeros(Value - 1);
+}
+
+/// GreatestCommonDivisor64 - Return the greatest common divisor of the two
+/// values using Euclid's algorithm.
+inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
+  while (B) {
+    uint64_t T = B;
+    B = A % B;
+    A = T;
+  }
+  return A;
+}
+
+/// BitsToDouble - This function takes a 64-bit integer and returns the bit
+/// equivalent double.
+inline double BitsToDouble(uint64_t Bits) {
+  union {
+    uint64_t L;
+    double D;
+  } T;
+  T.L = Bits;
+  return T.D;
+}
+
+/// BitsToFloat - This function takes a 32-bit integer and returns the bit
+/// equivalent float.
+inline float BitsToFloat(uint32_t Bits) {
+  union {
+    uint32_t I;
+    float F;
+  } T;
+  T.I = Bits;
+  return T.F;
+}
+
+/// DoubleToBits - This function takes a double and returns the bit
+/// equivalent 64-bit integer.  Note that copying doubles around
+/// changes the bits of NaNs on some hosts, notably x86, so this
+/// routine cannot be used if these bits are needed.
+inline uint64_t DoubleToBits(double Double) {
+  union {
+    uint64_t L;
+    double D;
+  } T;
+  T.D = Double;
+  return T.L;
+}
+
+/// FloatToBits - This function takes a float and returns the bit
+/// equivalent 32-bit integer.  Note that copying floats around
+/// changes the bits of NaNs on some hosts, notably x86, so this
+/// routine cannot be used if these bits are needed.
+inline uint32_t FloatToBits(float Float) {
+  union {
+    uint32_t I;
+    float F;
+  } T;
+  T.F = Float;
+  return T.I;
+}
+
+/// MinAlign - A and B are either alignments or offsets.  Return the minimum
+/// alignment that may be assumed after adding the two together.
+LLVM_CONSTEXPR inline uint64_t MinAlign(uint64_t A, uint64_t B) {
+  // The largest power of 2 that divides both A and B.
+  //
+  // Replace "-Value" by "1+~Value" in the following commented code to avoid
+  // MSVC warning C4146
+  //    return (A | B) & -(A | B);
+  return (A | B) & (1 + ~(A | B));
+}
+
+/// \brief Aligns \c Addr to \c Alignment bytes, rounding up.
+///
+/// Alignment should be a power of two.  This method rounds up, so
+/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
+inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
+  assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
+         "Alignment is not a power of two!");
+
+  assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr);
+
+  return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1));
+}
+
+/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment
+/// bytes, rounding up.
+inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
+  return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
+}
+
+/// NextPowerOf2 - Returns the next power of two (in 64-bits)
+/// that is strictly greater than A.  Returns zero on overflow.
+inline uint64_t NextPowerOf2(uint64_t A) {
+  A |= (A >> 1);
+  A |= (A >> 2);
+  A |= (A >> 4);
+  A |= (A >> 8);
+  A |= (A >> 16);
+  A |= (A >> 32);
+  return A + 1;
+}
+
+/// Returns the power of two which is less than or equal to the given value.
+/// Essentially, it is a floor operation across the domain of powers of two.
+inline uint64_t PowerOf2Floor(uint64_t A) {
+  if (!A) return 0;
+  return 1ull << (63 - countLeadingZeros(A, ZB_Undefined));
+}
+
+/// Returns the next integer (mod 2**64) that is greater than or equal to
+/// \p Value and is a multiple of \p Align. \p Align must be non-zero.
+///
+/// If non-zero \p Skew is specified, the return value will be a minimal
+/// integer that is greater than or equal to \p Value and equal to
+/// \p Align * N + \p Skew for some integer N. If \p Skew is larger than
+/// \p Align, its value is adjusted to '\p Skew mod \p Align'.
+///
+/// Examples:
+/// \code
+///   alignTo(5, 8) = 8
+///   alignTo(17, 8) = 24
+///   alignTo(~0LL, 8) = 0
+///   alignTo(321, 255) = 510
+///
+///   alignTo(5, 8, 7) = 7
+///   alignTo(17, 8, 1) = 17
+///   alignTo(~0LL, 8, 3) = 3
+///   alignTo(321, 255, 42) = 552
+/// \endcode
+inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
+  assert(Align != 0u && "Align can't be 0.");
+  Skew %= Align;
+  return (Value + Align - 1 - Skew) / Align * Align + Skew;
+}
+
+/// Returns the next integer (mod 2**64) that is greater than or equal to
+/// \p Value and is a multiple of \c Align. \c Align must be non-zero.
+template <uint64_t Align>
+LLVM_CONSTEXPR inline uint64_t alignTo(uint64_t Value) {
+  static_assert(Align != 0u, "Align must be non-zero");
+  return (Value + Align - 1) / Align * Align;
+}
+
+/// \c alignTo for contexts where a constant expression is required.
+/// \sa alignTo
+///
+/// \todo FIXME: remove when \c LLVM_CONSTEXPR becomes really \c constexpr
+template <uint64_t Align>
+struct AlignTo {
+  static_assert(Align != 0u, "Align must be non-zero");
+  template <uint64_t Value>
+  struct from_value {
+    static const uint64_t value = (Value + Align - 1) / Align * Align;
+  };
+};
+
+/// Returns the largest uint64_t less than or equal to \p Value and is
+/// \p Skew mod \p Align. \p Align must be non-zero
+inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
+  assert(Align != 0u && "Align can't be 0.");
+  Skew %= Align;
+  return (Value - Skew) / Align * Align + Skew;
+}
+
+/// Returns the offset to the next integer (mod 2**64) that is greater than
+/// or equal to \p Value and is a multiple of \p Align. \p Align must be
+/// non-zero.
+inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) {
+  return alignTo(Value, Align) - Value;
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires 0 < B <= 32.
+template <unsigned B> LLVM_CONSTEXPR inline int32_t SignExtend32(uint32_t X) {
+  static_assert(B > 0, "Bit width can't be 0.");
+  static_assert(B <= 32, "Bit width out of range.");
+  return int32_t(X << (32 - B)) >> (32 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires 0 < B < 32.
+inline int32_t SignExtend32(uint32_t X, unsigned B) {
+  assert(B > 0 && "Bit width can't be 0.");
+  assert(B <= 32 && "Bit width out of range.");
+  return int32_t(X << (32 - B)) >> (32 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires 0 < B < 64.
+template <unsigned B> LLVM_CONSTEXPR inline int64_t SignExtend64(uint64_t x) {
+  static_assert(B > 0, "Bit width can't be 0.");
+  static_assert(B <= 64, "Bit width out of range.");
+  return int64_t(x << (64 - B)) >> (64 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires 0 < B < 64.
+inline int64_t SignExtend64(uint64_t X, unsigned B) {
+  assert(B > 0 && "Bit width can't be 0.");
+  assert(B <= 64 && "Bit width out of range.");
+  return int64_t(X << (64 - B)) >> (64 - B);
+}
+
+/// Subtract two unsigned integers, X and Y, of type T and return the absolute
+/// value of the result.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+AbsoluteDifference(T X, T Y) {
+  return std::max(X, Y) - std::min(X, Y);
+}
+
+/// Add two unsigned integers, X and Y, of type T.  Clamp the result to the
+/// maximum representable value of T on overflow.  ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
+  bool Dummy;
+  bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+  // Hacker's Delight, p. 29
+  T Z = X + Y;
+  Overflowed = (Z < X || Z < Y);
+  if (Overflowed)
+    return std::numeric_limits<T>::max();
+  else
+    return Z;
+}
+
+/// Multiply two unsigned integers, X and Y, of type T.  Clamp the result to the
+/// maximum representable value of T on overflow.  ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
+  bool Dummy;
+  bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+  // Hacker's Delight, p. 30 has a different algorithm, but we don't use that
+  // because it fails for uint16_t (where multiplication can have undefined
+  // behavior due to promotion to int), and requires a division in addition
+  // to the multiplication.
+
+  Overflowed = false;
+
+  // Log2(Z) would be either Log2Z or Log2Z + 1.
+  // Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z
+  // will necessarily be less than Log2Max as desired.
+  int Log2Z = Log2_64(X) + Log2_64(Y);
+  const T Max = std::numeric_limits<T>::max();
+  int Log2Max = Log2_64(Max);
+  if (Log2Z < Log2Max) {
+    return X * Y;
+  }
+  if (Log2Z > Log2Max) {
+    Overflowed = true;
+    return Max;
+  }
+
+  // We're going to use the top bit, and maybe overflow one
+  // bit past it. Multiply all but the bottom bit then add
+  // that on at the end.
+  T Z = (X >> 1) * Y;
+  if (Z & ~(Max >> 1)) {
+    Overflowed = true;
+    return Max;
+  }
+  Z <<= 1;
+  if (X & 1)
+    return SaturatingAdd(Z, Y, ResultOverflowed);
+
+  return Z;
+}
+
+/// Multiply two unsigned integers, X and Y, and add the unsigned integer, A to
+/// the product. Clamp the result to the maximum representable value of T on
+/// overflow. ResultOverflowed indicates if the result is larger than the
+/// maximum representable value of type T.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
+  bool Dummy;
+  bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+  T Product = SaturatingMultiply(X, Y, &Overflowed);
+  if (Overflowed)
+    return Product;
+
+  return SaturatingAdd(A, Product, &Overflowed);
+}
+
+/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
+extern const float huge_valf;
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Memory.h b/third_party/llvm-subzero/include/llvm/Support/Memory.h
new file mode 100644
index 0000000..8103aea
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Memory.h
@@ -0,0 +1,186 @@
+//===- llvm/Support/Memory.h - Memory Support -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::Memory class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMORY_H
+#define LLVM_SUPPORT_MEMORY_H
+
+#include "llvm/Support/DataTypes.h"
+#include <string>
+#include <system_error>
+
+namespace llvm {
+namespace sys {
+
+  /// This class encapsulates the notion of a memory block which has an address
+  /// and a size. It is used by the Memory class (a friend) as the result of
+  /// various memory allocation operations.
+  /// @see Memory
+  /// @brief Memory block abstraction.
+  class MemoryBlock {
+  public:
+    MemoryBlock() : Address(nullptr), Size(0) { }
+    MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { }
+    void *base() const { return Address; }
+    size_t size() const { return Size; }
+
+  private:
+    void *Address;    ///< Address of first byte of memory area
+    size_t Size;      ///< Size, in bytes of the memory area
+    friend class Memory;
+  };
+
+  /// This class provides various memory handling functions that manipulate
+  /// MemoryBlock instances.
+  /// @since 1.4
+  /// @brief An abstraction for memory operations.
+  class Memory {
+  public:
+    enum ProtectionFlags {
+      MF_READ  = 0x1000000,
+      MF_WRITE = 0x2000000,
+      MF_EXEC  = 0x4000000
+    };
+
+    /// This method allocates a block of memory that is suitable for loading
+    /// dynamically generated code (e.g. JIT). An attempt to allocate
+    /// \p NumBytes bytes of virtual memory is made.
+    /// \p NearBlock may point to an existing allocation in which case
+    /// an attempt is made to allocate more memory near the existing block.
+    /// The actual allocated address is not guaranteed to be near the requested
+    /// address.
+    /// \p Flags is used to set the initial protection flags for the block
+    /// of the memory.
+    /// \p EC [out] returns an object describing any error that occurs.
+    ///
+    /// This method may allocate more than the number of bytes requested.  The
+    /// actual number of bytes allocated is indicated in the returned
+    /// MemoryBlock.
+    ///
+    /// The start of the allocated block must be aligned with the
+    /// system allocation granularity (64K on Windows, page size on Linux).
+    /// If the address following \p NearBlock is not so aligned, it will be
+    /// rounded up to the next allocation granularity boundary.
+    ///
+    /// \r a non-null MemoryBlock if the function was successful,
+    /// otherwise a null MemoryBlock is with \p EC describing the error.
+    ///
+    /// @brief Allocate mapped memory.
+    static MemoryBlock allocateMappedMemory(size_t NumBytes,
+                                            const MemoryBlock *const NearBlock,
+                                            unsigned Flags,
+                                            std::error_code &EC);
+
+    /// This method releases a block of memory that was allocated with the
+    /// allocateMappedMemory method. It should not be used to release any
+    /// memory block allocated any other way.
+    /// \p Block describes the memory to be released.
+    ///
+    /// \r error_success if the function was successful, or an error_code
+    /// describing the failure if an error occurred.
+    ///
+    /// @brief Release mapped memory.
+    static std::error_code releaseMappedMemory(MemoryBlock &Block);
+
+    /// This method sets the protection flags for a block of memory to the
+    /// state specified by /p Flags.  The behavior is not specified if the
+    /// memory was not allocated using the allocateMappedMemory method.
+    /// \p Block describes the memory block to be protected.
+    /// \p Flags specifies the new protection state to be assigned to the block.
+    /// \p ErrMsg [out] returns a string describing any error that occurred.
+    ///
+    /// If \p Flags is MF_WRITE, the actual behavior varies
+    /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
+    /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
+    ///
+    /// \r error_success if the function was successful, or an error_code
+    /// describing the failure if an error occurred.
+    ///
+    /// @brief Set memory protection state.
+    static std::error_code protectMappedMemory(const MemoryBlock &Block,
+                                               unsigned Flags);
+
+    /// This method allocates a block of Read/Write/Execute memory that is
+    /// suitable for executing dynamically generated code (e.g. JIT). An
+    /// attempt to allocate \p NumBytes bytes of virtual memory is made.
+    /// \p NearBlock may point to an existing allocation in which case
+    /// an attempt is made to allocate more memory near the existing block.
+    ///
+    /// On success, this returns a non-null memory block, otherwise it returns
+    /// a null memory block and fills in *ErrMsg.
+    ///
+    /// @brief Allocate Read/Write/Execute memory.
+    static MemoryBlock AllocateRWX(size_t NumBytes,
+                                   const MemoryBlock *NearBlock,
+                                   std::string *ErrMsg = nullptr);
+
+    /// This method releases a block of Read/Write/Execute memory that was
+    /// allocated with the AllocateRWX method. It should not be used to
+    /// release any memory block allocated any other way.
+    ///
+    /// On success, this returns false, otherwise it returns true and fills
+    /// in *ErrMsg.
+    /// @brief Release Read/Write/Execute memory.
+    static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr);
+
+    /// InvalidateInstructionCache - Before the JIT can run a block of code
+    /// that has been emitted it must invalidate the instruction cache on some
+    /// platforms.
+    static void InvalidateInstructionCache(const void *Addr, size_t Len);
+
+    /// setExecutable - Before the JIT can run a block of code, it has to be
+    /// given read and executable privilege. Return true if it is already r-x
+    /// or the system is able to change its previlege.
+    static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr);
+
+    /// setWritable - When adding to a block of code, the JIT may need
+    /// to mark a block of code as RW since the protections are on page
+    /// boundaries, and the JIT internal allocations are not page aligned.
+    static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr);
+
+    /// setRangeExecutable - Mark the page containing a range of addresses
+    /// as executable.
+    static bool setRangeExecutable(const void *Addr, size_t Size);
+
+    /// setRangeWritable - Mark the page containing a range of addresses
+    /// as writable.
+    static bool setRangeWritable(const void *Addr, size_t Size);
+  };
+
+  /// Owning version of MemoryBlock.
+  class OwningMemoryBlock {
+  public:
+    OwningMemoryBlock() = default;
+    explicit OwningMemoryBlock(MemoryBlock M) : M(M) {}
+    OwningMemoryBlock(OwningMemoryBlock &&Other) {
+      M = Other.M;
+      Other.M = MemoryBlock();
+    }
+    OwningMemoryBlock& operator=(OwningMemoryBlock &&Other) {
+      M = Other.M;
+      Other.M = MemoryBlock();
+      return *this;
+    }
+    ~OwningMemoryBlock() {
+      Memory::releaseMappedMemory(M);
+    }
+    void *base() const { return M.base(); }
+    size_t size() const { return M.size(); }
+    MemoryBlock getMemoryBlock() const { return M; }
+  private:
+    MemoryBlock M;
+  };
+
+}
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MemoryBuffer.h b/third_party/llvm-subzero/include/llvm/Support/MemoryBuffer.h
new file mode 100644
index 0000000..73d6435
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MemoryBuffer.h
@@ -0,0 +1,173 @@
+//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the MemoryBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMORYBUFFER_H
+#define LLVM_SUPPORT_MEMORYBUFFER_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorOr.h"
+#include <memory>
+
+namespace llvm {
+class MemoryBufferRef;
+
+/// This interface provides simple read-only access to a block of memory, and
+/// provides simple methods for reading files and standard input into a memory
+/// buffer.  In addition to basic access to the characters in the file, this
+/// interface guarantees you can read one character past the end of the file,
+/// and that this character will read as '\0'.
+///
+/// The '\0' guarantee is needed to support an optimization -- it's intended to
+/// be more efficient for clients which are reading all the data to stop
+/// reading when they encounter a '\0' than to continually check the file
+/// position to see if it has reached the end of the file.
+class MemoryBuffer {
+  const char *BufferStart; // Start of the buffer.
+  const char *BufferEnd;   // End of the buffer.
+
+  MemoryBuffer(const MemoryBuffer &) = delete;
+  MemoryBuffer &operator=(const MemoryBuffer &) = delete;
+protected:
+  MemoryBuffer() {}
+  void init(const char *BufStart, const char *BufEnd,
+            bool RequiresNullTerminator);
+public:
+  virtual ~MemoryBuffer();
+
+  const char *getBufferStart() const { return BufferStart; }
+  const char *getBufferEnd() const   { return BufferEnd; }
+  size_t getBufferSize() const { return BufferEnd-BufferStart; }
+
+  StringRef getBuffer() const {
+    return StringRef(BufferStart, getBufferSize());
+  }
+
+  /// Return an identifier for this buffer, typically the filename it was read
+  /// from.
+  virtual const char *getBufferIdentifier() const {
+    return "Unknown buffer";
+  }
+
+  /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer
+  /// if successful, otherwise returning null. If FileSize is specified, this
+  /// means that the client knows that the file exists and that it has the
+  /// specified size.
+  ///
+  /// \param IsVolatileSize Set to true to indicate that the file size may be
+  /// changing, e.g. when libclang tries to parse while the user is
+  /// editing/updating the file.
+  static ErrorOr<std::unique_ptr<MemoryBuffer>>
+  getFile(const Twine &Filename, int64_t FileSize = -1,
+          bool RequiresNullTerminator = true, bool IsVolatileSize = false);
+
+  /// Given an already-open file descriptor, map some slice of it into a
+  /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
+  /// Since this is in the middle of a file, the buffer is not null terminated.
+  static ErrorOr<std::unique_ptr<MemoryBuffer>>
+  getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
+                   int64_t Offset);
+
+  /// Given an already-open file descriptor, read the file and return a
+  /// MemoryBuffer.
+  ///
+  /// \param IsVolatileSize Set to true to indicate that the file size may be
+  /// changing, e.g. when libclang tries to parse while the user is
+  /// editing/updating the file.
+  static ErrorOr<std::unique_ptr<MemoryBuffer>>
+  getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
+              bool RequiresNullTerminator = true, bool IsVolatileSize = false);
+
+  /// Open the specified memory range as a MemoryBuffer. Note that InputData
+  /// must be null terminated if RequiresNullTerminator is true.
+  static std::unique_ptr<MemoryBuffer>
+  getMemBuffer(StringRef InputData, StringRef BufferName = "",
+               bool RequiresNullTerminator = true);
+
+  static std::unique_ptr<MemoryBuffer>
+  getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true);
+
+  /// Open the specified memory range as a MemoryBuffer, copying the contents
+  /// and taking ownership of it. InputData does not have to be null terminated.
+  static std::unique_ptr<MemoryBuffer>
+  getMemBufferCopy(StringRef InputData, const Twine &BufferName = "");
+
+  /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
+  /// that the caller need not initialize the memory allocated by this method.
+  /// The memory is owned by the MemoryBuffer object.
+  static std::unique_ptr<MemoryBuffer>
+  getNewMemBuffer(size_t Size, StringRef BufferName = "");
+
+  /// Allocate a new MemoryBuffer of the specified size that is not initialized.
+  /// Note that the caller should initialize the memory allocated by this
+  /// method. The memory is owned by the MemoryBuffer object.
+  static std::unique_ptr<MemoryBuffer>
+  getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "");
+
+  /// Read all of stdin into a file buffer, and return it.
+  static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN();
+
+  /// Open the specified file as a MemoryBuffer, or open stdin if the Filename
+  /// is "-".
+  static ErrorOr<std::unique_ptr<MemoryBuffer>>
+  getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1,
+                 bool RequiresNullTerminator = true);
+
+  /// Map a subrange of the specified file as a MemoryBuffer.
+  static ErrorOr<std::unique_ptr<MemoryBuffer>>
+  getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
+
+  //===--------------------------------------------------------------------===//
+  // Provided for performance analysis.
+  //===--------------------------------------------------------------------===//
+
+  /// The kind of memory backing used to support the MemoryBuffer.
+  enum BufferKind {
+    MemoryBuffer_Malloc,
+    MemoryBuffer_MMap
+  };
+
+  /// Return information on the memory mechanism used to support the
+  /// MemoryBuffer.
+  virtual BufferKind getBufferKind() const = 0;
+
+  MemoryBufferRef getMemBufferRef() const;
+};
+
+class MemoryBufferRef {
+  StringRef Buffer;
+  StringRef Identifier;
+
+public:
+  MemoryBufferRef() {}
+  MemoryBufferRef(MemoryBuffer& Buffer)
+      : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {}
+  MemoryBufferRef(StringRef Buffer, StringRef Identifier)
+      : Buffer(Buffer), Identifier(Identifier) {}
+
+  StringRef getBuffer() const { return Buffer; }
+
+  StringRef getBufferIdentifier() const { return Identifier; }
+
+  const char *getBufferStart() const { return Buffer.begin(); }
+  const char *getBufferEnd() const { return Buffer.end(); }
+  size_t getBufferSize() const { return Buffer.size(); }
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MemoryObject.h b/third_party/llvm-subzero/include/llvm/Support/MemoryObject.h
new file mode 100644
index 0000000..e0c8749
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MemoryObject.h
@@ -0,0 +1,68 @@
+//===- MemoryObject.h - Abstract memory interface ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMORYOBJECT_H
+#define LLVM_SUPPORT_MEMORYOBJECT_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+/// Interface to data which might be streamed. Streamability has 2 important
+/// implications/restrictions. First, the data might not yet exist in memory
+/// when the request is made. This just means that readByte/readBytes might have
+/// to block or do some work to get it. More significantly, the exact size of
+/// the object might not be known until it has all been fetched. This means that
+/// to return the right result, getExtent must also wait for all the data to
+/// arrive; therefore it should not be called on objects which are actually
+/// streamed (this would defeat the purpose of streaming). Instead,
+/// isValidAddress can be used to test addresses without knowing the exact size
+/// of the stream. Finally, getPointer can be used instead of readBytes to avoid
+/// extra copying.
+class MemoryObject {
+public:
+  virtual ~MemoryObject();
+
+  /// Returns the size of the region in bytes.  (The region is contiguous, so
+  /// the highest valid address of the region is getExtent() - 1).
+  ///
+  /// @result         - The size of the region.
+  virtual uint64_t getExtent() const = 0;
+
+  /// Tries to read a contiguous range of bytes from the region, up to the end
+  /// of the region.
+  ///
+  /// @param Buf      - A pointer to a buffer to be filled in.  Must be non-NULL
+  ///                   and large enough to hold size bytes.
+  /// @param Size     - The number of bytes to copy.
+  /// @param Address  - The address of the first byte, in the same space as
+  ///                   getBase().
+  /// @result         - The number of bytes read.
+  virtual uint64_t readBytes(uint8_t *Buf, uint64_t Size,
+                             uint64_t Address) const = 0;
+
+  /// Ensures that the requested data is in memory, and returns a pointer to it.
+  /// More efficient than using readBytes if the data is already in memory. May
+  /// block until (address - base + size) bytes have been read
+  /// @param address - address of the byte, in the same space as getBase()
+  /// @param size    - amount of data that must be available on return
+  /// @result        - valid pointer to the requested data
+  virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0;
+
+  /// Returns true if the address is within the object (i.e. between base and
+  /// base + extent - 1 inclusive). May block until (address - base) bytes have
+  /// been read
+  /// @param address - address of the byte, in the same space as getBase()
+  /// @result        - true if the address may be read with readByte()
+  virtual bool isValidAddress(uint64_t address) const = 0;
+};
+
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Mutex.h b/third_party/llvm-subzero/include/llvm/Support/Mutex.h
new file mode 100644
index 0000000..0f4e61a
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Mutex.h
@@ -0,0 +1,158 @@
+//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::Mutex class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MUTEX_H
+#define LLVM_SUPPORT_MUTEX_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Threading.h"
+#include <cassert>
+
+namespace llvm
+{
+  namespace sys
+  {
+    /// @brief Platform agnostic Mutex class.
+    class MutexImpl
+    {
+    /// @name Constructors
+    /// @{
+    public:
+
+      /// Initializes the lock but doesn't acquire it. if \p recursive is set
+      /// to false, the lock will not be recursive which makes it cheaper but
+      /// also more likely to deadlock (same thread can't acquire more than
+      /// once).
+      /// @brief Default Constructor.
+      explicit MutexImpl(bool recursive = true);
+
+      /// Releases and removes the lock
+      /// @brief Destructor
+      ~MutexImpl();
+
+    /// @}
+    /// @name Methods
+    /// @{
+    public:
+
+      /// Attempts to unconditionally acquire the lock. If the lock is held by
+      /// another thread, this method will wait until it can acquire the lock.
+      /// @returns false if any kind of error occurs, true otherwise.
+      /// @brief Unconditionally acquire the lock.
+      bool acquire();
+
+      /// Attempts to release the lock. If the lock is held by the current
+      /// thread, the lock is released allowing other threads to acquire the
+      /// lock.
+      /// @returns false if any kind of error occurs, true otherwise.
+      /// @brief Unconditionally release the lock.
+      bool release();
+
+      /// Attempts to acquire the lock without blocking. If the lock is not
+      /// available, this function returns false quickly (without blocking). If
+      /// the lock is available, it is acquired.
+      /// @returns false if any kind of error occurs or the lock is not
+      /// available, true otherwise.
+      /// @brief Try to acquire the lock.
+      bool tryacquire();
+
+    //@}
+    /// @name Platform Dependent Data
+    /// @{
+    private:
+#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
+      void* data_; ///< We don't know what the data will be
+#endif
+
+    /// @}
+    /// @name Do Not Implement
+    /// @{
+    private:
+      MutexImpl(const MutexImpl &) = delete;
+      void operator=(const MutexImpl &) = delete;
+    /// @}
+    };
+
+
+    /// SmartMutex - A mutex with a compile time constant parameter that
+    /// indicates whether this mutex should become a no-op when we're not
+    /// running in multithreaded mode.
+    template<bool mt_only>
+    class SmartMutex {
+      MutexImpl impl;
+      unsigned acquired;
+      bool recursive;
+    public:
+      explicit SmartMutex(bool rec = true) :
+        impl(rec), acquired(0), recursive(rec) { }
+
+      bool lock() {
+        if (!mt_only || llvm_is_multithreaded()) {
+          return impl.acquire();
+        } else {
+          // Single-threaded debugging code.  This would be racy in
+          // multithreaded mode, but provides not sanity checks in single
+          // threaded mode.
+          assert((recursive || acquired == 0) && "Lock already acquired!!");
+          ++acquired;
+          return true;
+        }
+      }
+
+      bool unlock() {
+        if (!mt_only || llvm_is_multithreaded()) {
+          return impl.release();
+        } else {
+          // Single-threaded debugging code.  This would be racy in
+          // multithreaded mode, but provides not sanity checks in single
+          // threaded mode.
+          assert(((recursive && acquired) || (acquired == 1)) &&
+                 "Lock not acquired before release!");
+          --acquired;
+          return true;
+        }
+      }
+
+      bool try_lock() {
+        if (!mt_only || llvm_is_multithreaded())
+          return impl.tryacquire();
+        else return true;
+      }
+
+      private:
+        SmartMutex(const SmartMutex<mt_only> & original);
+        void operator=(const SmartMutex<mt_only> &);
+    };
+
+    /// Mutex - A standard, always enforced mutex.
+    typedef SmartMutex<false> Mutex;
+
+    template<bool mt_only>
+    class SmartScopedLock  {
+      SmartMutex<mt_only>& mtx;
+
+    public:
+      SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
+        mtx.lock();
+      }
+
+      ~SmartScopedLock() {
+        mtx.unlock();
+      }
+    };
+
+    typedef SmartScopedLock<false> ScopedLock;
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MutexGuard.h b/third_party/llvm-subzero/include/llvm/Support/MutexGuard.h
new file mode 100644
index 0000000..07b64b6
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/MutexGuard.h
@@ -0,0 +1,41 @@
+//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a guard for a block of code that ensures a Mutex is locked
+// upon construction and released upon destruction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MUTEXGUARD_H
+#define LLVM_SUPPORT_MUTEXGUARD_H
+
+#include "llvm/Support/Mutex.h"
+
+namespace llvm {
+  /// Instances of this class acquire a given Mutex Lock when constructed and
+  /// hold that lock until destruction. The intention is to instantiate one of
+  /// these on the stack at the top of some scope to be assured that C++
+  /// destruction of the object will always release the Mutex and thus avoid
+  /// a host of nasty multi-threading problems in the face of exceptions, etc.
+  /// @brief Guard a section of code with a Mutex.
+  class MutexGuard {
+    sys::Mutex &M;
+    MutexGuard(const MutexGuard &) = delete;
+    void operator=(const MutexGuard &) = delete;
+  public:
+    MutexGuard(sys::Mutex &m) : M(m) { M.lock(); }
+    ~MutexGuard() { M.unlock(); }
+    /// holds - Returns true if this locker instance holds the specified lock.
+    /// This is mostly used in assertions to validate that the correct mutex
+    /// is held.
+    bool holds(const sys::Mutex& lock) const { return &M == &lock; }
+  };
+}
+
+#endif // LLVM_SUPPORT_MUTEXGUARD_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Options.h b/third_party/llvm-subzero/include/llvm/Support/Options.h
new file mode 100644
index 0000000..7b61b23
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Options.h
@@ -0,0 +1,120 @@
+//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares helper objects for defining debug options that can be
+/// configured via the command line. The new API currently builds on the cl::opt
+/// API, but does not require the use of static globals.
+///
+/// With this API options are registered during initialization. For passes, this
+/// happens during pass initialization. Passes with options will call a static
+/// registerOptions method during initialization that registers options with the
+/// OptionRegistry. An example implementation of registerOptions is:
+///
+/// static void registerOptions() {
+///   OptionRegistry::registerOption<bool, Scalarizer,
+///                                &Scalarizer::ScalarizeLoadStore>(
+///       "scalarize-load-store",
+///       "Allow the scalarizer pass to scalarize loads and store", false);
+/// }
+///
+/// When reading data for options the interface is via the LLVMContext. Option
+/// data for passes should be read from the context during doInitialization. An
+/// example of reading the above option would be:
+///
+/// ScalarizeLoadStore =
+///   M.getContext().getOption<bool,
+///                            Scalarizer,
+///                            &Scalarizer::ScalarizeLoadStore>();
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_OPTIONS_H
+#define LLVM_SUPPORT_OPTIONS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+
+namespace detail {
+
+// Options are keyed of the unique address of a static character synthesized
+// based on template arguments.
+template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey {
+public:
+  static char ID;
+};
+
+template <typename ValT, typename Base, ValT(Base::*Mem)>
+char OptionKey<ValT, Base, Mem>::ID = 0;
+
+} // namespace detail
+
+/// \brief Singleton class used to register debug options.
+///
+/// The OptionRegistry is responsible for managing lifetimes of the options and
+/// provides interfaces for option registration and reading values from options.
+/// This object is a singleton, only one instance should ever exist so that all
+/// options are registered in the same place.
+class OptionRegistry {
+private:
+  DenseMap<void *, cl::Option *> Options;
+
+  /// \brief Adds a cl::Option to the registry.
+  ///
+  /// \param Key unique key for option
+  /// \param O option to map to \p Key
+  ///
+  /// Allocated cl::Options are owned by the OptionRegistry and are deallocated
+  /// on destruction or removal
+  void addOption(void *Key, cl::Option *O);
+
+public:
+  ~OptionRegistry();
+  OptionRegistry() {}
+
+  /// \brief Returns a reference to the singleton instance.
+  static OptionRegistry &instance();
+
+  /// \brief Registers an option with the OptionRegistry singleton.
+  ///
+  /// \tparam ValT type of the option's data
+  /// \tparam Base class used to key the option
+  /// \tparam Mem member of \p Base used for keying the option
+  ///
+  /// Options are keyed off the template parameters to generate unique static
+  /// characters. The template parameters are (1) the type of the data the
+  /// option stores (\p ValT), the class that will read the option (\p Base),
+  /// and the member that the class will store the data into (\p Mem).
+  template <typename ValT, typename Base, ValT(Base::*Mem)>
+  static void registerOption(const char *ArgStr, const char *Desc,
+                             const ValT &InitValue) {
+    cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc),
+                                              cl::Hidden, cl::init(InitValue));
+    instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option);
+  }
+
+  /// \brief Returns the value of the option.
+  ///
+  /// \tparam ValT type of the option's data
+  /// \tparam Base class used to key the option
+  /// \tparam Mem member of \p Base used for keying the option
+  ///
+  /// Reads option values based on the key generated by the template parameters.
+  /// Keying for get() is the same as keying for registerOption.
+  template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const {
+    auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID);
+    assert(It != Options.end() && "Option not in OptionRegistry");
+    return *(cl::opt<ValT> *)It->second;
+  }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Path.h b/third_party/llvm-subzero/include/llvm/Support/Path.h
new file mode 100644
index 0000000..853f099
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Path.h
@@ -0,0 +1,456 @@
+//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::path namespace. It is designed after
+// TR2/boost filesystem (v3), but modified to remove exception handling and the
+// path class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PATH_H
+#define LLVM_SUPPORT_PATH_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/DataTypes.h"
+#include <iterator>
+
+namespace llvm {
+namespace sys {
+namespace path {
+
+/// @name Lexical Component Iterator
+/// @{
+
+/// @brief Path iterator.
+///
+/// This is an input iterator that iterates over the individual components in
+/// \a path. The traversal order is as follows:
+/// * The root-name element, if present.
+/// * The root-directory element, if present.
+/// * Each successive filename element, if present.
+/// * Dot, if one or more trailing non-root slash characters are present.
+/// Traversing backwards is possible with \a reverse_iterator
+///
+/// Iteration examples. Each component is separated by ',':
+/// @code
+///   /          => /
+///   /foo       => /,foo
+///   foo/       => foo,.
+///   /foo/bar   => /,foo,bar
+///   ../        => ..,.
+///   C:\foo\bar => C:,/,foo,bar
+/// @endcode
+class const_iterator
+    : public std::iterator<std::input_iterator_tag, const StringRef> {
+  StringRef Path;      ///< The entire path.
+  StringRef Component; ///< The current component. Not necessarily in Path.
+  size_t    Position;  ///< The iterators current position within Path.
+
+  // An end iterator has Position = Path.size() + 1.
+  friend const_iterator begin(StringRef path);
+  friend const_iterator end(StringRef path);
+
+public:
+  reference operator*() const { return Component; }
+  pointer   operator->() const { return &Component; }
+  const_iterator &operator++();    // preincrement
+  bool operator==(const const_iterator &RHS) const;
+  bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); }
+
+  /// @brief Difference in bytes between this and RHS.
+  ptrdiff_t operator-(const const_iterator &RHS) const;
+};
+
+/// @brief Reverse path iterator.
+///
+/// This is an input iterator that iterates over the individual components in
+/// \a path in reverse order. The traversal order is exactly reversed from that
+/// of \a const_iterator
+class reverse_iterator
+    : public std::iterator<std::input_iterator_tag, const StringRef> {
+  StringRef Path;      ///< The entire path.
+  StringRef Component; ///< The current component. Not necessarily in Path.
+  size_t    Position;  ///< The iterators current position within Path.
+
+  friend reverse_iterator rbegin(StringRef path);
+  friend reverse_iterator rend(StringRef path);
+
+public:
+  reference operator*() const { return Component; }
+  pointer   operator->() const { return &Component; }
+  reverse_iterator &operator++();    // preincrement
+  bool operator==(const reverse_iterator &RHS) const;
+  bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); }
+
+  /// @brief Difference in bytes between this and RHS.
+  ptrdiff_t operator-(const reverse_iterator &RHS) const;
+};
+
+/// @brief Get begin iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized with the first component of \a path.
+const_iterator begin(StringRef path);
+
+/// @brief Get end iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized to the end of \a path.
+const_iterator end(StringRef path);
+
+/// @brief Get reverse begin iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized with the first reverse component of \a path.
+reverse_iterator rbegin(StringRef path);
+
+/// @brief Get reverse end iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized to the reverse end of \a path.
+reverse_iterator rend(StringRef path);
+
+/// @}
+/// @name Lexical Modifiers
+/// @{
+
+/// @brief Remove the last component from \a path unless it is the root dir.
+///
+/// @code
+///   directory/filename.cpp => directory/
+///   directory/             => directory
+///   filename.cpp           => <empty>
+///   /                      => /
+/// @endcode
+///
+/// @param path A path that is modified to not have a file component.
+void remove_filename(SmallVectorImpl<char> &path);
+
+/// @brief Replace the file extension of \a path with \a extension.
+///
+/// @code
+///   ./filename.cpp => ./filename.extension
+///   ./filename     => ./filename.extension
+///   ./             => ./.extension
+/// @endcode
+///
+/// @param path A path that has its extension replaced with \a extension.
+/// @param extension The extension to be added. It may be empty. It may also
+///                  optionally start with a '.', if it does not, one will be
+///                  prepended.
+void replace_extension(SmallVectorImpl<char> &path, const Twine &extension);
+
+/// @brief Replace matching path prefix with another path.
+///
+/// @code
+///   /foo, /old, /new => /foo
+///   /old/foo, /old, /new => /new/foo
+///   /foo, <empty>, /new => /new/foo
+///   /old/foo, /old, <empty> => /foo
+/// @endcode
+///
+/// @param Path If \a Path starts with \a OldPrefix modify to instead
+///        start with \a NewPrefix.
+/// @param OldPrefix The path prefix to strip from \a Path.
+/// @param NewPrefix The path prefix to replace \a NewPrefix with.
+void replace_path_prefix(SmallVectorImpl<char> &Path,
+                         const StringRef &OldPrefix,
+                         const StringRef &NewPrefix);
+
+/// @brief Append to path.
+///
+/// @code
+///   /foo  + bar/f => /foo/bar/f
+///   /foo/ + bar/f => /foo/bar/f
+///   foo   + bar/f => foo/bar/f
+/// @endcode
+///
+/// @param path Set to \a path + \a component.
+/// @param a The component to be appended to \a path.
+void append(SmallVectorImpl<char> &path, const Twine &a,
+                                         const Twine &b = "",
+                                         const Twine &c = "",
+                                         const Twine &d = "");
+
+/// @brief Append to path.
+///
+/// @code
+///   /foo  + [bar,f] => /foo/bar/f
+///   /foo/ + [bar,f] => /foo/bar/f
+///   foo   + [bar,f] => foo/bar/f
+/// @endcode
+///
+/// @param path Set to \a path + [\a begin, \a end).
+/// @param begin Start of components to append.
+/// @param end One past the end of components to append.
+void append(SmallVectorImpl<char> &path,
+            const_iterator begin, const_iterator end);
+
+/// @}
+/// @name Transforms (or some other better name)
+/// @{
+
+/// Convert path to the native form. This is used to give paths to users and
+/// operating system calls in the platform's normal way. For example, on Windows
+/// all '/' are converted to '\'.
+///
+/// @param path A path that is transformed to native format.
+/// @param result Holds the result of the transformation.
+void native(const Twine &path, SmallVectorImpl<char> &result);
+
+/// Convert path to the native form in place. This is used to give paths to
+/// users and operating system calls in the platform's normal way. For example,
+/// on Windows all '/' are converted to '\'.
+///
+/// @param path A path that is transformed to native format.
+void native(SmallVectorImpl<char> &path);
+
+/// @}
+/// @name Lexical Observers
+/// @{
+
+/// @brief Get root name.
+///
+/// @code
+///   //net/hello => //net
+///   c:/hello    => c: (on Windows, on other platforms nothing)
+///   /hello      => <empty>
+/// @endcode
+///
+/// @param path Input path.
+/// @result The root name of \a path if it has one, otherwise "".
+StringRef root_name(StringRef path);
+
+/// @brief Get root directory.
+///
+/// @code
+///   /goo/hello => /
+///   c:/hello   => /
+///   d/file.txt => <empty>
+/// @endcode
+///
+/// @param path Input path.
+/// @result The root directory of \a path if it has one, otherwise
+///               "".
+StringRef root_directory(StringRef path);
+
+/// @brief Get root path.
+///
+/// Equivalent to root_name + root_directory.
+///
+/// @param path Input path.
+/// @result The root path of \a path if it has one, otherwise "".
+StringRef root_path(StringRef path);
+
+/// @brief Get relative path.
+///
+/// @code
+///   C:\hello\world => hello\world
+///   foo/bar        => foo/bar
+///   /foo/bar       => foo/bar
+/// @endcode
+///
+/// @param path Input path.
+/// @result The path starting after root_path if one exists, otherwise "".
+StringRef relative_path(StringRef path);
+
+/// @brief Get parent path.
+///
+/// @code
+///   /          => <empty>
+///   /foo       => /
+///   foo/../bar => foo/..
+/// @endcode
+///
+/// @param path Input path.
+/// @result The parent path of \a path if one exists, otherwise "".
+StringRef parent_path(StringRef path);
+
+/// @brief Get filename.
+///
+/// @code
+///   /foo.txt    => foo.txt
+///   .          => .
+///   ..         => ..
+///   /          => /
+/// @endcode
+///
+/// @param path Input path.
+/// @result The filename part of \a path. This is defined as the last component
+///         of \a path.
+StringRef filename(StringRef path);
+
+/// @brief Get stem.
+///
+/// If filename contains a dot but not solely one or two dots, result is the
+/// substring of filename ending at (but not including) the last dot. Otherwise
+/// it is filename.
+///
+/// @code
+///   /foo/bar.txt => bar
+///   /foo/bar     => bar
+///   /foo/.txt    => <empty>
+///   /foo/.       => .
+///   /foo/..      => ..
+/// @endcode
+///
+/// @param path Input path.
+/// @result The stem of \a path.
+StringRef stem(StringRef path);
+
+/// @brief Get extension.
+///
+/// If filename contains a dot but not solely one or two dots, result is the
+/// substring of filename starting at (and including) the last dot, and ending
+/// at the end of \a path. Otherwise "".
+///
+/// @code
+///   /foo/bar.txt => .txt
+///   /foo/bar     => <empty>
+///   /foo/.txt    => .txt
+/// @endcode
+///
+/// @param path Input path.
+/// @result The extension of \a path.
+StringRef extension(StringRef path);
+
+/// @brief Check whether the given char is a path separator on the host OS.
+///
+/// @param value a character
+/// @result true if \a value is a path separator character on the host OS
+bool is_separator(char value);
+
+/// @brief Return the preferred separator for this platform.
+///
+/// @result StringRef of the preferred separator, null-terminated.
+StringRef get_separator();
+
+/// @brief Get the typical temporary directory for the system, e.g.,
+/// "/var/tmp" or "C:/TEMP"
+///
+/// @param erasedOnReboot Whether to favor a path that is erased on reboot
+/// rather than one that potentially persists longer. This parameter will be
+/// ignored if the user or system has set the typical environment variable
+/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory.
+///
+/// @param result Holds the resulting path name.
+void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result);
+
+/// @brief Get the user's home directory.
+///
+/// @param result Holds the resulting path name.
+/// @result True if a home directory is set, false otherwise.
+bool home_directory(SmallVectorImpl<char> &result);
+
+/// @brief Get the user's cache directory.
+///
+/// Expect the resulting path to be a directory shared with other
+/// applications/services used by the user. Params \p Path1 to \p Path3 can be
+/// used to append additional directory names to the resulting path. Recommended
+/// pattern is <user_cache_directory>/<vendor>/<application>.
+///
+/// @param Result Holds the resulting path.
+/// @param Path1 Additional path to be appended to the user's cache directory
+/// path. "" can be used to append nothing.
+/// @param Path2 Second additional path to be appended.
+/// @param Path3 Third additional path to be appended.
+/// @result True if a cache directory path is set, false otherwise.
+bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
+                          const Twine &Path2 = "", const Twine &Path3 = "");
+
+/// @brief Has root name?
+///
+/// root_name != ""
+///
+/// @param path Input path.
+/// @result True if the path has a root name, false otherwise.
+bool has_root_name(const Twine &path);
+
+/// @brief Has root directory?
+///
+/// root_directory != ""
+///
+/// @param path Input path.
+/// @result True if the path has a root directory, false otherwise.
+bool has_root_directory(const Twine &path);
+
+/// @brief Has root path?
+///
+/// root_path != ""
+///
+/// @param path Input path.
+/// @result True if the path has a root path, false otherwise.
+bool has_root_path(const Twine &path);
+
+/// @brief Has relative path?
+///
+/// relative_path != ""
+///
+/// @param path Input path.
+/// @result True if the path has a relative path, false otherwise.
+bool has_relative_path(const Twine &path);
+
+/// @brief Has parent path?
+///
+/// parent_path != ""
+///
+/// @param path Input path.
+/// @result True if the path has a parent path, false otherwise.
+bool has_parent_path(const Twine &path);
+
+/// @brief Has filename?
+///
+/// filename != ""
+///
+/// @param path Input path.
+/// @result True if the path has a filename, false otherwise.
+bool has_filename(const Twine &path);
+
+/// @brief Has stem?
+///
+/// stem != ""
+///
+/// @param path Input path.
+/// @result True if the path has a stem, false otherwise.
+bool has_stem(const Twine &path);
+
+/// @brief Has extension?
+///
+/// extension != ""
+///
+/// @param path Input path.
+/// @result True if the path has a extension, false otherwise.
+bool has_extension(const Twine &path);
+
+/// @brief Is path absolute?
+///
+/// @param path Input path.
+/// @result True if the path is absolute, false if it is not.
+bool is_absolute(const Twine &path);
+
+/// @brief Is path relative?
+///
+/// @param path Input path.
+/// @result True if the path is relative, false if it is not.
+bool is_relative(const Twine &path);
+
+/// @brief Remove redundant leading "./" pieces and consecutive separators.
+///
+/// @param path Input path.
+/// @result The cleaned-up \a path.
+StringRef remove_leading_dotslash(StringRef path);
+
+/// @brief In-place remove any './' and optionally '../' components from a path.
+///
+/// @param path processed path
+/// @param remove_dot_dot specify if '../' should be removed
+/// @result True if path was changed
+bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false);
+
+} // end namespace path
+} // end namespace sys
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/PointerLikeTypeTraits.h b/third_party/llvm-subzero/include/llvm/Support/PointerLikeTypeTraits.h
new file mode 100644
index 0000000..96cdaed
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/PointerLikeTypeTraits.h
@@ -0,0 +1,94 @@
+//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PointerLikeTypeTraits class.  This allows data
+// structures to reason about pointers and other things that are pointer sized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
+#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
+
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+/// A traits type that is used to handle pointer types and things that are just
+/// wrappers for pointers as a uniform entity.
+template <typename T> class PointerLikeTypeTraits {
+  // getAsVoidPointer
+  // getFromVoidPointer
+  // getNumLowBitsAvailable
+};
+
+namespace detail {
+/// A tiny meta function to compute the log2 of a compile time constant.
+template <size_t N>
+struct ConstantLog2
+    : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {};
+template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};
+}
+
+// Provide PointerLikeTypeTraits for non-cvr pointers.
+template <typename T> class PointerLikeTypeTraits<T *> {
+public:
+  static inline void *getAsVoidPointer(T *P) { return P; }
+  static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
+
+  enum {
+    NumLowBitsAvailable = detail::ConstantLog2<AlignOf<T>::Alignment>::value
+  };
+};
+
+template <> class PointerLikeTypeTraits<void *> {
+public:
+  static inline void *getAsVoidPointer(void *P) { return P; }
+  static inline void *getFromVoidPointer(void *P) { return P; }
+
+  /// Note, we assume here that void* is related to raw malloc'ed memory and
+  /// that malloc returns objects at least 4-byte aligned. However, this may be
+  /// wrong, or pointers may be from something other than malloc. In this case,
+  /// you should specify a real typed pointer or avoid this template.
+  ///
+  /// All clients should use assertions to do a run-time check to ensure that
+  /// this is actually true.
+  enum { NumLowBitsAvailable = 2 };
+};
+
+// Provide PointerLikeTypeTraits for const pointers.
+template <typename T> class PointerLikeTypeTraits<const T *> {
+  typedef PointerLikeTypeTraits<T *> NonConst;
+
+public:
+  static inline const void *getAsVoidPointer(const T *P) {
+    return NonConst::getAsVoidPointer(const_cast<T *>(P));
+  }
+  static inline const T *getFromVoidPointer(const void *P) {
+    return NonConst::getFromVoidPointer(const_cast<void *>(P));
+  }
+  enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+};
+
+// Provide PointerLikeTypeTraits for uintptr_t.
+template <> class PointerLikeTypeTraits<uintptr_t> {
+public:
+  static inline void *getAsVoidPointer(uintptr_t P) {
+    return reinterpret_cast<void *>(P);
+  }
+  static inline uintptr_t getFromVoidPointer(void *P) {
+    return reinterpret_cast<uintptr_t>(P);
+  }
+  // No bits are available!
+  enum { NumLowBitsAvailable = 0 };
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Process.h b/third_party/llvm-subzero/include/llvm/Support/Process.h
new file mode 100644
index 0000000..06fd0af
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Process.h
@@ -0,0 +1,193 @@
+//===- llvm/Support/Process.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Provides a library for accessing information about this process and other
+/// processes on the operating system. Also provides means of spawning
+/// subprocess for commands. The design of this library is modeled after the
+/// proposed design of the Boost.Process library, and is design specifically to
+/// follow the style of standard libraries and potentially become a proposal
+/// for a standard library.
+///
+/// This file declares the llvm::sys::Process class which contains a collection
+/// of legacy static interfaces for extracting various information about the
+/// current process. The goal is to migrate users of this API over to the new
+/// interfaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PROCESS_H
+#define LLVM_SUPPORT_PROCESS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/TimeValue.h"
+#include <system_error>
+
+namespace llvm {
+template <typename T> class ArrayRef;
+class StringRef;
+
+namespace sys {
+
+
+/// \brief A collection of legacy interfaces for querying information about the
+/// current executing process.
+class Process {
+public:
+  static unsigned getPageSize();
+
+  /// \brief Return process memory usage.
+  /// This static function will return the total amount of memory allocated
+  /// by the process. This only counts the memory allocated via the malloc,
+  /// calloc and realloc functions and includes any "free" holes in the
+  /// allocated space.
+  static size_t GetMallocUsage();
+
+  /// This static function will set \p user_time to the amount of CPU time
+  /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU
+  /// time spent in system (kernel) mode.  If the operating system does not
+  /// support collection of these metrics, a zero TimeValue will be for both
+  /// values.
+  /// \param elapsed Returns the TimeValue::now() giving current time
+  /// \param user_time Returns the current amount of user time for the process
+  /// \param sys_time Returns the current amount of system time for the process
+  static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
+                           TimeValue &sys_time);
+
+  /// This function makes the necessary calls to the operating system to
+  /// prevent core files or any other kind of large memory dumps that can
+  /// occur when a program fails.
+  /// @brief Prevent core file generation.
+  static void PreventCoreFiles();
+
+  /// \brief true if PreventCoreFiles has been called, false otherwise.
+  static bool AreCoreFilesPrevented();
+
+  // This function returns the environment variable \arg name's value as a UTF-8
+  // string. \arg Name is assumed to be in UTF-8 encoding too.
+  static Optional<std::string> GetEnv(StringRef name);
+
+  /// This function searches for an existing file in the list of directories
+  /// in a PATH like environment variable, and returns the first file found,
+  /// according to the order of the entries in the PATH like environment
+  /// variable.
+  static Optional<std::string> FindInEnvPath(const std::string& EnvName,
+                                             const std::string& FileName);
+
+  /// This function returns a SmallVector containing the arguments passed from
+  /// the operating system to the program.  This function expects to be handed
+  /// the vector passed in from main.
+  static std::error_code
+  GetArgumentVector(SmallVectorImpl<const char *> &Args,
+                    ArrayRef<const char *> ArgsFromMain,
+                    SpecificBumpPtrAllocator<char> &ArgAllocator);
+
+  // This functions ensures that the standard file descriptors (input, output,
+  // and error) are properly mapped to a file descriptor before we use any of
+  // them.  This should only be called by standalone programs, library
+  // components should not call this.
+  static std::error_code FixupStandardFileDescriptors();
+
+  // This function safely closes a file descriptor.  It is not safe to retry
+  // close(2) when it returns with errno equivalent to EINTR; this is because
+  // *nixen cannot agree if the file descriptor is, in fact, closed when this
+  // occurs.
+  //
+  // N.B. Some operating systems, due to thread cancellation, cannot properly
+  // guarantee that it will or will not be closed one way or the other!
+  static std::error_code SafelyCloseFileDescriptor(int FD);
+
+  /// This function determines if the standard input is connected directly
+  /// to a user's input (keyboard probably), rather than coming from a file
+  /// or pipe.
+  static bool StandardInIsUserInput();
+
+  /// This function determines if the standard output is connected to a
+  /// "tty" or "console" window. That is, the output would be displayed to
+  /// the user rather than being put on a pipe or stored in a file.
+  static bool StandardOutIsDisplayed();
+
+  /// This function determines if the standard error is connected to a
+  /// "tty" or "console" window. That is, the output would be displayed to
+  /// the user rather than being put on a pipe or stored in a file.
+  static bool StandardErrIsDisplayed();
+
+  /// This function determines if the given file descriptor is connected to
+  /// a "tty" or "console" window. That is, the output would be displayed to
+  /// the user rather than being put on a pipe or stored in a file.
+  static bool FileDescriptorIsDisplayed(int fd);
+
+  /// This function determines if the given file descriptor is displayd and
+  /// supports colors.
+  static bool FileDescriptorHasColors(int fd);
+
+  /// This function determines the number of columns in the window
+  /// if standard output is connected to a "tty" or "console"
+  /// window. If standard output is not connected to a tty or
+  /// console, or if the number of columns cannot be determined,
+  /// this routine returns zero.
+  static unsigned StandardOutColumns();
+
+  /// This function determines the number of columns in the window
+  /// if standard error is connected to a "tty" or "console"
+  /// window. If standard error is not connected to a tty or
+  /// console, or if the number of columns cannot be determined,
+  /// this routine returns zero.
+  static unsigned StandardErrColumns();
+
+  /// This function determines whether the terminal connected to standard
+  /// output supports colors. If standard output is not connected to a
+  /// terminal, this function returns false.
+  static bool StandardOutHasColors();
+
+  /// This function determines whether the terminal connected to standard
+  /// error supports colors. If standard error is not connected to a
+  /// terminal, this function returns false.
+  static bool StandardErrHasColors();
+
+  /// Enables or disables whether ANSI escape sequences are used to output
+  /// colors. This only has an effect on Windows.
+  /// Note: Setting this option is not thread-safe and should only be done
+  /// during initialization.
+  static void UseANSIEscapeCodes(bool enable);
+
+  /// Whether changing colors requires the output to be flushed.
+  /// This is needed on systems that don't support escape sequences for
+  /// changing colors.
+  static bool ColorNeedsFlush();
+
+  /// This function returns the colorcode escape sequences.
+  /// If ColorNeedsFlush() is true then this function will change the colors
+  /// and return an empty escape sequence. In that case it is the
+  /// responsibility of the client to flush the output stream prior to
+  /// calling this function.
+  static const char *OutputColor(char c, bool bold, bool bg);
+
+  /// Same as OutputColor, but only enables the bold attribute.
+  static const char *OutputBold(bool bg);
+
+  /// This function returns the escape sequence to reverse forground and
+  /// background colors.
+  static const char *OutputReverse();
+
+  /// Resets the terminals colors, or returns an escape sequence to do so.
+  static const char *ResetColor();
+
+  /// Get the result of a process wide random number generator. The
+  /// generator will be automatically seeded in non-deterministic fashion.
+  static unsigned GetRandomNumber();
+};
+
+}
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Program.h b/third_party/llvm-subzero/include/llvm/Support/Program.h
new file mode 100644
index 0000000..055f016
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Program.h
@@ -0,0 +1,194 @@
+//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::Program class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PROGRAM_H
+#define LLVM_SUPPORT_PROGRAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ErrorOr.h"
+#include <system_error>
+
+namespace llvm {
+class StringRef;
+
+namespace sys {
+
+  /// This is the OS-specific separator for PATH like environment variables:
+  // a colon on Unix or a semicolon on Windows.
+#if defined(LLVM_ON_UNIX)
+  const char EnvPathSeparator = ':';
+#elif defined (LLVM_ON_WIN32)
+  const char EnvPathSeparator = ';';
+#endif
+
+/// @brief This struct encapsulates information about a process.
+struct ProcessInfo {
+#if defined(LLVM_ON_UNIX)
+  typedef pid_t ProcessId;
+#elif defined(LLVM_ON_WIN32)
+  typedef unsigned long ProcessId; // Must match the type of DWORD on Windows.
+  typedef void * HANDLE; // Must match the type of HANDLE on Windows.
+  /// The handle to the process (available on Windows only).
+  HANDLE ProcessHandle;
+#else
+#error "ProcessInfo is not defined for this platform!"
+#endif
+
+  enum : ProcessId { InvalidPid = 0 };
+
+  /// The process identifier.
+  ProcessId Pid;
+
+  /// The return code, set after execution.
+  int ReturnCode;
+
+  ProcessInfo();
+};
+
+  /// \brief Find the first executable file \p Name in \p Paths.
+  ///
+  /// This does not perform hashing as a shell would but instead stats each PATH
+  /// entry individually so should generally be avoided. Core LLVM library
+  /// functions and options should instead require fully specified paths.
+  ///
+  /// \param Name name of the executable to find. If it contains any system
+  ///   slashes, it will be returned as is.
+  /// \param Paths optional list of paths to search for \p Name. If empty it
+  ///   will use the system PATH environment instead.
+  ///
+  /// \returns The fully qualified path to the first \p Name in \p Paths if it
+  ///   exists. \p Name if \p Name has slashes in it. Otherwise an error.
+  ErrorOr<std::string>
+  findProgramByName(StringRef Name, ArrayRef<StringRef> Paths = None);
+
+  // These functions change the specified standard stream (stdin or stdout) to
+  // binary mode. They return errc::success if the specified stream
+  // was changed. Otherwise a platform dependent error is returned.
+  std::error_code ChangeStdinToBinary();
+  std::error_code ChangeStdoutToBinary();
+
+  /// This function executes the program using the arguments provided.  The
+  /// invoked program will inherit the stdin, stdout, and stderr file
+  /// descriptors, the environment and other configuration settings of the
+  /// invoking program.
+  /// This function waits for the program to finish, so should be avoided in
+  /// library functions that aren't expected to block. Consider using
+  /// ExecuteNoWait() instead.
+  /// @returns an integer result code indicating the status of the program.
+  /// A zero or positive value indicates the result code of the program.
+  /// -1 indicates failure to execute
+  /// -2 indicates a crash during execution or timeout
+  int ExecuteAndWait(
+      StringRef Program, ///< Path of the program to be executed. It is
+      ///< presumed this is the result of the findProgramByName method.
+      const char **args, ///< A vector of strings that are passed to the
+      ///< program.  The first element should be the name of the program.
+      ///< The list *must* be terminated by a null char* entry.
+      const char **env = nullptr, ///< An optional vector of strings to use for
+      ///< the program's environment. If not provided, the current program's
+      ///< environment will be used.
+      const StringRef **redirects = nullptr, ///< An optional array of pointers
+      ///< to paths. If the array is null, no redirection is done. The array
+      ///< should have a size of at least three. The inferior process's
+      ///< stdin(0), stdout(1), and stderr(2) will be redirected to the
+      ///< corresponding paths.
+      ///< When an empty path is passed in, the corresponding file
+      ///< descriptor will be disconnected (ie, /dev/null'd) in a portable
+      ///< way.
+      unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount
+      ///< of time to wait for the child process to exit. If the time
+      ///< expires, the child is killed and this call returns. If zero,
+      ///< this function will wait until the child finishes or forever if
+      ///< it doesn't.
+      unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount
+      ///< of memory can be allocated by process. If memory usage will be
+      ///< higher limit, the child is killed and this call returns. If zero
+      ///< - no memory limit.
+      std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
+      ///< string instance in which error messages will be returned. If the
+      ///< string is non-empty upon return an error occurred while invoking the
+      ///< program.
+      bool *ExecutionFailed = nullptr);
+
+  /// Similar to ExecuteAndWait, but returns immediately.
+  /// @returns The \see ProcessInfo of the newly launced process.
+  /// \note On Microsoft Windows systems, users will need to either call \see
+  /// Wait until the process finished execution or win32 CloseHandle() API on
+  /// ProcessInfo.ProcessHandle to avoid memory leaks.
+  ProcessInfo
+  ExecuteNoWait(StringRef Program, const char **args, const char **env = nullptr,
+                const StringRef **redirects = nullptr, unsigned memoryLimit = 0,
+                std::string *ErrMsg = nullptr, bool *ExecutionFailed = nullptr);
+
+  /// Return true if the given arguments fit within system-specific
+  /// argument length limits.
+  bool commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef<const char*> Args);
+
+  /// File encoding options when writing contents that a non-UTF8 tool will
+  /// read (on Windows systems). For UNIX, we always use UTF-8.
+  enum WindowsEncodingMethod {
+    /// UTF-8 is the LLVM native encoding, being the same as "do not perform
+    /// encoding conversion".
+    WEM_UTF8,
+    WEM_CurrentCodePage,
+    WEM_UTF16
+  };
+
+  /// Saves the UTF8-encoded \p contents string into the file \p FileName
+  /// using a specific encoding.
+  ///
+  /// This write file function adds the possibility to choose which encoding
+  /// to use when writing a text file. On Windows, this is important when
+  /// writing files with internationalization support with an encoding that is
+  /// different from the one used in LLVM (UTF-8). We use this when writing
+  /// response files, since GCC tools on MinGW only understand legacy code
+  /// pages, and VisualStudio tools only understand UTF-16.
+  /// For UNIX, using different encodings is silently ignored, since all tools
+  /// work well with UTF-8.
+  /// This function assumes that you only use UTF-8 *text* data and will convert
+  /// it to your desired encoding before writing to the file.
+  ///
+  /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in
+  /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is
+  /// our best shot to make gcc/ld understand international characters. This
+  /// should be changed as soon as binutils fix this to support UTF16 on mingw.
+  ///
+  /// \returns non-zero error_code if failed
+  std::error_code
+  writeFileWithEncoding(StringRef FileName, StringRef Contents,
+                        WindowsEncodingMethod Encoding = WEM_UTF8);
+
+  /// This function waits for the process specified by \p PI to finish.
+  /// \returns A \see ProcessInfo struct with Pid set to:
+  /// \li The process id of the child process if the child process has changed
+  /// state.
+  /// \li 0 if the child process has not changed state.
+  /// \note Users of this function should always check the ReturnCode member of
+  /// the \see ProcessInfo returned from this function.
+  ProcessInfo Wait(
+      const ProcessInfo &PI, ///< The child process that should be waited on.
+      unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
+      ///< time to wait for the child process to exit. If the time expires, the
+      ///< child is killed and this function returns. If zero, this function
+      ///< will perform a non-blocking wait on the child process.
+      bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
+      ///< until child has terminated.
+      std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a
+      ///< string instance in which error messages will be returned. If the
+      ///< string is non-empty upon return an error occurred while invoking the
+      ///< program.
+      );
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Signals.h b/third_party/llvm-subzero/include/llvm/Support/Signals.h
new file mode 100644
index 0000000..cbd6f68
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Signals.h
@@ -0,0 +1,77 @@
+//===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines some helpful functions for dealing with the possibility of
+// unix signals occurring while your program is running.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SIGNALS_H
+#define LLVM_SUPPORT_SIGNALS_H
+
+#include <string>
+
+namespace llvm {
+class StringRef;
+class raw_ostream;
+
+namespace sys {
+
+  /// This function runs all the registered interrupt handlers, including the
+  /// removal of files registered by RemoveFileOnSignal.
+  void RunInterruptHandlers();
+
+  /// This function registers signal handlers to ensure that if a signal gets
+  /// delivered that the named file is removed.
+  /// @brief Remove a file if a fatal signal occurs.
+  bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr);
+
+  /// This function removes a file from the list of files to be removed on
+  /// signal delivery.
+  void DontRemoveFileOnSignal(StringRef Filename);
+
+  /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the
+  /// process, print a stack trace and then exit.
+  /// \brief Print a stack trace if a fatal signal occurs.
+  /// \param Argv0 the current binary name, used to find the symbolizer
+  ///        relative to the current binary before searching $PATH; can be
+  ///        StringRef(), in which case we will only search $PATH.
+  /// \param DisableCrashReporting if \c true, disable the normal crash
+  ///        reporting mechanisms on the underlying operating system.
+  void PrintStackTraceOnErrorSignal(StringRef Argv0,
+                                    bool DisableCrashReporting = false);
+
+  /// Disable all system dialog boxes that appear when the process crashes.
+  void DisableSystemDialogsOnCrash();
+
+  /// \brief Print the stack trace using the given \c raw_ostream object.
+  void PrintStackTrace(raw_ostream &OS);
+
+  // Run all registered signal handlers.
+  void RunSignalHandlers();
+
+  /// AddSignalHandler - Add a function to be called when an abort/kill signal
+  /// is delivered to the process.  The handler can have a cookie passed to it
+  /// to identify what instance of the handler it is.
+  void AddSignalHandler(void (*FnPtr)(void *), void *Cookie);
+
+  /// This function registers a function to be called when the user "interrupts"
+  /// the program (typically by pressing ctrl-c).  When the user interrupts the
+  /// program, the specified interrupt function is called instead of the program
+  /// being killed, and the interrupt function automatically disabled.  Note
+  /// that interrupt functions are not allowed to call any non-reentrant
+  /// functions.  An null interrupt function pointer disables the current
+  /// installed function.  Note also that the handler may be executed on a
+  /// different thread on some platforms.
+  /// @brief Register a function to be called when ctrl-c is pressed.
+  void SetInterruptFunction(void (*IF)());
+} // End sys namespace
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/StreamingMemoryObject.h b/third_party/llvm-subzero/include/llvm/Support/StreamingMemoryObject.h
new file mode 100644
index 0000000..1ab8537
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/StreamingMemoryObject.h
@@ -0,0 +1,87 @@
+//===- StreamingMemoryObject.h - Streamable data interface -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H
+#define LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryObject.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+
+/// Interface to data which is actually streamed from a DataStreamer. In
+/// addition to inherited members, it has the dropLeadingBytes and
+/// setKnownObjectSize methods which are not applicable to non-streamed objects.
+class StreamingMemoryObject : public MemoryObject {
+public:
+  StreamingMemoryObject(std::unique_ptr<DataStreamer> Streamer);
+  uint64_t getExtent() const override;
+  uint64_t readBytes(uint8_t *Buf, uint64_t Size,
+                     uint64_t Address) const override;
+  const uint8_t *getPointer(uint64_t Address, uint64_t Size) const override;
+  bool isValidAddress(uint64_t address) const override;
+
+  /// Drop s bytes from the front of the stream, pushing the positions of the
+  /// remaining bytes down by s. This is used to skip past the bitcode header,
+  /// since we don't know a priori if it's present, and we can't put bytes
+  /// back into the stream once we've read them.
+  bool dropLeadingBytes(size_t s);
+
+  /// If the data object size is known in advance, many of the operations can
+  /// be made more efficient, so this method should be called before reading
+  /// starts (although it can be called anytime).
+  void setKnownObjectSize(size_t size);
+
+  /// The number of bytes read at a time from the data streamer.
+  static const uint32_t kChunkSize = 4096 * 4;
+
+private:
+  mutable std::vector<unsigned char> Bytes;
+  std::unique_ptr<DataStreamer> Streamer;
+  mutable size_t BytesRead;   // Bytes read from stream
+  size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header)
+  mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached
+  mutable bool EOFReached;
+
+  // Fetch enough bytes such that Pos can be read (i.e. BytesRead >
+  // Pos). Returns true if Pos can be read.  Unlike most of the
+  // functions in BitcodeReader, returns true on success.  Most of the
+  // requests will be small, but we fetch at kChunkSize bytes at a
+  // time to avoid making too many potentially expensive GetBytes
+  // calls.
+  bool fetchToPos(size_t Pos) const {
+    while (Pos >= BytesRead) {
+      if (EOFReached)
+        return false;
+      Bytes.resize(BytesRead + BytesSkipped + kChunkSize);
+      size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped],
+                                        kChunkSize);
+      BytesRead += bytes;
+      if (bytes == 0) { // reached EOF/ran out of bytes
+        if (ObjectSize == 0)
+          ObjectSize = BytesRead;
+        EOFReached = true;
+      }
+    }
+    return !ObjectSize || Pos < ObjectSize;
+  }
+
+  StreamingMemoryObject(const StreamingMemoryObject&) = delete;
+  void operator=(const StreamingMemoryObject&) = delete;
+};
+
+MemoryObject *getNonStreamedMemoryObject(
+    const unsigned char *Start, const unsigned char *End);
+
+}
+#endif  // STREAMINGMEMORYOBJECT_H_
diff --git a/third_party/llvm-subzero/include/llvm/Support/StringSaver.h b/third_party/llvm-subzero/include/llvm/Support/StringSaver.h
new file mode 100644
index 0000000..38fb7bb
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/StringSaver.h
@@ -0,0 +1,32 @@
+//===- llvm/Support/StringSaver.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_STRINGSAVER_H
+#define LLVM_SUPPORT_STRINGSAVER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Allocator.h"
+
+namespace llvm {
+
+/// \brief Saves strings in the inheritor's stable storage and returns a stable
+/// raw character pointer.
+class StringSaver final {
+  BumpPtrAllocator &Alloc;
+
+public:
+  StringSaver(BumpPtrAllocator &Alloc) : Alloc(Alloc) {}
+  const char *save(const char *S) { return save(StringRef(S)); }
+  const char *save(StringRef S);
+  const char *save(const Twine &S) { return save(StringRef(S.str())); }
+  const char *save(std::string &S) { return save(StringRef(S)); }
+};
+}
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/SwapByteOrder.h b/third_party/llvm-subzero/include/llvm/Support/SwapByteOrder.h
new file mode 100644
index 0000000..91693ac
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/SwapByteOrder.h
@@ -0,0 +1,124 @@
+//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares generic and optimized functions to swap the byte order of
+// an integral type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
+#define LLVM_SUPPORT_SWAPBYTEORDER_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include <cstddef>
+
+namespace llvm {
+namespace sys {
+
+/// SwapByteOrder_16 - This function returns a byte-swapped representation of
+/// the 16-bit argument.
+inline uint16_t SwapByteOrder_16(uint16_t value) {
+#if defined(_MSC_VER) && !defined(_DEBUG)
+  // The DLL version of the runtime lacks these functions (bug!?), but in a
+  // release build they're replaced with BSWAP instructions anyway.
+  return _byteswap_ushort(value);
+#else
+  uint16_t Hi = value << 8;
+  uint16_t Lo = value >> 8;
+  return Hi | Lo;
+#endif
+}
+
+/// SwapByteOrder_32 - This function returns a byte-swapped representation of
+/// the 32-bit argument.
+inline uint32_t SwapByteOrder_32(uint32_t value) {
+#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
+  return __builtin_bswap32(value);
+#elif defined(_MSC_VER) && !defined(_DEBUG)
+  return _byteswap_ulong(value);
+#else
+  uint32_t Byte0 = value & 0x000000FF;
+  uint32_t Byte1 = value & 0x0000FF00;
+  uint32_t Byte2 = value & 0x00FF0000;
+  uint32_t Byte3 = value & 0xFF000000;
+  return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
+#endif
+}
+
+/// SwapByteOrder_64 - This function returns a byte-swapped representation of
+/// the 64-bit argument.
+inline uint64_t SwapByteOrder_64(uint64_t value) {
+#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
+  return __builtin_bswap64(value);
+#elif defined(_MSC_VER) && !defined(_DEBUG)
+  return _byteswap_uint64(value);
+#else
+  uint64_t Hi = SwapByteOrder_32(uint32_t(value));
+  uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32));
+  return (Hi << 32) | Lo;
+#endif
+}
+
+inline unsigned char  getSwappedBytes(unsigned char C) { return C; }
+inline   signed char  getSwappedBytes(signed char C) { return C; }
+inline          char  getSwappedBytes(char C) { return C; }
+
+inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); }
+inline   signed short getSwappedBytes(  signed short C) { return SwapByteOrder_16(C); }
+
+inline unsigned int   getSwappedBytes(unsigned int   C) { return SwapByteOrder_32(C); }
+inline   signed int   getSwappedBytes(  signed int   C) { return SwapByteOrder_32(C); }
+
+#if __LONG_MAX__ == __INT_MAX__
+inline unsigned long  getSwappedBytes(unsigned long  C) { return SwapByteOrder_32(C); }
+inline   signed long  getSwappedBytes(  signed long  C) { return SwapByteOrder_32(C); }
+#elif __LONG_MAX__ == __LONG_LONG_MAX__
+inline unsigned long  getSwappedBytes(unsigned long  C) { return SwapByteOrder_64(C); }
+inline   signed long  getSwappedBytes(  signed long  C) { return SwapByteOrder_64(C); }
+#else
+#error "Unknown long size!"
+#endif
+
+inline unsigned long long getSwappedBytes(unsigned long long C) {
+  return SwapByteOrder_64(C);
+}
+inline signed long long getSwappedBytes(signed long long C) {
+  return SwapByteOrder_64(C);
+}
+
+inline float getSwappedBytes(float C) {
+  union {
+    uint32_t i;
+    float f;
+  } in, out;
+  in.f = C;
+  out.i = SwapByteOrder_32(in.i);
+  return out.f;
+}
+
+inline double getSwappedBytes(double C) {
+  union {
+    uint64_t i;
+    double d;
+  } in, out;
+  in.d = C;
+  out.i = SwapByteOrder_64(in.i);
+  return out.d;
+}
+
+template<typename T>
+inline void swapByteOrder(T &Value) {
+  Value = getSwappedBytes(Value);
+}
+
+} // end namespace sys
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/TargetParser.h b/third_party/llvm-subzero/include/llvm/Support/TargetParser.h
new file mode 100644
index 0000000..92b20ea
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/TargetParser.h
@@ -0,0 +1,208 @@
+//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise hardware features such as
+// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TARGETPARSER_H
+#define LLVM_SUPPORT_TARGETPARSER_H
+
+// FIXME: vector is used because that's what clang uses for subtarget feature
+// lists, but SmallVector would probably be better
+#include <vector>
+
+namespace llvm {
+class StringRef;
+
+// Target specific information into their own namespaces. These should be
+// generated from TableGen because the information is already there, and there
+// is where new information about targets will be added.
+// FIXME: To TableGen this we need to make some table generated files available
+// even if the back-end is not compiled with LLVM, plus we need to create a new
+// back-end to TableGen to create these clean tables.
+namespace ARM {
+
+// FPU names.
+enum FPUKind {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND,
+#include "ARMTargetParser.def"
+  FK_LAST
+};
+
+// FPU Version
+enum FPUVersion {
+  FV_NONE = 0,
+  FV_VFPV2,
+  FV_VFPV3,
+  FV_VFPV3_FP16,
+  FV_VFPV4,
+  FV_VFPV5
+};
+
+// An FPU name implies one of three levels of Neon support:
+enum NeonSupportLevel {
+  NS_None = 0, ///< No Neon
+  NS_Neon,     ///< Neon
+  NS_Crypto    ///< Neon with Crypto
+};
+
+// An FPU name restricts the FPU in one of three ways:
+enum FPURestriction {
+  FR_None = 0, ///< No restriction
+  FR_D16,      ///< Only 16 D registers
+  FR_SP_D16    ///< Only single-precision instructions, with 16 D registers
+};
+
+// Arch names.
+enum ArchKind {
+#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
+#include "ARMTargetParser.def"
+  AK_LAST
+};
+
+// Arch extension modifiers for CPUs.
+enum ArchExtKind : unsigned {
+  AEK_INVALID = 0x0,
+  AEK_NONE = 0x1,
+  AEK_CRC = 0x2,
+  AEK_CRYPTO = 0x4,
+  AEK_FP = 0x8,
+  AEK_HWDIV = 0x10,
+  AEK_HWDIVARM = 0x20,
+  AEK_MP = 0x40,
+  AEK_SIMD = 0x80,
+  AEK_SEC = 0x100,
+  AEK_VIRT = 0x200,
+  AEK_DSP = 0x400,
+  AEK_FP16 = 0x800,
+  AEK_RAS = 0x1000,
+  // Unsupported extensions.
+  AEK_OS = 0x8000000,
+  AEK_IWMMXT = 0x10000000,
+  AEK_IWMMXT2 = 0x20000000,
+  AEK_MAVERICK = 0x40000000,
+  AEK_XSCALE = 0x80000000,
+};
+
+// ISA kinds.
+enum ISAKind { IK_INVALID = 0, IK_ARM, IK_THUMB, IK_AARCH64 };
+
+// Endianness
+// FIXME: BE8 vs. BE32?
+enum EndianKind { EK_INVALID = 0, EK_LITTLE, EK_BIG };
+
+// v6/v7/v8 Profile
+enum ProfileKind { PK_INVALID = 0, PK_A, PK_R, PK_M };
+
+StringRef getCanonicalArchName(StringRef Arch);
+
+// Information by ID
+StringRef getFPUName(unsigned FPUKind);
+unsigned getFPUVersion(unsigned FPUKind);
+unsigned getFPUNeonSupportLevel(unsigned FPUKind);
+unsigned getFPURestriction(unsigned FPUKind);
+
+// FIXME: These should be moved to TargetTuple once it exists
+bool getFPUFeatures(unsigned FPUKind, std::vector<const char *> &Features);
+bool getHWDivFeatures(unsigned HWDivKind, std::vector<const char *> &Features);
+bool getExtensionFeatures(unsigned Extensions,
+                                   std::vector<const char*> &Features);
+
+StringRef getArchName(unsigned ArchKind);
+unsigned getArchAttr(unsigned ArchKind);
+StringRef getCPUAttr(unsigned ArchKind);
+StringRef getSubArch(unsigned ArchKind);
+StringRef getArchExtName(unsigned ArchExtKind);
+const char *getArchExtFeature(StringRef ArchExt);
+StringRef getHWDivName(unsigned HWDivKind);
+
+// Information by Name
+unsigned  getDefaultFPU(StringRef CPU, unsigned ArchKind);
+unsigned  getDefaultExtensions(StringRef CPU, unsigned ArchKind);
+StringRef getDefaultCPU(StringRef Arch);
+
+// Parser
+unsigned parseHWDiv(StringRef HWDiv);
+unsigned parseFPU(StringRef FPU);
+unsigned parseArch(StringRef Arch);
+unsigned parseArchExt(StringRef ArchExt);
+unsigned parseCPUArch(StringRef CPU);
+unsigned parseArchISA(StringRef Arch);
+unsigned parseArchEndian(StringRef Arch);
+unsigned parseArchProfile(StringRef Arch);
+unsigned parseArchVersion(StringRef Arch);
+
+} // namespace ARM
+
+// FIXME:This should be made into class design,to avoid dupplication. 
+namespace AArch64 {
+
+// Arch names.
+enum class ArchKind {
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
+#include "AArch64TargetParser.def"
+  AK_LAST
+};
+
+// Arch extension modifiers for CPUs.
+enum ArchExtKind : unsigned {
+  AEK_INVALID = 0x0,
+  AEK_NONE = 0x1,
+  AEK_CRC = 0x2,
+  AEK_CRYPTO = 0x4,
+  AEK_FP = 0x8,
+  AEK_SIMD = 0x10,
+  AEK_FP16 = 0x20,
+  AEK_PROFILE = 0x40,
+  AEK_RAS = 0x80
+};
+
+StringRef getCanonicalArchName(StringRef Arch);
+
+// Information by ID
+StringRef getFPUName(unsigned FPUKind);
+unsigned getFPUVersion(unsigned FPUKind);
+unsigned getFPUNeonSupportLevel(unsigned FPUKind);
+unsigned getFPURestriction(unsigned FPUKind);
+
+// FIXME: These should be moved to TargetTuple once it exists
+bool getFPUFeatures(unsigned FPUKind, std::vector<const char *> &Features);
+bool getExtensionFeatures(unsigned Extensions,
+                                   std::vector<const char*> &Features);
+bool getArchFeatures(unsigned ArchKind, std::vector<const char *> &Features);
+
+StringRef getArchName(unsigned ArchKind);
+unsigned getArchAttr(unsigned ArchKind);
+StringRef getCPUAttr(unsigned ArchKind);
+StringRef getSubArch(unsigned ArchKind);
+StringRef getArchExtName(unsigned ArchExtKind);
+const char *getArchExtFeature(StringRef ArchExt);
+unsigned checkArchVersion(StringRef Arch);
+
+// Information by Name
+unsigned  getDefaultFPU(StringRef CPU, unsigned ArchKind);
+unsigned  getDefaultExtensions(StringRef CPU, unsigned ArchKind);
+StringRef getDefaultCPU(StringRef Arch);
+
+// Parser
+unsigned parseFPU(StringRef FPU);
+unsigned parseArch(StringRef Arch);
+unsigned parseArchExt(StringRef ArchExt);
+unsigned parseCPUArch(StringRef CPU);
+unsigned parseArchISA(StringRef Arch);
+unsigned parseArchEndian(StringRef Arch);
+unsigned parseArchProfile(StringRef Arch);
+unsigned parseArchVersion(StringRef Arch);
+
+} // namespace AArch64
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Threading.h b/third_party/llvm-subzero/include/llvm/Support/Threading.h
new file mode 100644
index 0000000..09b96df
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Threading.h
@@ -0,0 +1,120 @@
+//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares helper functions for running LLVM in a multi-threaded
+// environment.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_THREADING_H
+#define LLVM_SUPPORT_THREADING_H
+
+#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
+#include "llvm/Support/Compiler.h"
+#include <ciso646> // So we can check the C++ standard lib macros.
+#include <functional>
+
+// We use std::call_once on all Unix platforms except for NetBSD with
+// libstdc++. That platform has a bug they are working to fix, and they'll
+// remove the NetBSD checks once fixed.
+#if defined(LLVM_ON_UNIX) &&                                                   \
+    !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__ppc__)
+#define LLVM_THREADING_USE_STD_CALL_ONCE 1
+#else
+#define LLVM_THREADING_USE_STD_CALL_ONCE 0
+#endif
+
+#if LLVM_THREADING_USE_STD_CALL_ONCE
+#include <mutex>
+#else
+#include "llvm/Support/Atomic.h"
+#endif
+
+namespace llvm {
+  /// Returns true if LLVM is compiled with support for multi-threading, and
+  /// false otherwise.
+  bool llvm_is_multithreaded();
+
+  /// llvm_execute_on_thread - Execute the given \p UserFn on a separate
+  /// thread, passing it the provided \p UserData and waits for thread
+  /// completion.
+  ///
+  /// This function does not guarantee that the code will actually be executed
+  /// on a separate thread or honoring the requested stack size, but tries to do
+  /// so where system support is available.
+  ///
+  /// \param UserFn - The callback to execute.
+  /// \param UserData - An argument to pass to the callback function.
+  /// \param RequestedStackSize - If non-zero, a requested size (in bytes) for
+  /// the thread stack.
+  void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData,
+                              unsigned RequestedStackSize = 0);
+
+#if LLVM_THREADING_USE_STD_CALL_ONCE
+
+  typedef std::once_flag once_flag;
+
+  /// This macro is the only way you should define your once flag for LLVM's
+  /// call_once.
+#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag
+
+#else
+
+  enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 };
+  typedef volatile sys::cas_flag once_flag;
+
+  /// This macro is the only way you should define your once flag for LLVM's
+  /// call_once.
+#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag = Uninitialized
+
+#endif
+
+  /// \brief Execute the function specified as a parameter once.
+  ///
+  /// Typical usage:
+  /// \code
+  ///   void foo() {...};
+  ///   ...
+  ///   LLVM_DEFINE_ONCE_FLAG(flag);
+  ///   call_once(flag, foo);
+  /// \endcode
+  ///
+  /// \param flag Flag used for tracking whether or not this has run.
+  /// \param F Function to call once.
+  template <typename Function, typename... Args>
+  void call_once(once_flag &flag, Function &&F, Args &&... ArgList) {
+#if LLVM_THREADING_USE_STD_CALL_ONCE
+    std::call_once(flag, std::forward<Function>(F),
+                   std::forward<Args>(ArgList)...);
+#else
+    // For other platforms we use a generic (if brittle) version based on our
+    // atomics.
+    sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized);
+    if (old_val == Uninitialized) {
+      std::forward<Function>(F)(std::forward<Args>(ArgList)...);
+      sys::MemoryFence();
+      TsanIgnoreWritesBegin();
+      TsanHappensBefore(&flag);
+      flag = Done;
+      TsanIgnoreWritesEnd();
+    } else {
+      // Wait until any thread doing the call has finished.
+      sys::cas_flag tmp = flag;
+      sys::MemoryFence();
+      while (tmp != Done) {
+        tmp = flag;
+        sys::MemoryFence();
+      }
+    }
+    TsanHappensAfter(&flag);
+#endif
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/TimeValue.h b/third_party/llvm-subzero/include/llvm/Support/TimeValue.h
new file mode 100644
index 0000000..6bca58b
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/TimeValue.h
@@ -0,0 +1,386 @@
+//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This header file declares the operating system TimeValue concept.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TIMEVALUE_H
+#define LLVM_SUPPORT_TIMEVALUE_H
+
+#include "llvm/Support/DataTypes.h"
+#include <string>
+
+namespace llvm {
+namespace sys {
+  /// This class is used where a precise fixed point in time is required. The
+  /// range of TimeValue spans many hundreds of billions of years both past and
+  /// present.  The precision of TimeValue is to the nanosecond. However, the
+  /// actual precision of its values will be determined by the resolution of
+  /// the system clock. The TimeValue class is used in conjunction with several
+  /// other lib/System interfaces to specify the time at which a call should
+  /// timeout, etc.
+  /// @since 1.4
+  /// @brief Provides an abstraction for a fixed point in time.
+  class TimeValue {
+
+  /// @name Constants
+  /// @{
+  public:
+
+    /// A constant TimeValue representing the smallest time
+    /// value permissible by the class. MinTime is some point
+    /// in the distant past, about 300 billion years BCE.
+    /// @brief The smallest possible time value.
+    static TimeValue MinTime() {
+      return TimeValue ( INT64_MIN,0 );
+    }
+
+    /// A constant TimeValue representing the largest time
+    /// value permissible by the class. MaxTime is some point
+    /// in the distant future, about 300 billion years AD.
+    /// @brief The largest possible time value.
+    static TimeValue MaxTime() {
+      return TimeValue ( INT64_MAX,0 );
+    }
+
+    /// A constant TimeValue representing the base time,
+    /// or zero time of 00:00:00 (midnight) January 1st, 2000.
+    /// @brief 00:00:00 Jan 1, 2000 UTC.
+    static TimeValue ZeroTime() {
+      return TimeValue ( 0,0 );
+    }
+
+    /// A constant TimeValue for the Posix base time which is
+    /// 00:00:00 (midnight) January 1st, 1970.
+    /// @brief 00:00:00 Jan 1, 1970 UTC.
+    static TimeValue PosixZeroTime() {
+      return TimeValue ( PosixZeroTimeSeconds,0 );
+    }
+
+    /// A constant TimeValue for the Win32 base time which is
+    /// 00:00:00 (midnight) January 1st, 1601.
+    /// @brief 00:00:00 Jan 1, 1601 UTC.
+    static TimeValue Win32ZeroTime() {
+      return TimeValue ( Win32ZeroTimeSeconds,0 );
+    }
+
+  /// @}
+  /// @name Types
+  /// @{
+  public:
+    typedef int64_t SecondsType;    ///< Type used for representing seconds.
+    typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds.
+
+    enum TimeConversions {
+      NANOSECONDS_PER_SECOND = 1000000000,  ///< One Billion
+      MICROSECONDS_PER_SECOND = 1000000,    ///< One Million
+      MILLISECONDS_PER_SECOND = 1000,       ///< One Thousand
+      NANOSECONDS_PER_MICROSECOND = 1000,   ///< One Thousand
+      NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million
+      NANOSECONDS_PER_WIN32_TICK = 100      ///< Win32 tick is 10^7 Hz (10ns)
+    };
+
+  /// @}
+  /// @name Constructors
+  /// @{
+  public:
+    /// \brief Default construct a time value, initializing to ZeroTime.
+    TimeValue() : seconds_(0), nanos_(0) {}
+
+    /// Caller provides the exact value in seconds and nanoseconds. The
+    /// \p nanos argument defaults to zero for convenience.
+    /// @brief Explicit constructor
+    explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0)
+      : seconds_( seconds ), nanos_( nanos ) { this->normalize(); }
+
+    /// Caller provides the exact value as a double in seconds with the
+    /// fractional part representing nanoseconds.
+    /// @brief Double Constructor.
+    explicit TimeValue( double new_time )
+      : seconds_( 0 ) , nanos_ ( 0 ) {
+      SecondsType integer_part = static_cast<SecondsType>( new_time );
+      seconds_ = integer_part;
+      nanos_ = static_cast<NanoSecondsType>( (new_time -
+               static_cast<double>(integer_part)) * NANOSECONDS_PER_SECOND );
+      this->normalize();
+    }
+
+    /// This is a static constructor that returns a TimeValue that represents
+    /// the current time.
+    /// @brief Creates a TimeValue with the current time (UTC).
+    static TimeValue now();
+
+  /// @}
+  /// @name Operators
+  /// @{
+  public:
+    /// Add \p that to \p this.
+    /// @returns this
+    /// @brief Incrementing assignment operator.
+    TimeValue& operator += (const TimeValue& that ) {
+      this->seconds_ += that.seconds_  ;
+      this->nanos_ += that.nanos_ ;
+      this->normalize();
+      return *this;
+    }
+
+    /// Subtract \p that from \p this.
+    /// @returns this
+    /// @brief Decrementing assignment operator.
+    TimeValue& operator -= (const TimeValue &that ) {
+      this->seconds_ -= that.seconds_ ;
+      this->nanos_ -= that.nanos_ ;
+      this->normalize();
+      return *this;
+    }
+
+    /// Determine if \p this is less than \p that.
+    /// @returns True iff *this < that.
+    /// @brief True if this < that.
+    int operator < (const TimeValue &that) const { return that > *this; }
+
+    /// Determine if \p this is greather than \p that.
+    /// @returns True iff *this > that.
+    /// @brief True if this > that.
+    int operator > (const TimeValue &that) const {
+      if ( this->seconds_ > that.seconds_ ) {
+          return 1;
+      } else if ( this->seconds_ == that.seconds_ ) {
+          if ( this->nanos_ > that.nanos_ ) return 1;
+      }
+      return 0;
+    }
+
+    /// Determine if \p this is less than or equal to \p that.
+    /// @returns True iff *this <= that.
+    /// @brief True if this <= that.
+    int operator <= (const TimeValue &that) const { return that >= *this; }
+
+    /// Determine if \p this is greater than or equal to \p that.
+    /// @returns True iff *this >= that.
+    int operator >= (const TimeValue &that) const {
+      if ( this->seconds_ > that.seconds_ ) {
+          return 1;
+      } else if ( this->seconds_ == that.seconds_ ) {
+          if ( this->nanos_ >= that.nanos_ ) return 1;
+      }
+      return 0;
+    }
+
+    /// Determines if two TimeValue objects represent the same moment in time.
+    /// @returns True iff *this == that.
+    int operator == (const TimeValue &that) const {
+      return (this->seconds_ == that.seconds_) &&
+             (this->nanos_ == that.nanos_);
+    }
+
+    /// Determines if two TimeValue objects represent times that are not the
+    /// same.
+    /// @returns True iff *this != that.
+    int operator != (const TimeValue &that) const { return !(*this == that); }
+
+    /// Adds two TimeValue objects together.
+    /// @returns The sum of the two operands as a new TimeValue
+    /// @brief Addition operator.
+    friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2);
+
+    /// Subtracts two TimeValue objects.
+    /// @returns The difference of the two operands as a new TimeValue
+    /// @brief Subtraction operator.
+    friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2);
+
+  /// @}
+  /// @name Accessors
+  /// @{
+  public:
+
+    /// Returns only the seconds component of the TimeValue. The nanoseconds
+    /// portion is ignored. No rounding is performed.
+    /// @brief Retrieve the seconds component
+    SecondsType seconds() const { return seconds_; }
+
+    /// Returns only the nanoseconds component of the TimeValue. The seconds
+    /// portion is ignored.
+    /// @brief Retrieve the nanoseconds component.
+    NanoSecondsType nanoseconds() const { return nanos_; }
+
+    /// Returns only the fractional portion of the TimeValue rounded down to the
+    /// nearest microsecond (divide by one thousand).
+    /// @brief Retrieve the fractional part as microseconds;
+    uint32_t microseconds() const {
+      return nanos_ / NANOSECONDS_PER_MICROSECOND;
+    }
+
+    /// Returns only the fractional portion of the TimeValue rounded down to the
+    /// nearest millisecond (divide by one million).
+    /// @brief Retrieve the fractional part as milliseconds;
+    uint32_t milliseconds() const {
+      return nanos_ / NANOSECONDS_PER_MILLISECOND;
+    }
+
+    /// Returns the TimeValue as a number of microseconds. Note that the value
+    /// returned can overflow because the range of a uint64_t is smaller than
+    /// the range of a TimeValue. Nevertheless, this is useful on some operating
+    /// systems and is therefore provided.
+    /// @brief Convert to a number of microseconds (can overflow)
+    uint64_t usec() const {
+      return seconds_ * MICROSECONDS_PER_SECOND +
+             ( nanos_ / NANOSECONDS_PER_MICROSECOND );
+    }
+
+    /// Returns the TimeValue as a number of milliseconds. Note that the value
+    /// returned can overflow because the range of a uint64_t is smaller than
+    /// the range of a TimeValue. Nevertheless, this is useful on some operating
+    /// systems and is therefore provided.
+    /// @brief Convert to a number of milliseconds (can overflow)
+    uint64_t msec() const {
+      return seconds_ * MILLISECONDS_PER_SECOND +
+             ( nanos_ / NANOSECONDS_PER_MILLISECOND );
+    }
+
+    /// Converts the TimeValue into the corresponding number of seconds
+    /// since the epoch (00:00:00 Jan 1,1970).
+    uint64_t toEpochTime() const {
+      return seconds_ - PosixZeroTimeSeconds;
+    }
+
+    /// Converts the TimeValue into the corresponding number of "ticks" for
+    /// Win32 platforms, correcting for the difference in Win32 zero time.
+    /// @brief Convert to Win32's FILETIME
+    /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC)
+    uint64_t toWin32Time() const {
+      uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds);
+      result += nanos_ / NANOSECONDS_PER_WIN32_TICK;
+      return result;
+    }
+
+    /// Provides the seconds and nanoseconds as results in its arguments after
+    /// correction for the Posix zero time.
+    /// @brief Convert to timespec time (ala POSIX.1b)
+    void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const {
+      seconds = seconds_ - PosixZeroTimeSeconds;
+      nanos = nanos_;
+    }
+
+    /// Provides conversion of the TimeValue into a readable time & date.
+    /// @returns std::string containing the readable time value
+    /// @brief Convert time to a string.
+    std::string str() const;
+
+  /// @}
+  /// @name Mutators
+  /// @{
+  public:
+    /// The seconds component of the TimeValue is set to \p sec without
+    /// modifying the nanoseconds part.  This is useful for whole second
+    /// arithmetic.
+    /// @brief Set the seconds component.
+    void seconds (SecondsType sec ) {
+      this->seconds_ = sec;
+      this->normalize();
+    }
+
+    /// The nanoseconds component of the TimeValue is set to \p nanos without
+    /// modifying the seconds part. This is useful for basic computations
+    /// involving just the nanoseconds portion. Note that the TimeValue will be
+    /// normalized after this call so that the fractional (nanoseconds) portion
+    /// will have the smallest equivalent value.
+    /// @brief Set the nanoseconds component using a number of nanoseconds.
+    void nanoseconds ( NanoSecondsType nanos ) {
+      this->nanos_ = nanos;
+      this->normalize();
+    }
+
+    /// The seconds component remains unchanged.
+    /// @brief Set the nanoseconds component using a number of microseconds.
+    void microseconds ( int32_t micros ) {
+      this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND;
+      this->normalize();
+    }
+
+    /// The seconds component remains unchanged.
+    /// @brief Set the nanoseconds component using a number of milliseconds.
+    void milliseconds ( int32_t millis ) {
+      this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND;
+      this->normalize();
+    }
+
+    /// @brief Converts from microsecond format to TimeValue format
+    void usec( int64_t microseconds ) {
+      this->seconds_ = microseconds / MICROSECONDS_PER_SECOND;
+      this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) *
+        NANOSECONDS_PER_MICROSECOND;
+      this->normalize();
+    }
+
+    /// @brief Converts from millisecond format to TimeValue format
+    void msec( int64_t milliseconds ) {
+      this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND;
+      this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) *
+        NANOSECONDS_PER_MILLISECOND;
+      this->normalize();
+    }
+
+    /// Converts the \p seconds argument from PosixTime to the corresponding
+    /// TimeValue and assigns that value to \p this.
+    /// @brief Convert seconds form PosixTime to TimeValue
+    void fromEpochTime( SecondsType seconds ) {
+      seconds_ = seconds + PosixZeroTimeSeconds;
+      nanos_ = 0;
+      this->normalize();
+    }
+
+    /// Converts the \p win32Time argument from Windows FILETIME to the
+    /// corresponding TimeValue and assigns that value to \p this.
+    /// @brief Convert seconds form Windows FILETIME to TimeValue
+    void fromWin32Time( uint64_t win32Time ) {
+      this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds;
+      this->nanos_ = NanoSecondsType(win32Time  % 10000000) * 100;
+    }
+
+  /// @}
+  /// @name Implementation
+  /// @{
+  private:
+    /// This causes the values to be represented so that the fractional
+    /// part is minimized, possibly incrementing the seconds part.
+    /// @brief Normalize to canonical form.
+    void normalize();
+
+  /// @}
+  /// @name Data
+  /// @{
+  private:
+    /// Store the values as a <timeval>.
+    SecondsType      seconds_;///< Stores the seconds part of the TimeVal
+    NanoSecondsType  nanos_;  ///< Stores the nanoseconds part of the TimeVal
+
+    static const SecondsType PosixZeroTimeSeconds;
+    static const SecondsType Win32ZeroTimeSeconds;
+  /// @}
+
+  };
+
+inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) {
+  TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_);
+  sum.normalize ();
+  return sum;
+}
+
+inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) {
+  TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ );
+  difference.normalize ();
+  return difference;
+}
+
+}
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Timer.h b/third_party/llvm-subzero/include/llvm/Support/Timer.h
new file mode 100644
index 0000000..f0cb075
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Timer.h
@@ -0,0 +1,199 @@
+//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TIMER_H
+#define LLVM_SUPPORT_TIMER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class Timer;
+class TimerGroup;
+class raw_ostream;
+
+class TimeRecord {
+  double WallTime;       // Wall clock time elapsed in seconds
+  double UserTime;       // User time elapsed
+  double SystemTime;     // System time elapsed
+  ssize_t MemUsed;       // Memory allocated (in bytes)
+public:
+  TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
+
+  /// getCurrentTime - Get the current time and memory usage.  If Start is true
+  /// we get the memory usage before the time, otherwise we get time before
+  /// memory usage.  This matters if the time to get the memory usage is
+  /// significant and shouldn't be counted as part of a duration.
+  static TimeRecord getCurrentTime(bool Start = true);
+
+  double getProcessTime() const { return UserTime + SystemTime; }
+  double getUserTime() const { return UserTime; }
+  double getSystemTime() const { return SystemTime; }
+  double getWallTime() const { return WallTime; }
+  ssize_t getMemUsed() const { return MemUsed; }
+
+  // operator< - Allow sorting.
+  bool operator<(const TimeRecord &T) const {
+    // Sort by Wall Time elapsed, as it is the only thing really accurate
+    return WallTime < T.WallTime;
+  }
+
+  void operator+=(const TimeRecord &RHS) {
+    WallTime   += RHS.WallTime;
+    UserTime   += RHS.UserTime;
+    SystemTime += RHS.SystemTime;
+    MemUsed    += RHS.MemUsed;
+  }
+  void operator-=(const TimeRecord &RHS) {
+    WallTime   -= RHS.WallTime;
+    UserTime   -= RHS.UserTime;
+    SystemTime -= RHS.SystemTime;
+    MemUsed    -= RHS.MemUsed;
+  }
+
+  /// Print the current time record to \p OS, with a breakdown showing
+  /// contributions to the \p Total time record.
+  void print(const TimeRecord &Total, raw_ostream &OS) const;
+};
+
+/// Timer - This class is used to track the amount of time spent between
+/// invocations of its startTimer()/stopTimer() methods.  Given appropriate OS
+/// support it can also keep track of the RSS of the program at various points.
+/// By default, the Timer will print the amount of time it has captured to
+/// standard error when the last timer is destroyed, otherwise it is printed
+/// when its TimerGroup is destroyed.  Timers do not print their information
+/// if they are never started.
+///
+class Timer {
+  TimeRecord Time;       // The total time captured
+  TimeRecord StartTime;  // The time startTimer() was last called
+  std::string Name;      // The name of this time variable.
+  bool Running;          // Is the timer currently running?
+  bool Triggered;        // Has the timer ever been triggered?
+  TimerGroup *TG;        // The TimerGroup this Timer is in.
+
+  Timer **Prev, *Next;   // Doubly linked list of timers in the group.
+public:
+  explicit Timer(StringRef N) : TG(nullptr) { init(N); }
+  Timer(StringRef N, TimerGroup &tg) : TG(nullptr) { init(N, tg); }
+  Timer(const Timer &RHS) : TG(nullptr) {
+    assert(!RHS.TG && "Can only copy uninitialized timers");
+  }
+  const Timer &operator=(const Timer &T) {
+    assert(!TG && !T.TG && "Can only assign uninit timers");
+    return *this;
+  }
+  ~Timer();
+
+  // Create an uninitialized timer, client must use 'init'.
+  explicit Timer() : TG(nullptr) {}
+  void init(StringRef N);
+  void init(StringRef N, TimerGroup &tg);
+
+  const std::string &getName() const { return Name; }
+  bool isInitialized() const { return TG != nullptr; }
+
+  /// Check if the timer is currently running.
+  bool isRunning() const { return Running; }
+
+  /// Check if startTimer() has ever been called on this timer.
+  bool hasTriggered() const { return Triggered; }
+
+  /// Start the timer running.  Time between calls to startTimer/stopTimer is
+  /// counted by the Timer class.  Note that these calls must be correctly
+  /// paired.
+  void startTimer();
+
+  /// Stop the timer.
+  void stopTimer();
+
+  /// Clear the timer state.
+  void clear();
+
+  /// Return the duration for which this timer has been running.
+  TimeRecord getTotalTime() const { return Time; }
+
+private:
+  friend class TimerGroup;
+};
+
+/// The TimeRegion class is used as a helper class to call the startTimer() and
+/// stopTimer() methods of the Timer class.  When the object is constructed, it
+/// starts the timer specified as its argument.  When it is destroyed, it stops
+/// the relevant timer.  This makes it easy to time a region of code.
+///
+class TimeRegion {
+  Timer *T;
+  TimeRegion(const TimeRegion &) = delete;
+
+public:
+  explicit TimeRegion(Timer &t) : T(&t) {
+    T->startTimer();
+  }
+  explicit TimeRegion(Timer *t) : T(t) {
+    if (T) T->startTimer();
+  }
+  ~TimeRegion() {
+    if (T) T->stopTimer();
+  }
+};
+
+/// NamedRegionTimer - This class is basically a combination of TimeRegion and
+/// Timer.  It allows you to declare a new timer, AND specify the region to
+/// time, all in one statement.  All timers with the same name are merged.  This
+/// is primarily used for debugging and for hunting performance problems.
+///
+struct NamedRegionTimer : public TimeRegion {
+  explicit NamedRegionTimer(StringRef Name,
+                            bool Enabled = true);
+  explicit NamedRegionTimer(StringRef Name, StringRef GroupName,
+                            bool Enabled = true);
+};
+
+/// The TimerGroup class is used to group together related timers into a single
+/// report that is printed when the TimerGroup is destroyed.  It is illegal to
+/// destroy a TimerGroup object before all of the Timers in it are gone.  A
+/// TimerGroup can be specified for a newly created timer in its constructor.
+///
+class TimerGroup {
+  std::string Name;
+  Timer *FirstTimer;   // First timer in the group.
+  std::vector<std::pair<TimeRecord, std::string>> TimersToPrint;
+
+  TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
+  TimerGroup(const TimerGroup &TG) = delete;
+  void operator=(const TimerGroup &TG) = delete;
+
+public:
+  explicit TimerGroup(StringRef name);
+  ~TimerGroup();
+
+  void setName(StringRef name) { Name.assign(name.begin(), name.end()); }
+
+  /// print - Print any started timers in this group and zero them.
+  void print(raw_ostream &OS);
+
+  /// printAll - This static method prints all timers and clears them all out.
+  static void printAll(raw_ostream &OS);
+
+private:
+  friend class Timer;
+  void addTimer(Timer &T);
+  void removeTimer(Timer &T);
+  void PrintQueuedTimers(raw_ostream &OS);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Valgrind.h b/third_party/llvm-subzero/include/llvm/Support/Valgrind.h
new file mode 100644
index 0000000..084b901
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/Valgrind.h
@@ -0,0 +1,32 @@
+//===- llvm/Support/Valgrind.h - Communication with Valgrind ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Methods for communicating with a valgrind instance this program is running
+// under.  These are all no-ops unless LLVM was configured on a system with the
+// valgrind headers installed and valgrind is controlling this process.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_VALGRIND_H
+#define LLVM_SUPPORT_VALGRIND_H
+
+#include <cstddef>
+
+namespace llvm {
+namespace sys {
+  // True if Valgrind is controlling this process.
+  bool RunningOnValgrind();
+
+  // Discard valgrind's translation of code in the range [Addr .. Addr + Len).
+  // Otherwise valgrind may continue to execute the old version of the code.
+  void ValgrindDiscardTranslations(const void *Addr, size_t Len);
+} // namespace sys
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_VALGRIND_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/WindowsError.h b/third_party/llvm-subzero/include/llvm/Support/WindowsError.h
new file mode 100644
index 0000000..63bfe59
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/WindowsError.h
@@ -0,0 +1,19 @@
+//===-- WindowsError.h - Support for mapping windows errors to posix-------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WINDOWSERROR_H
+#define LLVM_SUPPORT_WINDOWSERROR_H
+
+#include <system_error>
+
+namespace llvm {
+std::error_code mapWindowsError(unsigned EV);
+}
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/circular_raw_ostream.h b/third_party/llvm-subzero/include/llvm/Support/circular_raw_ostream.h
new file mode 100644
index 0000000..b46fd7f
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/circular_raw_ostream.h
@@ -0,0 +1,156 @@
+//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains raw_ostream implementations for streams to do circular
+// buffering of their output.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
+#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+  /// circular_raw_ostream - A raw_ostream which *can* save its data
+  /// to a circular buffer, or can pass it through directly to an
+  /// underlying stream if specified with a buffer of zero.
+  ///
+  class circular_raw_ostream : public raw_ostream {
+  public:
+    /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying
+    /// stream and is responsible for cleanup, memory management
+    /// issues, etc.
+    ///
+    static const bool TAKE_OWNERSHIP = true;
+
+    /// REFERENCE_ONLY - Tell this stream it should not manage the
+    /// held stream.
+    ///
+    static const bool REFERENCE_ONLY = false;
+
+  private:
+    /// TheStream - The real stream we output to. We set it to be
+    /// unbuffered, since we're already doing our own buffering.
+    ///
+    raw_ostream *TheStream;
+
+    /// OwnsStream - Are we responsible for managing the underlying
+    /// stream?
+    ///
+    bool OwnsStream;
+
+    /// BufferSize - The size of the buffer in bytes.
+    ///
+    size_t BufferSize;
+
+    /// BufferArray - The actual buffer storage.
+    ///
+    char *BufferArray;
+
+    /// Cur - Pointer to the current output point in BufferArray.
+    ///
+    char *Cur;
+
+    /// Filled - Indicate whether the buffer has been completely
+    /// filled.  This helps avoid garbage output.
+    ///
+    bool Filled;
+
+    /// Banner - A pointer to a banner to print before dumping the
+    /// log.
+    ///
+    const char *Banner;
+
+    /// flushBuffer - Dump the contents of the buffer to Stream.
+    ///
+    void flushBuffer() {
+      if (Filled)
+        // Write the older portion of the buffer.
+        TheStream->write(Cur, BufferArray + BufferSize - Cur);
+      // Write the newer portion of the buffer.
+      TheStream->write(BufferArray, Cur - BufferArray);
+      Cur = BufferArray;
+      Filled = false;
+    }
+
+    void write_impl(const char *Ptr, size_t Size) override;
+
+    /// current_pos - Return the current position within the stream,
+    /// not counting the bytes currently in the buffer.
+    ///
+    uint64_t current_pos() const override {
+      // This has the same effect as calling TheStream.current_pos(),
+      // but that interface is private.
+      return TheStream->tell() - TheStream->GetNumBytesInBuffer();
+    }
+
+  public:
+    /// circular_raw_ostream - Construct an optionally
+    /// circular-buffered stream, handing it an underlying stream to
+    /// do the "real" output.
+    ///
+    /// As a side effect, if BuffSize is nonzero, the given Stream is
+    /// set to be Unbuffered.  This is because circular_raw_ostream
+    /// does its own buffering, so it doesn't want another layer of
+    /// buffering to be happening underneath it.
+    ///
+    /// "Owns" tells the circular_raw_ostream whether it is
+    /// responsible for managing the held stream, doing memory
+    /// management of it, etc.
+    ///
+    circular_raw_ostream(raw_ostream &Stream, const char *Header,
+                         size_t BuffSize = 0, bool Owns = REFERENCE_ONLY)
+        : raw_ostream(/*unbuffered*/ true), TheStream(nullptr),
+          OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr),
+          Filled(false), Banner(Header) {
+      if (BufferSize != 0)
+        BufferArray = new char[BufferSize];
+      Cur = BufferArray;
+      setStream(Stream, Owns);
+    }
+
+    ~circular_raw_ostream() override {
+      flush();
+      flushBufferWithBanner();
+      releaseStream();
+      delete[] BufferArray;
+    }
+
+    /// setStream - Tell the circular_raw_ostream to output a
+    /// different stream.  "Owns" tells circular_raw_ostream whether
+    /// it should take responsibility for managing the underlying
+    /// stream.
+    ///
+    void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) {
+      releaseStream();
+      TheStream = &Stream;
+      OwnsStream = Owns;
+    }
+
+    /// flushBufferWithBanner - Force output of the buffer along with
+    /// a small header.
+    ///
+    void flushBufferWithBanner();
+
+  private:
+    /// releaseStream - Delete the held stream if needed. Otherwise,
+    /// transfer the buffer settings from this circular_raw_ostream
+    /// back to the underlying stream.
+    ///
+    void releaseStream() {
+      if (!TheStream)
+        return;
+      if (OwnsStream)
+        delete TheStream;
+    }
+  };
+} // end llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/raw_os_ostream.h b/third_party/llvm-subzero/include/llvm/Support/raw_os_ostream.h
new file mode 100644
index 0000000..a983aeb
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/raw_os_ostream.h
@@ -0,0 +1,42 @@
+//===- raw_os_ostream.h - std::ostream adaptor for raw_ostream --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the raw_os_ostream class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RAW_OS_OSTREAM_H
+#define LLVM_SUPPORT_RAW_OS_OSTREAM_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <iosfwd>
+
+namespace llvm {
+
+/// raw_os_ostream - A raw_ostream that writes to an std::ostream.  This is a
+/// simple adaptor class.  It does not check for output errors; clients should
+/// use the underlying stream to detect errors.
+class raw_os_ostream : public raw_ostream {
+  std::ostream &OS;
+
+  /// write_impl - See raw_ostream::write_impl.
+  void write_impl(const char *Ptr, size_t Size) override;
+
+  /// current_pos - Return the current position within the stream, not
+  /// counting the bytes currently in the buffer.
+  uint64_t current_pos() const override;
+
+public:
+  raw_os_ostream(std::ostream &O) : OS(O) {}
+  ~raw_os_ostream() override;
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/raw_ostream.h b/third_party/llvm-subzero/include/llvm/Support/raw_ostream.h
new file mode 100644
index 0000000..d1e96f8
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/raw_ostream.h
@@ -0,0 +1,530 @@
+//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the raw_ostream class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RAW_OSTREAM_H
+#define LLVM_SUPPORT_RAW_OSTREAM_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include <system_error>
+
+namespace llvm {
+class format_object_base;
+class FormattedString;
+class FormattedNumber;
+template <typename T> class SmallVectorImpl;
+
+namespace sys {
+namespace fs {
+enum OpenFlags : unsigned;
+}
+}
+
+/// This class implements an extremely fast bulk output stream that can *only*
+/// output to a stream.  It does not support seeking, reopening, rewinding, line
+/// buffered disciplines etc. It is a simple buffer that outputs
+/// a chunk at a time.
+class raw_ostream {
+private:
+  void operator=(const raw_ostream &) = delete;
+  raw_ostream(const raw_ostream &) = delete;
+
+  /// The buffer is handled in such a way that the buffer is
+  /// uninitialized, unbuffered, or out of space when OutBufCur >=
+  /// OutBufEnd. Thus a single comparison suffices to determine if we
+  /// need to take the slow path to write a single character.
+  ///
+  /// The buffer is in one of three states:
+  ///  1. Unbuffered (BufferMode == Unbuffered)
+  ///  1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0).
+  ///  2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 &&
+  ///               OutBufEnd - OutBufStart >= 1).
+  ///
+  /// If buffered, then the raw_ostream owns the buffer if (BufferMode ==
+  /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is
+  /// managed by the subclass.
+  ///
+  /// If a subclass installs an external buffer using SetBuffer then it can wait
+  /// for a \see write_impl() call to handle the data which has been put into
+  /// this buffer.
+  char *OutBufStart, *OutBufEnd, *OutBufCur;
+
+  enum BufferKind {
+    Unbuffered = 0,
+    InternalBuffer,
+    ExternalBuffer
+  } BufferMode;
+
+public:
+  // color order matches ANSI escape sequence, don't change
+  enum Colors {
+    BLACK=0,
+    RED,
+    GREEN,
+    YELLOW,
+    BLUE,
+    MAGENTA,
+    CYAN,
+    WHITE,
+    SAVEDCOLOR
+  };
+
+  explicit raw_ostream(bool unbuffered = false)
+      : BufferMode(unbuffered ? Unbuffered : InternalBuffer) {
+    // Start out ready to flush.
+    OutBufStart = OutBufEnd = OutBufCur = nullptr;
+  }
+
+  virtual ~raw_ostream();
+
+  /// tell - Return the current offset with the file.
+  uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); }
+
+  //===--------------------------------------------------------------------===//
+  // Configuration Interface
+  //===--------------------------------------------------------------------===//
+
+  /// Set the stream to be buffered, with an automatically determined buffer
+  /// size.
+  void SetBuffered();
+
+  /// Set the stream to be buffered, using the specified buffer size.
+  void SetBufferSize(size_t Size) {
+    flush();
+    SetBufferAndMode(new char[Size], Size, InternalBuffer);
+  }
+
+  size_t GetBufferSize() const {
+    // If we're supposed to be buffered but haven't actually gotten around
+    // to allocating the buffer yet, return the value that would be used.
+    if (BufferMode != Unbuffered && OutBufStart == nullptr)
+      return preferred_buffer_size();
+
+    // Otherwise just return the size of the allocated buffer.
+    return OutBufEnd - OutBufStart;
+  }
+
+  /// Set the stream to be unbuffered. When unbuffered, the stream will flush
+  /// after every write. This routine will also flush the buffer immediately
+  /// when the stream is being set to unbuffered.
+  void SetUnbuffered() {
+    flush();
+    SetBufferAndMode(nullptr, 0, Unbuffered);
+  }
+
+  size_t GetNumBytesInBuffer() const {
+    return OutBufCur - OutBufStart;
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Data Output Interface
+  //===--------------------------------------------------------------------===//
+
+  void flush() {
+    if (OutBufCur != OutBufStart)
+      flush_nonempty();
+  }
+
+  raw_ostream &operator<<(char C) {
+    if (OutBufCur >= OutBufEnd)
+      return write(C);
+    *OutBufCur++ = C;
+    return *this;
+  }
+
+  raw_ostream &operator<<(unsigned char C) {
+    if (OutBufCur >= OutBufEnd)
+      return write(C);
+    *OutBufCur++ = C;
+    return *this;
+  }
+
+  raw_ostream &operator<<(signed char C) {
+    if (OutBufCur >= OutBufEnd)
+      return write(C);
+    *OutBufCur++ = C;
+    return *this;
+  }
+
+  raw_ostream &operator<<(StringRef Str) {
+    // Inline fast path, particularly for strings with a known length.
+    size_t Size = Str.size();
+
+    // Make sure we can use the fast path.
+    if (Size > (size_t)(OutBufEnd - OutBufCur))
+      return write(Str.data(), Size);
+
+    if (Size) {
+      memcpy(OutBufCur, Str.data(), Size);
+      OutBufCur += Size;
+    }
+    return *this;
+  }
+
+  raw_ostream &operator<<(const char *Str) {
+    // Inline fast path, particularly for constant strings where a sufficiently
+    // smart compiler will simplify strlen.
+
+    return this->operator<<(StringRef(Str));
+  }
+
+  raw_ostream &operator<<(const std::string &Str) {
+    // Avoid the fast path, it would only increase code size for a marginal win.
+    return write(Str.data(), Str.length());
+  }
+
+  raw_ostream &operator<<(const llvm::SmallVectorImpl<char> &Str) {
+    return write(Str.data(), Str.size());
+  }
+
+  raw_ostream &operator<<(unsigned long N);
+  raw_ostream &operator<<(long N);
+  raw_ostream &operator<<(unsigned long long N);
+  raw_ostream &operator<<(long long N);
+  raw_ostream &operator<<(const void *P);
+  raw_ostream &operator<<(unsigned int N) {
+    return this->operator<<(static_cast<unsigned long>(N));
+  }
+
+  raw_ostream &operator<<(int N) {
+    return this->operator<<(static_cast<long>(N));
+  }
+
+  raw_ostream &operator<<(double N);
+
+  /// Output \p N in hexadecimal, without any prefix or padding.
+  raw_ostream &write_hex(unsigned long long N);
+
+  /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't
+  /// satisfy std::isprint into an escape sequence.
+  raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false);
+
+  raw_ostream &write(unsigned char C);
+  raw_ostream &write(const char *Ptr, size_t Size);
+
+  // Formatted output, see the format() function in Support/Format.h.
+  raw_ostream &operator<<(const format_object_base &Fmt);
+
+  // Formatted output, see the leftJustify() function in Support/Format.h.
+  raw_ostream &operator<<(const FormattedString &);
+
+  // Formatted output, see the formatHex() function in Support/Format.h.
+  raw_ostream &operator<<(const FormattedNumber &);
+
+  /// indent - Insert 'NumSpaces' spaces.
+  raw_ostream &indent(unsigned NumSpaces);
+
+  /// Changes the foreground color of text that will be output from this point
+  /// forward.
+  /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
+  /// change only the bold attribute, and keep colors untouched
+  /// @param Bold bold/brighter text, default false
+  /// @param BG if true change the background, default: change foreground
+  /// @returns itself so it can be used within << invocations
+  virtual raw_ostream &changeColor(enum Colors Color,
+                                   bool Bold = false,
+                                   bool BG = false) {
+    (void)Color;
+    (void)Bold;
+    (void)BG;
+    return *this;
+  }
+
+  /// Resets the colors to terminal defaults. Call this when you are done
+  /// outputting colored text, or before program exit.
+  virtual raw_ostream &resetColor() { return *this; }
+
+  /// Reverses the foreground and background colors.
+  virtual raw_ostream &reverseColor() { return *this; }
+
+  /// This function determines if this stream is connected to a "tty" or
+  /// "console" window. That is, the output would be displayed to the user
+  /// rather than being put on a pipe or stored in a file.
+  virtual bool is_displayed() const { return false; }
+
+  /// This function determines if this stream is displayed and supports colors.
+  virtual bool has_colors() const { return is_displayed(); }
+
+  //===--------------------------------------------------------------------===//
+  // Subclass Interface
+  //===--------------------------------------------------------------------===//
+
+private:
+  /// The is the piece of the class that is implemented by subclasses.  This
+  /// writes the \p Size bytes starting at
+  /// \p Ptr to the underlying stream.
+  ///
+  /// This function is guaranteed to only be called at a point at which it is
+  /// safe for the subclass to install a new buffer via SetBuffer.
+  ///
+  /// \param Ptr The start of the data to be written. For buffered streams this
+  /// is guaranteed to be the start of the buffer.
+  ///
+  /// \param Size The number of bytes to be written.
+  ///
+  /// \invariant { Size > 0 }
+  virtual void write_impl(const char *Ptr, size_t Size) = 0;
+
+  // An out of line virtual method to provide a home for the class vtable.
+  virtual void handle();
+
+  /// Return the current position within the stream, not counting the bytes
+  /// currently in the buffer.
+  virtual uint64_t current_pos() const = 0;
+
+protected:
+  /// Use the provided buffer as the raw_ostream buffer. This is intended for
+  /// use only by subclasses which can arrange for the output to go directly
+  /// into the desired output buffer, instead of being copied on each flush.
+  void SetBuffer(char *BufferStart, size_t Size) {
+    SetBufferAndMode(BufferStart, Size, ExternalBuffer);
+  }
+
+  /// Return an efficient buffer size for the underlying output mechanism.
+  virtual size_t preferred_buffer_size() const;
+
+  /// Return the beginning of the current stream buffer, or 0 if the stream is
+  /// unbuffered.
+  const char *getBufferStart() const { return OutBufStart; }
+
+  //===--------------------------------------------------------------------===//
+  // Private Interface
+  //===--------------------------------------------------------------------===//
+private:
+  /// Install the given buffer and mode.
+  void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode);
+
+  /// Flush the current buffer, which is known to be non-empty. This outputs the
+  /// currently buffered data and resets the buffer to empty.
+  void flush_nonempty();
+
+  /// Copy data into the buffer. Size must not be greater than the number of
+  /// unused bytes in the buffer.
+  void copy_to_buffer(const char *Ptr, size_t Size);
+};
+
+/// An abstract base class for streams implementations that also support a
+/// pwrite operation. This is useful for code that can mostly stream out data,
+/// but needs to patch in a header that needs to know the output size.
+class raw_pwrite_stream : public raw_ostream {
+  virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0;
+
+public:
+  explicit raw_pwrite_stream(bool Unbuffered = false)
+      : raw_ostream(Unbuffered) {}
+  void pwrite(const char *Ptr, size_t Size, uint64_t Offset) {
+#ifndef NDBEBUG
+    uint64_t Pos = tell();
+    // /dev/null always reports a pos of 0, so we cannot perform this check
+    // in that case.
+    if (Pos)
+      assert(Size + Offset <= Pos && "We don't support extending the stream");
+#endif
+    pwrite_impl(Ptr, Size, Offset);
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// File Output Streams
+//===----------------------------------------------------------------------===//
+
+/// A raw_ostream that writes to a file descriptor.
+///
+class raw_fd_ostream : public raw_pwrite_stream {
+  int FD;
+  bool ShouldClose;
+
+  /// Error This flag is true if an error of any kind has been detected.
+  ///
+  bool Error;
+
+  uint64_t pos;
+
+  bool SupportsSeeking;
+
+  /// See raw_ostream::write_impl.
+  void write_impl(const char *Ptr, size_t Size) override;
+
+  void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+  /// Return the current position within the stream, not counting the bytes
+  /// currently in the buffer.
+  uint64_t current_pos() const override { return pos; }
+
+  /// Determine an efficient buffer size.
+  size_t preferred_buffer_size() const override;
+
+  /// Set the flag indicating that an output error has been encountered.
+  void error_detected() { Error = true; }
+
+public:
+  /// Open the specified file for writing. If an error occurs, information
+  /// about the error is put into EC, and the stream should be immediately
+  /// destroyed;
+  /// \p Flags allows optional flags to control how the file will be opened.
+  ///
+  /// As a special case, if Filename is "-", then the stream will use
+  /// STDOUT_FILENO instead of opening a file. Note that it will still consider
+  /// itself to own the file descriptor. In particular, it will close the
+  /// file descriptor when it is done (this is necessary to detect
+  /// output errors).
+  raw_fd_ostream(StringRef Filename, std::error_code &EC,
+                 sys::fs::OpenFlags Flags);
+
+  /// FD is the file descriptor that this writes to.  If ShouldClose is true,
+  /// this closes the file when the stream is destroyed.
+  raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false);
+
+  ~raw_fd_ostream() override;
+
+  /// Manually flush the stream and close the file. Note that this does not call
+  /// fsync.
+  void close();
+
+  bool supportsSeeking() { return SupportsSeeking; }
+
+  /// Flushes the stream and repositions the underlying file descriptor position
+  /// to the offset specified from the beginning of the file.
+  uint64_t seek(uint64_t off);
+
+  raw_ostream &changeColor(enum Colors colors, bool bold=false,
+                           bool bg=false) override;
+  raw_ostream &resetColor() override;
+
+  raw_ostream &reverseColor() override;
+
+  bool is_displayed() const override;
+
+  bool has_colors() const override;
+
+  /// Return the value of the flag in this raw_fd_ostream indicating whether an
+  /// output error has been encountered.
+  /// This doesn't implicitly flush any pending output.  Also, it doesn't
+  /// guarantee to detect all errors unless the stream has been closed.
+  bool has_error() const {
+    return Error;
+  }
+
+  /// Set the flag read by has_error() to false. If the error flag is set at the
+  /// time when this raw_ostream's destructor is called, report_fatal_error is
+  /// called to report the error. Use clear_error() after handling the error to
+  /// avoid this behavior.
+  ///
+  ///   "Errors should never pass silently.
+  ///    Unless explicitly silenced."
+  ///      - from The Zen of Python, by Tim Peters
+  ///
+  void clear_error() {
+    Error = false;
+  }
+};
+
+/// This returns a reference to a raw_ostream for standard output. Use it like:
+/// outs() << "foo" << "bar";
+raw_ostream &outs();
+
+/// This returns a reference to a raw_ostream for standard error. Use it like:
+/// errs() << "foo" << "bar";
+raw_ostream &errs();
+
+/// This returns a reference to a raw_ostream which simply discards output.
+raw_ostream &nulls();
+
+//===----------------------------------------------------------------------===//
+// Output Stream Adaptors
+//===----------------------------------------------------------------------===//
+
+/// A raw_ostream that writes to an std::string.  This is a simple adaptor
+/// class. This class does not encounter output errors.
+class raw_string_ostream : public raw_ostream {
+  std::string &OS;
+
+  /// See raw_ostream::write_impl.
+  void write_impl(const char *Ptr, size_t Size) override;
+
+  /// Return the current position within the stream, not counting the bytes
+  /// currently in the buffer.
+  uint64_t current_pos() const override { return OS.size(); }
+
+public:
+  explicit raw_string_ostream(std::string &O) : OS(O) {}
+  ~raw_string_ostream() override;
+
+  /// Flushes the stream contents to the target string and returns  the string's
+  /// reference.
+  std::string& str() {
+    flush();
+    return OS;
+  }
+};
+
+/// A raw_ostream that writes to an SmallVector or SmallString.  This is a
+/// simple adaptor class. This class does not encounter output errors.
+/// raw_svector_ostream operates without a buffer, delegating all memory
+/// management to the SmallString. Thus the SmallString is always up-to-date,
+/// may be used directly and there is no need to call flush().
+class raw_svector_ostream : public raw_pwrite_stream {
+  SmallVectorImpl<char> &OS;
+
+  /// See raw_ostream::write_impl.
+  void write_impl(const char *Ptr, size_t Size) override;
+
+  void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+  /// Return the current position within the stream.
+  uint64_t current_pos() const override;
+
+public:
+  /// Construct a new raw_svector_ostream.
+  ///
+  /// \param O The vector to write to; this should generally have at least 128
+  /// bytes free to avoid any extraneous memory overhead.
+  explicit raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {
+    SetUnbuffered();
+  }
+  ~raw_svector_ostream() override {}
+
+  void flush() = delete;
+
+  /// Return a StringRef for the vector contents.
+  StringRef str() { return StringRef(OS.data(), OS.size()); }
+};
+
+/// A raw_ostream that discards all output.
+class raw_null_ostream : public raw_pwrite_stream {
+  /// See raw_ostream::write_impl.
+  void write_impl(const char *Ptr, size_t size) override;
+  void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+  /// Return the current position within the stream, not counting the bytes
+  /// currently in the buffer.
+  uint64_t current_pos() const override;
+
+public:
+  explicit raw_null_ostream() {}
+  ~raw_null_ostream() override;
+};
+
+class buffer_ostream : public raw_svector_ostream {
+  raw_ostream &OS;
+  SmallVector<char, 0> Buffer;
+
+public:
+  buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer), OS(OS) {}
+  ~buffer_ostream() override { OS << str(); }
+};
+
+} // end llvm namespace
+
+#endif // LLVM_SUPPORT_RAW_OSTREAM_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/thread.h b/third_party/llvm-subzero/include/llvm/Support/thread.h
new file mode 100644
index 0000000..9c45418
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/thread.h
@@ -0,0 +1,67 @@
+//===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header is a wrapper for <thread> that works around problems with the
+// MSVC headers when exceptions are disabled. It also provides llvm::thread,
+// which is either a typedef of std::thread or a replacement that calls the
+// function synchronously depending on the value of LLVM_ENABLE_THREADS.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_THREAD_H
+#define LLVM_SUPPORT_THREAD_H
+
+#include "llvm/Config/llvm-config.h"
+
+#if LLVM_ENABLE_THREADS
+
+#ifdef _MSC_VER
+// concrt.h depends on eh.h for __uncaught_exception declaration
+// even if we disable exceptions.
+#include <eh.h>
+
+// Suppress 'C++ exception handler used, but unwind semantics are not enabled.'
+#pragma warning(push)
+#pragma warning(disable:4530)
+#endif
+
+#include <thread>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+namespace llvm {
+typedef std::thread thread;
+}
+
+#else // !LLVM_ENABLE_THREADS
+
+#include <utility>
+
+namespace llvm {
+
+struct thread {
+  thread() {}
+  thread(thread &&other) {}
+  template <class Function, class... Args>
+  explicit thread(Function &&f, Args &&... args) {
+    f(std::forward<Args>(args)...);
+  }
+  thread(const thread &) = delete;
+
+  void join() {}
+  static unsigned hardware_concurrency() { return 1; };
+};
+
+}
+
+#endif // LLVM_ENABLE_THREADS
+
+#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/type_traits.h b/third_party/llvm-subzero/include/llvm/Support/type_traits.h
new file mode 100644
index 0000000..7706ff5
--- /dev/null
+++ b/third_party/llvm-subzero/include/llvm/Support/type_traits.h
@@ -0,0 +1,113 @@
+//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides useful additions to the standard type_traits library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPE_TRAITS_H
+#define LLVM_SUPPORT_TYPE_TRAITS_H
+
+#include <type_traits>
+#include <utility>
+
+#include "llvm/Support/Compiler.h"
+
+#ifndef __has_feature
+#define LLVM_DEFINED_HAS_FEATURE
+#define __has_feature(x) 0
+#endif
+
+namespace llvm {
+
+/// isPodLike - This is a type trait that is used to determine whether a given
+/// type can be copied around with memcpy instead of running ctors etc.
+template <typename T>
+struct isPodLike {
+  // std::is_trivially_copyable is available in libc++ with clang, libstdc++
+  // that comes with GCC 5.
+#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) ||      \
+    (defined(__GNUC__) && __GNUC__ >= 5)
+  // If the compiler supports the is_trivially_copyable trait use it, as it
+  // matches the definition of isPodLike closely.
+  static const bool value = std::is_trivially_copyable<T>::value;
+#elif __has_feature(is_trivially_copyable)
+  // Use the internal name if the compiler supports is_trivially_copyable but we
+  // don't know if the standard library does. This is the case for clang in
+  // conjunction with libstdc++ from GCC 4.x.
+  static const bool value = __is_trivially_copyable(T);
+#else
+  // If we don't know anything else, we can (at least) assume that all non-class
+  // types are PODs.
+  static const bool value = !std::is_class<T>::value;
+#endif
+};
+
+// std::pair's are pod-like if their elements are.
+template<typename T, typename U>
+struct isPodLike<std::pair<T, U> > {
+  static const bool value = isPodLike<T>::value && isPodLike<U>::value;
+};
+
+/// \brief Metafunction that determines whether the given type is either an
+/// integral type or an enumeration type, including enum classes.
+///
+/// Note that this accepts potentially more integral types than is_integral
+/// because it is based on being implicitly convertible to an integral type.
+/// Also note that enum classes aren't implicitly convertible to integral types,
+/// the value may therefore need to be explicitly converted before being used.
+template <typename T> class is_integral_or_enum {
+  typedef typename std::remove_reference<T>::type UnderlyingT;
+
+public:
+  static const bool value =
+      !std::is_class<UnderlyingT>::value && // Filter conversion operators.
+      !std::is_pointer<UnderlyingT>::value &&
+      !std::is_floating_point<UnderlyingT>::value &&
+      (std::is_enum<UnderlyingT>::value ||
+       std::is_convertible<UnderlyingT, unsigned long long>::value);
+};
+
+/// \brief If T is a pointer, just return it. If it is not, return T&.
+template<typename T, typename Enable = void>
+struct add_lvalue_reference_if_not_pointer { typedef T &type; };
+
+template <typename T>
+struct add_lvalue_reference_if_not_pointer<
+    T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+  typedef T type;
+};
+
+/// \brief If T is a pointer to X, return a pointer to const X. If it is not,
+/// return const T.
+template<typename T, typename Enable = void>
+struct add_const_past_pointer { typedef const T type; };
+
+template <typename T>
+struct add_const_past_pointer<
+    T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+  typedef const typename std::remove_pointer<T>::type *type;
+};
+
+}
+
+// If the compiler supports detecting whether a class is final, define
+// an LLVM_IS_FINAL macro. If it cannot be defined properly, this
+// macro will be left undefined.
+#if __cplusplus >= 201402L
+#define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
+#elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
+#define LLVM_IS_FINAL(Ty) __is_final(Ty)
+#endif
+
+#ifdef LLVM_DEFINED_HAS_FEATURE
+#undef __has_feature
+#endif
+
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/APInt.cpp b/third_party/llvm-subzero/lib/Support/APInt.cpp
new file mode 100644
index 0000000..318ce10
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/APInt.cpp
@@ -0,0 +1,2887 @@
+//===-- APInt.cpp - Implement APInt class ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a class to represent arbitrary precision integer
+// constant values and provide a variety of arithmetic operations on them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+using namespace llvm;
+
+#define DEBUG_TYPE "apint"
+
+/// A utility function for allocating memory, checking for allocation failures,
+/// and ensuring the contents are zeroed.
+inline static uint64_t* getClearedMemory(unsigned numWords) {
+  uint64_t * result = new uint64_t[numWords];
+  assert(result && "APInt memory allocation fails!");
+  memset(result, 0, numWords * sizeof(uint64_t));
+  return result;
+}
+
+/// A utility function for allocating memory and checking for allocation
+/// failure.  The content is not zeroed.
+inline static uint64_t* getMemory(unsigned numWords) {
+  uint64_t * result = new uint64_t[numWords];
+  assert(result && "APInt memory allocation fails!");
+  return result;
+}
+
+/// A utility function that converts a character to a digit.
+inline static unsigned getDigit(char cdigit, uint8_t radix) {
+  unsigned r;
+
+  if (radix == 16 || radix == 36) {
+    r = cdigit - '0';
+    if (r <= 9)
+      return r;
+
+    r = cdigit - 'A';
+    if (r <= radix - 11U)
+      return r + 10;
+
+    r = cdigit - 'a';
+    if (r <= radix - 11U)
+      return r + 10;
+    
+    radix = 10;
+  }
+
+  r = cdigit - '0';
+  if (r < radix)
+    return r;
+
+  return -1U;
+}
+
+
+void APInt::initSlowCase(uint64_t val, bool isSigned) {
+  pVal = getClearedMemory(getNumWords());
+  pVal[0] = val;
+  if (isSigned && int64_t(val) < 0)
+    for (unsigned i = 1; i < getNumWords(); ++i)
+      pVal[i] = -1ULL;
+}
+
+void APInt::initSlowCase(const APInt& that) {
+  pVal = getMemory(getNumWords());
+  memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE);
+}
+
+void APInt::initFromArray(ArrayRef<uint64_t> bigVal) {
+  assert(BitWidth && "Bitwidth too small");
+  assert(bigVal.data() && "Null pointer detected!");
+  if (isSingleWord())
+    VAL = bigVal[0];
+  else {
+    // Get memory, cleared to 0
+    pVal = getClearedMemory(getNumWords());
+    // Calculate the number of words to copy
+    unsigned words = std::min<unsigned>(bigVal.size(), getNumWords());
+    // Copy the words from bigVal to pVal
+    memcpy(pVal, bigVal.data(), words * APINT_WORD_SIZE);
+  }
+  // Make sure unused high bits are cleared
+  clearUnusedBits();
+}
+
+APInt::APInt(unsigned numBits, ArrayRef<uint64_t> bigVal)
+  : BitWidth(numBits), VAL(0) {
+  initFromArray(bigVal);
+}
+
+APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[])
+  : BitWidth(numBits), VAL(0) {
+  initFromArray(makeArrayRef(bigVal, numWords));
+}
+
+APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix)
+  : BitWidth(numbits), VAL(0) {
+  assert(BitWidth && "Bitwidth too small");
+  fromString(numbits, Str, radix);
+}
+
+APInt& APInt::AssignSlowCase(const APInt& RHS) {
+  // Don't do anything for X = X
+  if (this == &RHS)
+    return *this;
+
+  if (BitWidth == RHS.getBitWidth()) {
+    // assume same bit-width single-word case is already handled
+    assert(!isSingleWord());
+    memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE);
+    return *this;
+  }
+
+  if (isSingleWord()) {
+    // assume case where both are single words is already handled
+    assert(!RHS.isSingleWord());
+    VAL = 0;
+    pVal = getMemory(RHS.getNumWords());
+    memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
+  } else if (getNumWords() == RHS.getNumWords())
+    memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
+  else if (RHS.isSingleWord()) {
+    delete [] pVal;
+    VAL = RHS.VAL;
+  } else {
+    delete [] pVal;
+    pVal = getMemory(RHS.getNumWords());
+    memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
+  }
+  BitWidth = RHS.BitWidth;
+  return clearUnusedBits();
+}
+
+APInt& APInt::operator=(uint64_t RHS) {
+  if (isSingleWord())
+    VAL = RHS;
+  else {
+    pVal[0] = RHS;
+    memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
+  }
+  return clearUnusedBits();
+}
+
+/// This method 'profiles' an APInt for use with FoldingSet.
+void APInt::Profile(FoldingSetNodeID& ID) const {
+  ID.AddInteger(BitWidth);
+
+  if (isSingleWord()) {
+    ID.AddInteger(VAL);
+    return;
+  }
+
+  unsigned NumWords = getNumWords();
+  for (unsigned i = 0; i < NumWords; ++i)
+    ID.AddInteger(pVal[i]);
+}
+
+/// This function adds a single "digit" integer, y, to the multiple
+/// "digit" integer array,  x[]. x[] is modified to reflect the addition and
+/// 1 is returned if there is a carry out, otherwise 0 is returned.
+/// @returns the carry of the addition.
+static bool add_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) {
+  for (unsigned i = 0; i < len; ++i) {
+    dest[i] = y + x[i];
+    if (dest[i] < y)
+      y = 1; // Carry one to next digit.
+    else {
+      y = 0; // No need to carry so exit early
+      break;
+    }
+  }
+  return y;
+}
+
+/// @brief Prefix increment operator. Increments the APInt by one.
+APInt& APInt::operator++() {
+  if (isSingleWord())
+    ++VAL;
+  else
+    add_1(pVal, pVal, getNumWords(), 1);
+  return clearUnusedBits();
+}
+
+/// This function subtracts a single "digit" (64-bit word), y, from
+/// the multi-digit integer array, x[], propagating the borrowed 1 value until
+/// no further borrowing is neeeded or it runs out of "digits" in x.  The result
+/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted.
+/// In other words, if y > x then this function returns 1, otherwise 0.
+/// @returns the borrow out of the subtraction
+static bool sub_1(uint64_t x[], unsigned len, uint64_t y) {
+  for (unsigned i = 0; i < len; ++i) {
+    uint64_t X = x[i];
+    x[i] -= y;
+    if (y > X)
+      y = 1;  // We have to "borrow 1" from next "digit"
+    else {
+      y = 0;  // No need to borrow
+      break;  // Remaining digits are unchanged so exit early
+    }
+  }
+  return bool(y);
+}
+
+/// @brief Prefix decrement operator. Decrements the APInt by one.
+APInt& APInt::operator--() {
+  if (isSingleWord())
+    --VAL;
+  else
+    sub_1(pVal, getNumWords(), 1);
+  return clearUnusedBits();
+}
+
+/// This function adds the integer array x to the integer array Y and
+/// places the result in dest.
+/// @returns the carry out from the addition
+/// @brief General addition of 64-bit integer arrays
+static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y,
+                unsigned len) {
+  bool carry = false;
+  for (unsigned i = 0; i< len; ++i) {
+    uint64_t limit = std::min(x[i],y[i]); // must come first in case dest == x
+    dest[i] = x[i] + y[i] + carry;
+    carry = dest[i] < limit || (carry && dest[i] == limit);
+  }
+  return carry;
+}
+
+/// Adds the RHS APint to this APInt.
+/// @returns this, after addition of RHS.
+/// @brief Addition assignment operator.
+APInt& APInt::operator+=(const APInt& RHS) {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord())
+    VAL += RHS.VAL;
+  else {
+    add(pVal, pVal, RHS.pVal, getNumWords());
+  }
+  return clearUnusedBits();
+}
+
+APInt& APInt::operator+=(uint64_t RHS) {
+  if (isSingleWord())
+    VAL += RHS;
+  else
+    add_1(pVal, pVal, getNumWords(), RHS);
+  return clearUnusedBits();
+}
+
+/// Subtracts the integer array y from the integer array x
+/// @returns returns the borrow out.
+/// @brief Generalized subtraction of 64-bit integer arrays.
+static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y,
+                unsigned len) {
+  bool borrow = false;
+  for (unsigned i = 0; i < len; ++i) {
+    uint64_t x_tmp = borrow ? x[i] - 1 : x[i];
+    borrow = y[i] > x_tmp || (borrow && x[i] == 0);
+    dest[i] = x_tmp - y[i];
+  }
+  return borrow;
+}
+
+/// Subtracts the RHS APInt from this APInt
+/// @returns this, after subtraction
+/// @brief Subtraction assignment operator.
+APInt& APInt::operator-=(const APInt& RHS) {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord())
+    VAL -= RHS.VAL;
+  else
+    sub(pVal, pVal, RHS.pVal, getNumWords());
+  return clearUnusedBits();
+}
+
+APInt& APInt::operator-=(uint64_t RHS) {
+  if (isSingleWord())
+    VAL -= RHS;
+  else
+    sub_1(pVal, getNumWords(), RHS);
+  return clearUnusedBits();
+}
+
+/// Multiplies an integer array, x, by a uint64_t integer and places the result
+/// into dest.
+/// @returns the carry out of the multiplication.
+/// @brief Multiply a multi-digit APInt by a single digit (64-bit) integer.
+static uint64_t mul_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) {
+  // Split y into high 32-bit part (hy)  and low 32-bit part (ly)
+  uint64_t ly = y & 0xffffffffULL, hy = y >> 32;
+  uint64_t carry = 0;
+
+  // For each digit of x.
+  for (unsigned i = 0; i < len; ++i) {
+    // Split x into high and low words
+    uint64_t lx = x[i] & 0xffffffffULL;
+    uint64_t hx = x[i] >> 32;
+    // hasCarry - A flag to indicate if there is a carry to the next digit.
+    // hasCarry == 0, no carry
+    // hasCarry == 1, has carry
+    // hasCarry == 2, no carry and the calculation result == 0.
+    uint8_t hasCarry = 0;
+    dest[i] = carry + lx * ly;
+    // Determine if the add above introduces carry.
+    hasCarry = (dest[i] < carry) ? 1 : 0;
+    carry = hx * ly + (dest[i] >> 32) + (hasCarry ? (1ULL << 32) : 0);
+    // The upper limit of carry can be (2^32 - 1)(2^32 - 1) +
+    // (2^32 - 1) + 2^32 = 2^64.
+    hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
+
+    carry += (lx * hy) & 0xffffffffULL;
+    dest[i] = (carry << 32) | (dest[i] & 0xffffffffULL);
+    carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) +
+            (carry >> 32) + ((lx * hy) >> 32) + hx * hy;
+  }
+  return carry;
+}
+
+/// Multiplies integer array x by integer array y and stores the result into
+/// the integer array dest. Note that dest's size must be >= xlen + ylen.
+/// @brief Generalized multiplicate of integer arrays.
+static void mul(uint64_t dest[], uint64_t x[], unsigned xlen, uint64_t y[],
+                unsigned ylen) {
+  dest[xlen] = mul_1(dest, x, xlen, y[0]);
+  for (unsigned i = 1; i < ylen; ++i) {
+    uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32;
+    uint64_t carry = 0, lx = 0, hx = 0;
+    for (unsigned j = 0; j < xlen; ++j) {
+      lx = x[j] & 0xffffffffULL;
+      hx = x[j] >> 32;
+      // hasCarry - A flag to indicate if has carry.
+      // hasCarry == 0, no carry
+      // hasCarry == 1, has carry
+      // hasCarry == 2, no carry and the calculation result == 0.
+      uint8_t hasCarry = 0;
+      uint64_t resul = carry + lx * ly;
+      hasCarry = (resul < carry) ? 1 : 0;
+      carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + (resul >> 32);
+      hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
+
+      carry += (lx * hy) & 0xffffffffULL;
+      resul = (carry << 32) | (resul & 0xffffffffULL);
+      dest[i+j] += resul;
+      carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+
+              (carry >> 32) + (dest[i+j] < resul ? 1 : 0) +
+              ((lx * hy) >> 32) + hx * hy;
+    }
+    dest[i+xlen] = carry;
+  }
+}
+
+APInt& APInt::operator*=(const APInt& RHS) {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord()) {
+    VAL *= RHS.VAL;
+    clearUnusedBits();
+    return *this;
+  }
+
+  // Get some bit facts about LHS and check for zero
+  unsigned lhsBits = getActiveBits();
+  unsigned lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1;
+  if (!lhsWords)
+    // 0 * X ===> 0
+    return *this;
+
+  // Get some bit facts about RHS and check for zero
+  unsigned rhsBits = RHS.getActiveBits();
+  unsigned rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1;
+  if (!rhsWords) {
+    // X * 0 ===> 0
+    clearAllBits();
+    return *this;
+  }
+
+  // Allocate space for the result
+  unsigned destWords = rhsWords + lhsWords;
+  uint64_t *dest = getMemory(destWords);
+
+  // Perform the long multiply
+  mul(dest, pVal, lhsWords, RHS.pVal, rhsWords);
+
+  // Copy result back into *this
+  clearAllBits();
+  unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords;
+  memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE);
+  clearUnusedBits();
+
+  // delete dest array and return
+  delete[] dest;
+  return *this;
+}
+
+APInt& APInt::operator&=(const APInt& RHS) {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord()) {
+    VAL &= RHS.VAL;
+    return *this;
+  }
+  unsigned numWords = getNumWords();
+  for (unsigned i = 0; i < numWords; ++i)
+    pVal[i] &= RHS.pVal[i];
+  return *this;
+}
+
+APInt& APInt::operator|=(const APInt& RHS) {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord()) {
+    VAL |= RHS.VAL;
+    return *this;
+  }
+  unsigned numWords = getNumWords();
+  for (unsigned i = 0; i < numWords; ++i)
+    pVal[i] |= RHS.pVal[i];
+  return *this;
+}
+
+APInt& APInt::operator^=(const APInt& RHS) {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord()) {
+    VAL ^= RHS.VAL;
+    this->clearUnusedBits();
+    return *this;
+  }
+  unsigned numWords = getNumWords();
+  for (unsigned i = 0; i < numWords; ++i)
+    pVal[i] ^= RHS.pVal[i];
+  return clearUnusedBits();
+}
+
+APInt APInt::AndSlowCase(const APInt& RHS) const {
+  unsigned numWords = getNumWords();
+  uint64_t* val = getMemory(numWords);
+  for (unsigned i = 0; i < numWords; ++i)
+    val[i] = pVal[i] & RHS.pVal[i];
+  return APInt(val, getBitWidth());
+}
+
+APInt APInt::OrSlowCase(const APInt& RHS) const {
+  unsigned numWords = getNumWords();
+  uint64_t *val = getMemory(numWords);
+  for (unsigned i = 0; i < numWords; ++i)
+    val[i] = pVal[i] | RHS.pVal[i];
+  return APInt(val, getBitWidth());
+}
+
+APInt APInt::XorSlowCase(const APInt& RHS) const {
+  unsigned numWords = getNumWords();
+  uint64_t *val = getMemory(numWords);
+  for (unsigned i = 0; i < numWords; ++i)
+    val[i] = pVal[i] ^ RHS.pVal[i];
+
+  APInt Result(val, getBitWidth());
+  // 0^0==1 so clear the high bits in case they got set.
+  Result.clearUnusedBits();
+  return Result;
+}
+
+APInt APInt::operator*(const APInt& RHS) const {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord())
+    return APInt(BitWidth, VAL * RHS.VAL);
+  APInt Result(*this);
+  Result *= RHS;
+  return Result;
+}
+
+bool APInt::EqualSlowCase(const APInt& RHS) const {
+  return std::equal(pVal, pVal + getNumWords(), RHS.pVal);
+}
+
+bool APInt::EqualSlowCase(uint64_t Val) const {
+  unsigned n = getActiveBits();
+  if (n <= APINT_BITS_PER_WORD)
+    return pVal[0] == Val;
+  else
+    return false;
+}
+
+bool APInt::ult(const APInt& RHS) const {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
+  if (isSingleWord())
+    return VAL < RHS.VAL;
+
+  // Get active bit length of both operands
+  unsigned n1 = getActiveBits();
+  unsigned n2 = RHS.getActiveBits();
+
+  // If magnitude of LHS is less than RHS, return true.
+  if (n1 < n2)
+    return true;
+
+  // If magnitude of RHS is greather than LHS, return false.
+  if (n2 < n1)
+    return false;
+
+  // If they bot fit in a word, just compare the low order word
+  if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD)
+    return pVal[0] < RHS.pVal[0];
+
+  // Otherwise, compare all words
+  unsigned topWord = whichWord(std::max(n1,n2)-1);
+  for (int i = topWord; i >= 0; --i) {
+    if (pVal[i] > RHS.pVal[i])
+      return false;
+    if (pVal[i] < RHS.pVal[i])
+      return true;
+  }
+  return false;
+}
+
+bool APInt::slt(const APInt& RHS) const {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
+  if (isSingleWord()) {
+    int64_t lhsSext = SignExtend64(VAL, BitWidth);
+    int64_t rhsSext = SignExtend64(RHS.VAL, BitWidth);
+    return lhsSext < rhsSext;
+  }
+
+  bool lhsNeg = isNegative();
+  bool rhsNeg = RHS.isNegative();
+
+  // If the sign bits don't match, then (LHS < RHS) if LHS is negative
+  if (lhsNeg != rhsNeg)
+    return lhsNeg;
+
+  // Otherwise we can just use an unsigned comparision, because even negative
+  // numbers compare correctly this way if both have the same signed-ness.
+  return ult(RHS);
+}
+
+void APInt::setBit(unsigned bitPosition) {
+  if (isSingleWord())
+    VAL |= maskBit(bitPosition);
+  else
+    pVal[whichWord(bitPosition)] |= maskBit(bitPosition);
+}
+
+/// Set the given bit to 0 whose position is given as "bitPosition".
+/// @brief Set a given bit to 0.
+void APInt::clearBit(unsigned bitPosition) {
+  if (isSingleWord())
+    VAL &= ~maskBit(bitPosition);
+  else
+    pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition);
+}
+
+/// @brief Toggle every bit to its opposite value.
+
+/// Toggle a given bit to its opposite value whose position is given
+/// as "bitPosition".
+/// @brief Toggles a given bit to its opposite value.
+void APInt::flipBit(unsigned bitPosition) {
+  assert(bitPosition < BitWidth && "Out of the bit-width range!");
+  if ((*this)[bitPosition]) clearBit(bitPosition);
+  else setBit(bitPosition);
+}
+
+unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
+  assert(!str.empty() && "Invalid string length");
+  assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || 
+          radix == 36) &&
+         "Radix should be 2, 8, 10, 16, or 36!");
+
+  size_t slen = str.size();
+
+  // Each computation below needs to know if it's negative.
+  StringRef::iterator p = str.begin();
+  unsigned isNegative = *p == '-';
+  if (*p == '-' || *p == '+') {
+    p++;
+    slen--;
+    assert(slen && "String is only a sign, needs a value.");
+  }
+
+  // For radixes of power-of-two values, the bits required is accurately and
+  // easily computed
+  if (radix == 2)
+    return slen + isNegative;
+  if (radix == 8)
+    return slen * 3 + isNegative;
+  if (radix == 16)
+    return slen * 4 + isNegative;
+
+  // FIXME: base 36
+  
+  // This is grossly inefficient but accurate. We could probably do something
+  // with a computation of roughly slen*64/20 and then adjust by the value of
+  // the first few digits. But, I'm not sure how accurate that could be.
+
+  // Compute a sufficient number of bits that is always large enough but might
+  // be too large. This avoids the assertion in the constructor. This
+  // calculation doesn't work appropriately for the numbers 0-9, so just use 4
+  // bits in that case.
+  unsigned sufficient 
+    = radix == 10? (slen == 1 ? 4 : slen * 64/18)
+                 : (slen == 1 ? 7 : slen * 16/3);
+
+  // Convert to the actual binary value.
+  APInt tmp(sufficient, StringRef(p, slen), radix);
+
+  // Compute how many bits are required. If the log is infinite, assume we need
+  // just bit.
+  unsigned log = tmp.logBase2();
+  if (log == (unsigned)-1) {
+    return isNegative + 1;
+  } else {
+    return isNegative + log + 1;
+  }
+}
+
+hash_code llvm::hash_value(const APInt &Arg) {
+  if (Arg.isSingleWord())
+    return hash_combine(Arg.VAL);
+
+  return hash_combine_range(Arg.pVal, Arg.pVal + Arg.getNumWords());
+}
+
+bool APInt::isSplat(unsigned SplatSizeInBits) const {
+  assert(getBitWidth() % SplatSizeInBits == 0 &&
+         "SplatSizeInBits must divide width!");
+  // We can check that all parts of an integer are equal by making use of a
+  // little trick: rotate and check if it's still the same value.
+  return *this == rotl(SplatSizeInBits);
+}
+
+/// This function returns the high "numBits" bits of this APInt.
+APInt APInt::getHiBits(unsigned numBits) const {
+  return APIntOps::lshr(*this, BitWidth - numBits);
+}
+
+/// This function returns the low "numBits" bits of this APInt.
+APInt APInt::getLoBits(unsigned numBits) const {
+  return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits),
+                        BitWidth - numBits);
+}
+
+unsigned APInt::countLeadingZerosSlowCase() const {
+  unsigned Count = 0;
+  for (int i = getNumWords()-1; i >= 0; --i) {
+    integerPart V = pVal[i];
+    if (V == 0)
+      Count += APINT_BITS_PER_WORD;
+    else {
+      Count += llvm::countLeadingZeros(V);
+      break;
+    }
+  }
+  // Adjust for unused bits in the most significant word (they are zero).
+  unsigned Mod = BitWidth % APINT_BITS_PER_WORD;
+  Count -= Mod > 0 ? APINT_BITS_PER_WORD - Mod : 0;
+  return Count;
+}
+
+unsigned APInt::countLeadingOnes() const {
+  if (isSingleWord())
+    return llvm::countLeadingOnes(VAL << (APINT_BITS_PER_WORD - BitWidth));
+
+  unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD;
+  unsigned shift;
+  if (!highWordBits) {
+    highWordBits = APINT_BITS_PER_WORD;
+    shift = 0;
+  } else {
+    shift = APINT_BITS_PER_WORD - highWordBits;
+  }
+  int i = getNumWords() - 1;
+  unsigned Count = llvm::countLeadingOnes(pVal[i] << shift);
+  if (Count == highWordBits) {
+    for (i--; i >= 0; --i) {
+      if (pVal[i] == -1ULL)
+        Count += APINT_BITS_PER_WORD;
+      else {
+        Count += llvm::countLeadingOnes(pVal[i]);
+        break;
+      }
+    }
+  }
+  return Count;
+}
+
+unsigned APInt::countTrailingZeros() const {
+  if (isSingleWord())
+    return std::min(unsigned(llvm::countTrailingZeros(VAL)), BitWidth);
+  unsigned Count = 0;
+  unsigned i = 0;
+  for (; i < getNumWords() && pVal[i] == 0; ++i)
+    Count += APINT_BITS_PER_WORD;
+  if (i < getNumWords())
+    Count += llvm::countTrailingZeros(pVal[i]);
+  return std::min(Count, BitWidth);
+}
+
+unsigned APInt::countTrailingOnesSlowCase() const {
+  unsigned Count = 0;
+  unsigned i = 0;
+  for (; i < getNumWords() && pVal[i] == -1ULL; ++i)
+    Count += APINT_BITS_PER_WORD;
+  if (i < getNumWords())
+    Count += llvm::countTrailingOnes(pVal[i]);
+  return std::min(Count, BitWidth);
+}
+
+unsigned APInt::countPopulationSlowCase() const {
+  unsigned Count = 0;
+  for (unsigned i = 0; i < getNumWords(); ++i)
+    Count += llvm::countPopulation(pVal[i]);
+  return Count;
+}
+
+/// Perform a logical right-shift from Src to Dst, which must be equal or
+/// non-overlapping, of Words words, by Shift, which must be less than 64.
+static void lshrNear(uint64_t *Dst, uint64_t *Src, unsigned Words,
+                     unsigned Shift) {
+  uint64_t Carry = 0;
+  for (int I = Words - 1; I >= 0; --I) {
+    uint64_t Tmp = Src[I];
+    Dst[I] = (Tmp >> Shift) | Carry;
+    Carry = Tmp << (64 - Shift);
+  }
+}
+
+APInt APInt::byteSwap() const {
+  assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!");
+  if (BitWidth == 16)
+    return APInt(BitWidth, ByteSwap_16(uint16_t(VAL)));
+  if (BitWidth == 32)
+    return APInt(BitWidth, ByteSwap_32(unsigned(VAL)));
+  if (BitWidth == 48) {
+    unsigned Tmp1 = unsigned(VAL >> 16);
+    Tmp1 = ByteSwap_32(Tmp1);
+    uint16_t Tmp2 = uint16_t(VAL);
+    Tmp2 = ByteSwap_16(Tmp2);
+    return APInt(BitWidth, (uint64_t(Tmp2) << 32) | Tmp1);
+  }
+  if (BitWidth == 64)
+    return APInt(BitWidth, ByteSwap_64(VAL));
+
+  APInt Result(getNumWords() * APINT_BITS_PER_WORD, 0);
+  for (unsigned I = 0, N = getNumWords(); I != N; ++I)
+    Result.pVal[I] = ByteSwap_64(pVal[N - I - 1]);
+  if (Result.BitWidth != BitWidth) {
+    lshrNear(Result.pVal, Result.pVal, getNumWords(),
+             Result.BitWidth - BitWidth);
+    Result.BitWidth = BitWidth;
+  }
+  return Result;
+}
+
+APInt APInt::reverseBits() const {
+  switch (BitWidth) {
+  case 64:
+    return APInt(BitWidth, llvm::reverseBits<uint64_t>(VAL));
+  case 32:
+    return APInt(BitWidth, llvm::reverseBits<uint32_t>(VAL));
+  case 16:
+    return APInt(BitWidth, llvm::reverseBits<uint16_t>(VAL));
+  case 8:
+    return APInt(BitWidth, llvm::reverseBits<uint8_t>(VAL));
+  default:
+    break;
+  }
+
+  APInt Val(*this);
+  APInt Reversed(*this);
+  int S = BitWidth - 1;
+
+  const APInt One(BitWidth, 1);
+
+  for ((Val = Val.lshr(1)); Val != 0; (Val = Val.lshr(1))) {
+    Reversed <<= 1;
+    Reversed |= (Val & One);
+    --S;
+  }
+
+  Reversed <<= S;
+  return Reversed;
+}
+
+APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
+                                            const APInt& API2) {
+  APInt A = API1, B = API2;
+  while (!!B) {
+    APInt T = B;
+    B = APIntOps::urem(A, B);
+    A = T;
+  }
+  return A;
+}
+
+APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
+  union {
+    double D;
+    uint64_t I;
+  } T;
+  T.D = Double;
+
+  // Get the sign bit from the highest order bit
+  bool isNeg = T.I >> 63;
+
+  // Get the 11-bit exponent and adjust for the 1023 bit bias
+  int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
+
+  // If the exponent is negative, the value is < 0 so just return 0.
+  if (exp < 0)
+    return APInt(width, 0u);
+
+  // Extract the mantissa by clearing the top 12 bits (sign + exponent).
+  uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52;
+
+  // If the exponent doesn't shift all bits out of the mantissa
+  if (exp < 52)
+    return isNeg ? -APInt(width, mantissa >> (52 - exp)) :
+                    APInt(width, mantissa >> (52 - exp));
+
+  // If the client didn't provide enough bits for us to shift the mantissa into
+  // then the result is undefined, just return 0
+  if (width <= exp - 52)
+    return APInt(width, 0);
+
+  // Otherwise, we have to shift the mantissa bits up to the right location
+  APInt Tmp(width, mantissa);
+  Tmp = Tmp.shl((unsigned)exp - 52);
+  return isNeg ? -Tmp : Tmp;
+}
+
+/// This function converts this APInt to a double.
+/// The layout for double is as following (IEEE Standard 754):
+///  --------------------------------------
+/// |  Sign    Exponent    Fraction    Bias |
+/// |-------------------------------------- |
+/// |  1[63]   11[62-52]   52[51-00]   1023 |
+///  --------------------------------------
+double APInt::roundToDouble(bool isSigned) const {
+
+  // Handle the simple case where the value is contained in one uint64_t.
+  // It is wrong to optimize getWord(0) to VAL; there might be more than one word.
+  if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
+    if (isSigned) {
+      int64_t sext = SignExtend64(getWord(0), BitWidth);
+      return double(sext);
+    } else
+      return double(getWord(0));
+  }
+
+  // Determine if the value is negative.
+  bool isNeg = isSigned ? (*this)[BitWidth-1] : false;
+
+  // Construct the absolute value if we're negative.
+  APInt Tmp(isNeg ? -(*this) : (*this));
+
+  // Figure out how many bits we're using.
+  unsigned n = Tmp.getActiveBits();
+
+  // The exponent (without bias normalization) is just the number of bits
+  // we are using. Note that the sign bit is gone since we constructed the
+  // absolute value.
+  uint64_t exp = n;
+
+  // Return infinity for exponent overflow
+  if (exp > 1023) {
+    if (!isSigned || !isNeg)
+      return std::numeric_limits<double>::infinity();
+    else
+      return -std::numeric_limits<double>::infinity();
+  }
+  exp += 1023; // Increment for 1023 bias
+
+  // Number of bits in mantissa is 52. To obtain the mantissa value, we must
+  // extract the high 52 bits from the correct words in pVal.
+  uint64_t mantissa;
+  unsigned hiWord = whichWord(n-1);
+  if (hiWord == 0) {
+    mantissa = Tmp.pVal[0];
+    if (n > 52)
+      mantissa >>= n - 52; // shift down, we want the top 52 bits.
+  } else {
+    assert(hiWord > 0 && "huh?");
+    uint64_t hibits = Tmp.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD);
+    uint64_t lobits = Tmp.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD);
+    mantissa = hibits | lobits;
+  }
+
+  // The leading bit of mantissa is implicit, so get rid of it.
+  uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;
+  union {
+    double D;
+    uint64_t I;
+  } T;
+  T.I = sign | (exp << 52) | mantissa;
+  return T.D;
+}
+
+// Truncate to new width.
+APInt APInt::trunc(unsigned width) const {
+  assert(width < BitWidth && "Invalid APInt Truncate request");
+  assert(width && "Can't truncate to 0 bits");
+
+  if (width <= APINT_BITS_PER_WORD)
+    return APInt(width, getRawData()[0]);
+
+  APInt Result(getMemory(getNumWords(width)), width);
+
+  // Copy full words.
+  unsigned i;
+  for (i = 0; i != width / APINT_BITS_PER_WORD; i++)
+    Result.pVal[i] = pVal[i];
+
+  // Truncate and copy any partial word.
+  unsigned bits = (0 - width) % APINT_BITS_PER_WORD;
+  if (bits != 0)
+    Result.pVal[i] = pVal[i] << bits >> bits;
+
+  return Result;
+}
+
+// Sign extend to a new width.
+APInt APInt::sext(unsigned width) const {
+  assert(width > BitWidth && "Invalid APInt SignExtend request");
+
+  if (width <= APINT_BITS_PER_WORD) {
+    uint64_t val = VAL << (APINT_BITS_PER_WORD - BitWidth);
+    val = (int64_t)val >> (width - BitWidth);
+    return APInt(width, val >> (APINT_BITS_PER_WORD - width));
+  }
+
+  APInt Result(getMemory(getNumWords(width)), width);
+
+  // Copy full words.
+  unsigned i;
+  uint64_t word = 0;
+  for (i = 0; i != BitWidth / APINT_BITS_PER_WORD; i++) {
+    word = getRawData()[i];
+    Result.pVal[i] = word;
+  }
+
+  // Read and sign-extend any partial word.
+  unsigned bits = (0 - BitWidth) % APINT_BITS_PER_WORD;
+  if (bits != 0)
+    word = (int64_t)getRawData()[i] << bits >> bits;
+  else
+    word = (int64_t)word >> (APINT_BITS_PER_WORD - 1);
+
+  // Write remaining full words.
+  for (; i != width / APINT_BITS_PER_WORD; i++) {
+    Result.pVal[i] = word;
+    word = (int64_t)word >> (APINT_BITS_PER_WORD - 1);
+  }
+
+  // Write any partial word.
+  bits = (0 - width) % APINT_BITS_PER_WORD;
+  if (bits != 0)
+    Result.pVal[i] = word << bits >> bits;
+
+  return Result;
+}
+
+//  Zero extend to a new width.
+APInt APInt::zext(unsigned width) const {
+  assert(width > BitWidth && "Invalid APInt ZeroExtend request");
+
+  if (width <= APINT_BITS_PER_WORD)
+    return APInt(width, VAL);
+
+  APInt Result(getMemory(getNumWords(width)), width);
+
+  // Copy words.
+  unsigned i;
+  for (i = 0; i != getNumWords(); i++)
+    Result.pVal[i] = getRawData()[i];
+
+  // Zero remaining words.
+  memset(&Result.pVal[i], 0, (Result.getNumWords() - i) * APINT_WORD_SIZE);
+
+  return Result;
+}
+
+APInt APInt::zextOrTrunc(unsigned width) const {
+  if (BitWidth < width)
+    return zext(width);
+  if (BitWidth > width)
+    return trunc(width);
+  return *this;
+}
+
+APInt APInt::sextOrTrunc(unsigned width) const {
+  if (BitWidth < width)
+    return sext(width);
+  if (BitWidth > width)
+    return trunc(width);
+  return *this;
+}
+
+APInt APInt::zextOrSelf(unsigned width) const {
+  if (BitWidth < width)
+    return zext(width);
+  return *this;
+}
+
+APInt APInt::sextOrSelf(unsigned width) const {
+  if (BitWidth < width)
+    return sext(width);
+  return *this;
+}
+
+/// Arithmetic right-shift this APInt by shiftAmt.
+/// @brief Arithmetic right-shift function.
+APInt APInt::ashr(const APInt &shiftAmt) const {
+  return ashr((unsigned)shiftAmt.getLimitedValue(BitWidth));
+}
+
+/// Arithmetic right-shift this APInt by shiftAmt.
+/// @brief Arithmetic right-shift function.
+APInt APInt::ashr(unsigned shiftAmt) const {
+  assert(shiftAmt <= BitWidth && "Invalid shift amount");
+  // Handle a degenerate case
+  if (shiftAmt == 0)
+    return *this;
+
+  // Handle single word shifts with built-in ashr
+  if (isSingleWord()) {
+    if (shiftAmt == BitWidth)
+      return APInt(BitWidth, 0); // undefined
+    return APInt(BitWidth, SignExtend64(VAL, BitWidth) >> shiftAmt);
+  }
+
+  // If all the bits were shifted out, the result is, technically, undefined.
+  // We return -1 if it was negative, 0 otherwise. We check this early to avoid
+  // issues in the algorithm below.
+  if (shiftAmt == BitWidth) {
+    if (isNegative())
+      return APInt(BitWidth, -1ULL, true);
+    else
+      return APInt(BitWidth, 0);
+  }
+
+  // Create some space for the result.
+  uint64_t * val = new uint64_t[getNumWords()];
+
+  // Compute some values needed by the following shift algorithms
+  unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word
+  unsigned offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift
+  unsigned breakWord = getNumWords() - 1 - offset; // last word affected
+  unsigned bitsInWord = whichBit(BitWidth); // how many bits in last word?
+  if (bitsInWord == 0)
+    bitsInWord = APINT_BITS_PER_WORD;
+
+  // If we are shifting whole words, just move whole words
+  if (wordShift == 0) {
+    // Move the words containing significant bits
+    for (unsigned i = 0; i <= breakWord; ++i)
+      val[i] = pVal[i+offset]; // move whole word
+
+    // Adjust the top significant word for sign bit fill, if negative
+    if (isNegative())
+      if (bitsInWord < APINT_BITS_PER_WORD)
+        val[breakWord] |= ~0ULL << bitsInWord; // set high bits
+  } else {
+    // Shift the low order words
+    for (unsigned i = 0; i < breakWord; ++i) {
+      // This combines the shifted corresponding word with the low bits from
+      // the next word (shifted into this word's high bits).
+      val[i] = (pVal[i+offset] >> wordShift) |
+               (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift));
+    }
+
+    // Shift the break word. In this case there are no bits from the next word
+    // to include in this word.
+    val[breakWord] = pVal[breakWord+offset] >> wordShift;
+
+    // Deal with sign extension in the break word, and possibly the word before
+    // it.
+    if (isNegative()) {
+      if (wordShift > bitsInWord) {
+        if (breakWord > 0)
+          val[breakWord-1] |=
+            ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord));
+        val[breakWord] |= ~0ULL;
+      } else
+        val[breakWord] |= (~0ULL << (bitsInWord - wordShift));
+    }
+  }
+
+  // Remaining words are 0 or -1, just assign them.
+  uint64_t fillValue = (isNegative() ? -1ULL : 0);
+  for (unsigned i = breakWord+1; i < getNumWords(); ++i)
+    val[i] = fillValue;
+  APInt Result(val, BitWidth);
+  Result.clearUnusedBits();
+  return Result;
+}
+
+/// Logical right-shift this APInt by shiftAmt.
+/// @brief Logical right-shift function.
+APInt APInt::lshr(const APInt &shiftAmt) const {
+  return lshr((unsigned)shiftAmt.getLimitedValue(BitWidth));
+}
+
+/// Logical right-shift this APInt by shiftAmt.
+/// @brief Logical right-shift function.
+APInt APInt::lshr(unsigned shiftAmt) const {
+  if (isSingleWord()) {
+    if (shiftAmt >= BitWidth)
+      return APInt(BitWidth, 0);
+    else
+      return APInt(BitWidth, this->VAL >> shiftAmt);
+  }
+
+  // If all the bits were shifted out, the result is 0. This avoids issues
+  // with shifting by the size of the integer type, which produces undefined
+  // results. We define these "undefined results" to always be 0.
+  if (shiftAmt >= BitWidth)
+    return APInt(BitWidth, 0);
+
+  // If none of the bits are shifted out, the result is *this. This avoids
+  // issues with shifting by the size of the integer type, which produces
+  // undefined results in the code below. This is also an optimization.
+  if (shiftAmt == 0)
+    return *this;
+
+  // Create some space for the result.
+  uint64_t * val = new uint64_t[getNumWords()];
+
+  // If we are shifting less than a word, compute the shift with a simple carry
+  if (shiftAmt < APINT_BITS_PER_WORD) {
+    lshrNear(val, pVal, getNumWords(), shiftAmt);
+    APInt Result(val, BitWidth);
+    Result.clearUnusedBits();
+    return Result;
+  }
+
+  // Compute some values needed by the remaining shift algorithms
+  unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD;
+  unsigned offset = shiftAmt / APINT_BITS_PER_WORD;
+
+  // If we are shifting whole words, just move whole words
+  if (wordShift == 0) {
+    for (unsigned i = 0; i < getNumWords() - offset; ++i)
+      val[i] = pVal[i+offset];
+    for (unsigned i = getNumWords()-offset; i < getNumWords(); i++)
+      val[i] = 0;
+    APInt Result(val, BitWidth);
+    Result.clearUnusedBits();
+    return Result;
+  }
+
+  // Shift the low order words
+  unsigned breakWord = getNumWords() - offset -1;
+  for (unsigned i = 0; i < breakWord; ++i)
+    val[i] = (pVal[i+offset] >> wordShift) |
+             (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift));
+  // Shift the break word.
+  val[breakWord] = pVal[breakWord+offset] >> wordShift;
+
+  // Remaining words are 0
+  for (unsigned i = breakWord+1; i < getNumWords(); ++i)
+    val[i] = 0;
+  APInt Result(val, BitWidth);
+  Result.clearUnusedBits();
+  return Result;
+}
+
+/// Left-shift this APInt by shiftAmt.
+/// @brief Left-shift function.
+APInt APInt::shl(const APInt &shiftAmt) const {
+  // It's undefined behavior in C to shift by BitWidth or greater.
+  return shl((unsigned)shiftAmt.getLimitedValue(BitWidth));
+}
+
+APInt APInt::shlSlowCase(unsigned shiftAmt) const {
+  // If all the bits were shifted out, the result is 0. This avoids issues
+  // with shifting by the size of the integer type, which produces undefined
+  // results. We define these "undefined results" to always be 0.
+  if (shiftAmt == BitWidth)
+    return APInt(BitWidth, 0);
+
+  // If none of the bits are shifted out, the result is *this. This avoids a
+  // lshr by the words size in the loop below which can produce incorrect
+  // results. It also avoids the expensive computation below for a common case.
+  if (shiftAmt == 0)
+    return *this;
+
+  // Create some space for the result.
+  uint64_t * val = new uint64_t[getNumWords()];
+
+  // If we are shifting less than a word, do it the easy way
+  if (shiftAmt < APINT_BITS_PER_WORD) {
+    uint64_t carry = 0;
+    for (unsigned i = 0; i < getNumWords(); i++) {
+      val[i] = pVal[i] << shiftAmt | carry;
+      carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt);
+    }
+    APInt Result(val, BitWidth);
+    Result.clearUnusedBits();
+    return Result;
+  }
+
+  // Compute some values needed by the remaining shift algorithms
+  unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD;
+  unsigned offset = shiftAmt / APINT_BITS_PER_WORD;
+
+  // If we are shifting whole words, just move whole words
+  if (wordShift == 0) {
+    for (unsigned i = 0; i < offset; i++)
+      val[i] = 0;
+    for (unsigned i = offset; i < getNumWords(); i++)
+      val[i] = pVal[i-offset];
+    APInt Result(val, BitWidth);
+    Result.clearUnusedBits();
+    return Result;
+  }
+
+  // Copy whole words from this to Result.
+  unsigned i = getNumWords() - 1;
+  for (; i > offset; --i)
+    val[i] = pVal[i-offset] << wordShift |
+             pVal[i-offset-1] >> (APINT_BITS_PER_WORD - wordShift);
+  val[offset] = pVal[0] << wordShift;
+  for (i = 0; i < offset; ++i)
+    val[i] = 0;
+  APInt Result(val, BitWidth);
+  Result.clearUnusedBits();
+  return Result;
+}
+
+APInt APInt::rotl(const APInt &rotateAmt) const {
+  return rotl((unsigned)rotateAmt.getLimitedValue(BitWidth));
+}
+
+APInt APInt::rotl(unsigned rotateAmt) const {
+  rotateAmt %= BitWidth;
+  if (rotateAmt == 0)
+    return *this;
+  return shl(rotateAmt) | lshr(BitWidth - rotateAmt);
+}
+
+APInt APInt::rotr(const APInt &rotateAmt) const {
+  return rotr((unsigned)rotateAmt.getLimitedValue(BitWidth));
+}
+
+APInt APInt::rotr(unsigned rotateAmt) const {
+  rotateAmt %= BitWidth;
+  if (rotateAmt == 0)
+    return *this;
+  return lshr(rotateAmt) | shl(BitWidth - rotateAmt);
+}
+
+// Square Root - this method computes and returns the square root of "this".
+// Three mechanisms are used for computation. For small values (<= 5 bits),
+// a table lookup is done. This gets some performance for common cases. For
+// values using less than 52 bits, the value is converted to double and then
+// the libc sqrt function is called. The result is rounded and then converted
+// back to a uint64_t which is then used to construct the result. Finally,
+// the Babylonian method for computing square roots is used.
+APInt APInt::sqrt() const {
+
+  // Determine the magnitude of the value.
+  unsigned magnitude = getActiveBits();
+
+  // Use a fast table for some small values. This also gets rid of some
+  // rounding errors in libc sqrt for small values.
+  if (magnitude <= 5) {
+    static const uint8_t results[32] = {
+      /*     0 */ 0,
+      /*  1- 2 */ 1, 1,
+      /*  3- 6 */ 2, 2, 2, 2,
+      /*  7-12 */ 3, 3, 3, 3, 3, 3,
+      /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
+      /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+      /*    31 */ 6
+    };
+    return APInt(BitWidth, results[ (isSingleWord() ? VAL : pVal[0]) ]);
+  }
+
+  // If the magnitude of the value fits in less than 52 bits (the precision of
+  // an IEEE double precision floating point value), then we can use the
+  // libc sqrt function which will probably use a hardware sqrt computation.
+  // This should be faster than the algorithm below.
+  if (magnitude < 52) {
+    return APInt(BitWidth,
+                 uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0])))));
+  }
+
+  // Okay, all the short cuts are exhausted. We must compute it. The following
+  // is a classical Babylonian method for computing the square root. This code
+  // was adapted to APInt from a wikipedia article on such computations.
+  // See http://www.wikipedia.org/ and go to the page named
+  // Calculate_an_integer_square_root.
+  unsigned nbits = BitWidth, i = 4;
+  APInt testy(BitWidth, 16);
+  APInt x_old(BitWidth, 1);
+  APInt x_new(BitWidth, 0);
+  APInt two(BitWidth, 2);
+
+  // Select a good starting value using binary logarithms.
+  for (;; i += 2, testy = testy.shl(2))
+    if (i >= nbits || this->ule(testy)) {
+      x_old = x_old.shl(i / 2);
+      break;
+    }
+
+  // Use the Babylonian method to arrive at the integer square root:
+  for (;;) {
+    x_new = (this->udiv(x_old) + x_old).udiv(two);
+    if (x_old.ule(x_new))
+      break;
+    x_old = x_new;
+  }
+
+  // Make sure we return the closest approximation
+  // NOTE: The rounding calculation below is correct. It will produce an
+  // off-by-one discrepancy with results from pari/gp. That discrepancy has been
+  // determined to be a rounding issue with pari/gp as it begins to use a
+  // floating point representation after 192 bits. There are no discrepancies
+  // between this algorithm and pari/gp for bit widths < 192 bits.
+  APInt square(x_old * x_old);
+  APInt nextSquare((x_old + 1) * (x_old +1));
+  if (this->ult(square))
+    return x_old;
+  assert(this->ule(nextSquare) && "Error in APInt::sqrt computation");
+  APInt midpoint((nextSquare - square).udiv(two));
+  APInt offset(*this - square);
+  if (offset.ult(midpoint))
+    return x_old;
+  return x_old + 1;
+}
+
+/// Computes the multiplicative inverse of this APInt for a given modulo. The
+/// iterative extended Euclidean algorithm is used to solve for this value,
+/// however we simplify it to speed up calculating only the inverse, and take
+/// advantage of div+rem calculations. We also use some tricks to avoid copying
+/// (potentially large) APInts around.
+APInt APInt::multiplicativeInverse(const APInt& modulo) const {
+  assert(ult(modulo) && "This APInt must be smaller than the modulo");
+
+  // Using the properties listed at the following web page (accessed 06/21/08):
+  //   http://www.numbertheory.org/php/euclid.html
+  // (especially the properties numbered 3, 4 and 9) it can be proved that
+  // BitWidth bits suffice for all the computations in the algorithm implemented
+  // below. More precisely, this number of bits suffice if the multiplicative
+  // inverse exists, but may not suffice for the general extended Euclidean
+  // algorithm.
+
+  APInt r[2] = { modulo, *this };
+  APInt t[2] = { APInt(BitWidth, 0), APInt(BitWidth, 1) };
+  APInt q(BitWidth, 0);
+
+  unsigned i;
+  for (i = 0; r[i^1] != 0; i ^= 1) {
+    // An overview of the math without the confusing bit-flipping:
+    // q = r[i-2] / r[i-1]
+    // r[i] = r[i-2] % r[i-1]
+    // t[i] = t[i-2] - t[i-1] * q
+    udivrem(r[i], r[i^1], q, r[i]);
+    t[i] -= t[i^1] * q;
+  }
+
+  // If this APInt and the modulo are not coprime, there is no multiplicative
+  // inverse, so return 0. We check this by looking at the next-to-last
+  // remainder, which is the gcd(*this,modulo) as calculated by the Euclidean
+  // algorithm.
+  if (r[i] != 1)
+    return APInt(BitWidth, 0);
+
+  // The next-to-last t is the multiplicative inverse.  However, we are
+  // interested in a positive inverse. Calcuate a positive one from a negative
+  // one if necessary. A simple addition of the modulo suffices because
+  // abs(t[i]) is known to be less than *this/2 (see the link above).
+  return t[i].isNegative() ? t[i] + modulo : t[i];
+}
+
+/// Calculate the magic numbers required to implement a signed integer division
+/// by a constant as a sequence of multiplies, adds and shifts.  Requires that
+/// the divisor not be 0, 1, or -1.  Taken from "Hacker's Delight", Henry S.
+/// Warren, Jr., chapter 10.
+APInt::ms APInt::magic() const {
+  const APInt& d = *this;
+  unsigned p;
+  APInt ad, anc, delta, q1, r1, q2, r2, t;
+  APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
+  struct ms mag;
+
+  ad = d.abs();
+  t = signedMin + (d.lshr(d.getBitWidth() - 1));
+  anc = t - 1 - t.urem(ad);   // absolute value of nc
+  p = d.getBitWidth() - 1;    // initialize p
+  q1 = signedMin.udiv(anc);   // initialize q1 = 2p/abs(nc)
+  r1 = signedMin - q1*anc;    // initialize r1 = rem(2p,abs(nc))
+  q2 = signedMin.udiv(ad);    // initialize q2 = 2p/abs(d)
+  r2 = signedMin - q2*ad;     // initialize r2 = rem(2p,abs(d))
+  do {
+    p = p + 1;
+    q1 = q1<<1;          // update q1 = 2p/abs(nc)
+    r1 = r1<<1;          // update r1 = rem(2p/abs(nc))
+    if (r1.uge(anc)) {  // must be unsigned comparison
+      q1 = q1 + 1;
+      r1 = r1 - anc;
+    }
+    q2 = q2<<1;          // update q2 = 2p/abs(d)
+    r2 = r2<<1;          // update r2 = rem(2p/abs(d))
+    if (r2.uge(ad)) {   // must be unsigned comparison
+      q2 = q2 + 1;
+      r2 = r2 - ad;
+    }
+    delta = ad - r2;
+  } while (q1.ult(delta) || (q1 == delta && r1 == 0));
+
+  mag.m = q2 + 1;
+  if (d.isNegative()) mag.m = -mag.m;   // resulting magic number
+  mag.s = p - d.getBitWidth();          // resulting shift
+  return mag;
+}
+
+/// Calculate the magic numbers required to implement an unsigned integer
+/// division by a constant as a sequence of multiplies, adds and shifts.
+/// Requires that the divisor not be 0.  Taken from "Hacker's Delight", Henry
+/// S. Warren, Jr., chapter 10.
+/// LeadingZeros can be used to simplify the calculation if the upper bits
+/// of the divided value are known zero.
+APInt::mu APInt::magicu(unsigned LeadingZeros) const {
+  const APInt& d = *this;
+  unsigned p;
+  APInt nc, delta, q1, r1, q2, r2;
+  struct mu magu;
+  magu.a = 0;               // initialize "add" indicator
+  APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()).lshr(LeadingZeros);
+  APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
+  APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth());
+
+  nc = allOnes - (allOnes - d).urem(d);
+  p = d.getBitWidth() - 1;  // initialize p
+  q1 = signedMin.udiv(nc);  // initialize q1 = 2p/nc
+  r1 = signedMin - q1*nc;   // initialize r1 = rem(2p,nc)
+  q2 = signedMax.udiv(d);   // initialize q2 = (2p-1)/d
+  r2 = signedMax - q2*d;    // initialize r2 = rem((2p-1),d)
+  do {
+    p = p + 1;
+    if (r1.uge(nc - r1)) {
+      q1 = q1 + q1 + 1;  // update q1
+      r1 = r1 + r1 - nc; // update r1
+    }
+    else {
+      q1 = q1+q1; // update q1
+      r1 = r1+r1; // update r1
+    }
+    if ((r2 + 1).uge(d - r2)) {
+      if (q2.uge(signedMax)) magu.a = 1;
+      q2 = q2+q2 + 1;     // update q2
+      r2 = r2+r2 + 1 - d; // update r2
+    }
+    else {
+      if (q2.uge(signedMin)) magu.a = 1;
+      q2 = q2+q2;     // update q2
+      r2 = r2+r2 + 1; // update r2
+    }
+    delta = d - 1 - r2;
+  } while (p < d.getBitWidth()*2 &&
+           (q1.ult(delta) || (q1 == delta && r1 == 0)));
+  magu.m = q2 + 1; // resulting magic number
+  magu.s = p - d.getBitWidth();  // resulting shift
+  return magu;
+}
+
+/// Implementation of Knuth's Algorithm D (Division of nonnegative integers)
+/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The
+/// variables here have the same names as in the algorithm. Comments explain
+/// the algorithm and any deviation from it.
+static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
+                     unsigned m, unsigned n) {
+  assert(u && "Must provide dividend");
+  assert(v && "Must provide divisor");
+  assert(q && "Must provide quotient");
+  assert(u != v && u != q && v != q && "Must use different memory");
+  assert(n>1 && "n must be > 1");
+
+  // b denotes the base of the number system. In our case b is 2^32.
+  const uint64_t b = uint64_t(1) << 32;
+
+  DEBUG(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n');
+  DEBUG(dbgs() << "KnuthDiv: original:");
+  DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
+  DEBUG(dbgs() << " by");
+  DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]);
+  DEBUG(dbgs() << '\n');
+  // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of
+  // u and v by d. Note that we have taken Knuth's advice here to use a power
+  // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of
+  // 2 allows us to shift instead of multiply and it is easy to determine the
+  // shift amount from the leading zeros.  We are basically normalizing the u
+  // and v so that its high bits are shifted to the top of v's range without
+  // overflow. Note that this can require an extra word in u so that u must
+  // be of length m+n+1.
+  unsigned shift = countLeadingZeros(v[n-1]);
+  unsigned v_carry = 0;
+  unsigned u_carry = 0;
+  if (shift) {
+    for (unsigned i = 0; i < m+n; ++i) {
+      unsigned u_tmp = u[i] >> (32 - shift);
+      u[i] = (u[i] << shift) | u_carry;
+      u_carry = u_tmp;
+    }
+    for (unsigned i = 0; i < n; ++i) {
+      unsigned v_tmp = v[i] >> (32 - shift);
+      v[i] = (v[i] << shift) | v_carry;
+      v_carry = v_tmp;
+    }
+  }
+  u[m+n] = u_carry;
+
+  DEBUG(dbgs() << "KnuthDiv:   normal:");
+  DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
+  DEBUG(dbgs() << " by");
+  DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]);
+  DEBUG(dbgs() << '\n');
+
+  // D2. [Initialize j.]  Set j to m. This is the loop counter over the places.
+  int j = m;
+  do {
+    DEBUG(dbgs() << "KnuthDiv: quotient digit #" << j << '\n');
+    // D3. [Calculate q'.].
+    //     Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q')
+    //     Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r')
+    // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease
+    // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test
+    // on v[n-2] determines at high speed most of the cases in which the trial
+    // value qp is one too large, and it eliminates all cases where qp is two
+    // too large.
+    uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]);
+    DEBUG(dbgs() << "KnuthDiv: dividend == " << dividend << '\n');
+    uint64_t qp = dividend / v[n-1];
+    uint64_t rp = dividend % v[n-1];
+    if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) {
+      qp--;
+      rp += v[n-1];
+      if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2]))
+        qp--;
+    }
+    DEBUG(dbgs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n');
+
+    // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with
+    // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
+    // consists of a simple multiplication by a one-place number, combined with
+    // a subtraction.
+    // The digits (u[j+n]...u[j]) should be kept positive; if the result of
+    // this step is actually negative, (u[j+n]...u[j]) should be left as the
+    // true value plus b**(n+1), namely as the b's complement of
+    // the true value, and a "borrow" to the left should be remembered.
+    int64_t borrow = 0;
+    for (unsigned i = 0; i < n; ++i) {
+      uint64_t p = uint64_t(qp) * uint64_t(v[i]);
+      int64_t subres = int64_t(u[j+i]) - borrow - (unsigned)p;
+      u[j+i] = (unsigned)subres;
+      borrow = (p >> 32) - (subres >> 32);
+      DEBUG(dbgs() << "KnuthDiv: u[j+i] = " << u[j+i]
+                   << ", borrow = " << borrow << '\n');
+    }
+    bool isNeg = u[j+n] < borrow;
+    u[j+n] -= (unsigned)borrow;
+
+    DEBUG(dbgs() << "KnuthDiv: after subtraction:");
+    DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
+    DEBUG(dbgs() << '\n');
+
+    // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was
+    // negative, go to step D6; otherwise go on to step D7.
+    q[j] = (unsigned)qp;
+    if (isNeg) {
+      // D6. [Add back]. The probability that this step is necessary is very
+      // small, on the order of only 2/b. Make sure that test data accounts for
+      // this possibility. Decrease q[j] by 1
+      q[j]--;
+      // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]).
+      // A carry will occur to the left of u[j+n], and it should be ignored
+      // since it cancels with the borrow that occurred in D4.
+      bool carry = false;
+      for (unsigned i = 0; i < n; i++) {
+        unsigned limit = std::min(u[j+i],v[i]);
+        u[j+i] += v[i] + carry;
+        carry = u[j+i] < limit || (carry && u[j+i] == limit);
+      }
+      u[j+n] += carry;
+    }
+    DEBUG(dbgs() << "KnuthDiv: after correction:");
+    DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
+    DEBUG(dbgs() << "\nKnuthDiv: digit result = " << q[j] << '\n');
+
+  // D7. [Loop on j.]  Decrease j by one. Now if j >= 0, go back to D3.
+  } while (--j >= 0);
+
+  DEBUG(dbgs() << "KnuthDiv: quotient:");
+  DEBUG(for (int i = m; i >=0; i--) dbgs() <<" " << q[i]);
+  DEBUG(dbgs() << '\n');
+
+  // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired
+  // remainder may be obtained by dividing u[...] by d. If r is non-null we
+  // compute the remainder (urem uses this).
+  if (r) {
+    // The value d is expressed by the "shift" value above since we avoided
+    // multiplication by d by using a shift left. So, all we have to do is
+    // shift right here. In order to mak
+    if (shift) {
+      unsigned carry = 0;
+      DEBUG(dbgs() << "KnuthDiv: remainder:");
+      for (int i = n-1; i >= 0; i--) {
+        r[i] = (u[i] >> shift) | carry;
+        carry = u[i] << (32 - shift);
+        DEBUG(dbgs() << " " << r[i]);
+      }
+    } else {
+      for (int i = n-1; i >= 0; i--) {
+        r[i] = u[i];
+        DEBUG(dbgs() << " " << r[i]);
+      }
+    }
+    DEBUG(dbgs() << '\n');
+  }
+  DEBUG(dbgs() << '\n');
+}
+
+void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
+                   unsigned rhsWords, APInt *Quotient, APInt *Remainder) {
+  assert(lhsWords >= rhsWords && "Fractional result");
+
+  // First, compose the values into an array of 32-bit words instead of
+  // 64-bit words. This is a necessity of both the "short division" algorithm
+  // and the Knuth "classical algorithm" which requires there to be native
+  // operations for +, -, and * on an m bit value with an m*2 bit result. We
+  // can't use 64-bit operands here because we don't have native results of
+  // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't
+  // work on large-endian machines.
+  uint64_t mask = ~0ull >> (sizeof(unsigned)*CHAR_BIT);
+  unsigned n = rhsWords * 2;
+  unsigned m = (lhsWords * 2) - n;
+
+  // Allocate space for the temporary values we need either on the stack, if
+  // it will fit, or on the heap if it won't.
+  unsigned SPACE[128];
+  unsigned *U = nullptr;
+  unsigned *V = nullptr;
+  unsigned *Q = nullptr;
+  unsigned *R = nullptr;
+  if ((Remainder?4:3)*n+2*m+1 <= 128) {
+    U = &SPACE[0];
+    V = &SPACE[m+n+1];
+    Q = &SPACE[(m+n+1) + n];
+    if (Remainder)
+      R = &SPACE[(m+n+1) + n + (m+n)];
+  } else {
+    U = new unsigned[m + n + 1];
+    V = new unsigned[n];
+    Q = new unsigned[m+n];
+    if (Remainder)
+      R = new unsigned[n];
+  }
+
+  // Initialize the dividend
+  memset(U, 0, (m+n+1)*sizeof(unsigned));
+  for (unsigned i = 0; i < lhsWords; ++i) {
+    uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]);
+    U[i * 2] = (unsigned)(tmp & mask);
+    U[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT));
+  }
+  U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm.
+
+  // Initialize the divisor
+  memset(V, 0, (n)*sizeof(unsigned));
+  for (unsigned i = 0; i < rhsWords; ++i) {
+    uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]);
+    V[i * 2] = (unsigned)(tmp & mask);
+    V[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT));
+  }
+
+  // initialize the quotient and remainder
+  memset(Q, 0, (m+n) * sizeof(unsigned));
+  if (Remainder)
+    memset(R, 0, n * sizeof(unsigned));
+
+  // Now, adjust m and n for the Knuth division. n is the number of words in
+  // the divisor. m is the number of words by which the dividend exceeds the
+  // divisor (i.e. m+n is the length of the dividend). These sizes must not
+  // contain any zero words or the Knuth algorithm fails.
+  for (unsigned i = n; i > 0 && V[i-1] == 0; i--) {
+    n--;
+    m++;
+  }
+  for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--)
+    m--;
+
+  // If we're left with only a single word for the divisor, Knuth doesn't work
+  // so we implement the short division algorithm here. This is much simpler
+  // and faster because we are certain that we can divide a 64-bit quantity
+  // by a 32-bit quantity at hardware speed and short division is simply a
+  // series of such operations. This is just like doing short division but we
+  // are using base 2^32 instead of base 10.
+  assert(n != 0 && "Divide by zero?");
+  if (n == 1) {
+    unsigned divisor = V[0];
+    unsigned remainder = 0;
+    for (int i = m+n-1; i >= 0; i--) {
+      uint64_t partial_dividend = uint64_t(remainder) << 32 | U[i];
+      if (partial_dividend == 0) {
+        Q[i] = 0;
+        remainder = 0;
+      } else if (partial_dividend < divisor) {
+        Q[i] = 0;
+        remainder = (unsigned)partial_dividend;
+      } else if (partial_dividend == divisor) {
+        Q[i] = 1;
+        remainder = 0;
+      } else {
+        Q[i] = (unsigned)(partial_dividend / divisor);
+        remainder = (unsigned)(partial_dividend - (Q[i] * divisor));
+      }
+    }
+    if (R)
+      R[0] = remainder;
+  } else {
+    // Now we're ready to invoke the Knuth classical divide algorithm. In this
+    // case n > 1.
+    KnuthDiv(U, V, Q, R, m, n);
+  }
+
+  // If the caller wants the quotient
+  if (Quotient) {
+    // Set up the Quotient value's memory.
+    if (Quotient->BitWidth != LHS.BitWidth) {
+      if (Quotient->isSingleWord())
+        Quotient->VAL = 0;
+      else
+        delete [] Quotient->pVal;
+      Quotient->BitWidth = LHS.BitWidth;
+      if (!Quotient->isSingleWord())
+        Quotient->pVal = getClearedMemory(Quotient->getNumWords());
+    } else
+      Quotient->clearAllBits();
+
+    // The quotient is in Q. Reconstitute the quotient into Quotient's low
+    // order words.
+    // This case is currently dead as all users of divide() handle trivial cases
+    // earlier.
+    if (lhsWords == 1) {
+      uint64_t tmp =
+        uint64_t(Q[0]) | (uint64_t(Q[1]) << (APINT_BITS_PER_WORD / 2));
+      if (Quotient->isSingleWord())
+        Quotient->VAL = tmp;
+      else
+        Quotient->pVal[0] = tmp;
+    } else {
+      assert(!Quotient->isSingleWord() && "Quotient APInt not large enough");
+      for (unsigned i = 0; i < lhsWords; ++i)
+        Quotient->pVal[i] =
+          uint64_t(Q[i*2]) | (uint64_t(Q[i*2+1]) << (APINT_BITS_PER_WORD / 2));
+    }
+  }
+
+  // If the caller wants the remainder
+  if (Remainder) {
+    // Set up the Remainder value's memory.
+    if (Remainder->BitWidth != RHS.BitWidth) {
+      if (Remainder->isSingleWord())
+        Remainder->VAL = 0;
+      else
+        delete [] Remainder->pVal;
+      Remainder->BitWidth = RHS.BitWidth;
+      if (!Remainder->isSingleWord())
+        Remainder->pVal = getClearedMemory(Remainder->getNumWords());
+    } else
+      Remainder->clearAllBits();
+
+    // The remainder is in R. Reconstitute the remainder into Remainder's low
+    // order words.
+    if (rhsWords == 1) {
+      uint64_t tmp =
+        uint64_t(R[0]) | (uint64_t(R[1]) << (APINT_BITS_PER_WORD / 2));
+      if (Remainder->isSingleWord())
+        Remainder->VAL = tmp;
+      else
+        Remainder->pVal[0] = tmp;
+    } else {
+      assert(!Remainder->isSingleWord() && "Remainder APInt not large enough");
+      for (unsigned i = 0; i < rhsWords; ++i)
+        Remainder->pVal[i] =
+          uint64_t(R[i*2]) | (uint64_t(R[i*2+1]) << (APINT_BITS_PER_WORD / 2));
+    }
+  }
+
+  // Clean up the memory we allocated.
+  if (U != &SPACE[0]) {
+    delete [] U;
+    delete [] V;
+    delete [] Q;
+    delete [] R;
+  }
+}
+
+APInt APInt::udiv(const APInt& RHS) const {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+
+  // First, deal with the easy case
+  if (isSingleWord()) {
+    assert(RHS.VAL != 0 && "Divide by zero?");
+    return APInt(BitWidth, VAL / RHS.VAL);
+  }
+
+  // Get some facts about the LHS and RHS number of bits and words
+  unsigned rhsBits = RHS.getActiveBits();
+  unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
+  assert(rhsWords && "Divided by zero???");
+  unsigned lhsBits = this->getActiveBits();
+  unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1);
+
+  // Deal with some degenerate cases
+  if (!lhsWords)
+    // 0 / X ===> 0
+    return APInt(BitWidth, 0);
+  else if (lhsWords < rhsWords || this->ult(RHS)) {
+    // X / Y ===> 0, iff X < Y
+    return APInt(BitWidth, 0);
+  } else if (*this == RHS) {
+    // X / X ===> 1
+    return APInt(BitWidth, 1);
+  } else if (lhsWords == 1 && rhsWords == 1) {
+    // All high words are zero, just use native divide
+    return APInt(BitWidth, this->pVal[0] / RHS.pVal[0]);
+  }
+
+  // We have to compute it the hard way. Invoke the Knuth divide algorithm.
+  APInt Quotient(1,0); // to hold result.
+  divide(*this, lhsWords, RHS, rhsWords, &Quotient, nullptr);
+  return Quotient;
+}
+
+APInt APInt::sdiv(const APInt &RHS) const {
+  if (isNegative()) {
+    if (RHS.isNegative())
+      return (-(*this)).udiv(-RHS);
+    return -((-(*this)).udiv(RHS));
+  }
+  if (RHS.isNegative())
+    return -(this->udiv(-RHS));
+  return this->udiv(RHS);
+}
+
+APInt APInt::urem(const APInt& RHS) const {
+  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+  if (isSingleWord()) {
+    assert(RHS.VAL != 0 && "Remainder by zero?");
+    return APInt(BitWidth, VAL % RHS.VAL);
+  }
+
+  // Get some facts about the LHS
+  unsigned lhsBits = getActiveBits();
+  unsigned lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1);
+
+  // Get some facts about the RHS
+  unsigned rhsBits = RHS.getActiveBits();
+  unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
+  assert(rhsWords && "Performing remainder operation by zero ???");
+
+  // Check the degenerate cases
+  if (lhsWords == 0) {
+    // 0 % Y ===> 0
+    return APInt(BitWidth, 0);
+  } else if (lhsWords < rhsWords || this->ult(RHS)) {
+    // X % Y ===> X, iff X < Y
+    return *this;
+  } else if (*this == RHS) {
+    // X % X == 0;
+    return APInt(BitWidth, 0);
+  } else if (lhsWords == 1) {
+    // All high words are zero, just use native remainder
+    return APInt(BitWidth, pVal[0] % RHS.pVal[0]);
+  }
+
+  // We have to compute it the hard way. Invoke the Knuth divide algorithm.
+  APInt Remainder(1,0);
+  divide(*this, lhsWords, RHS, rhsWords, nullptr, &Remainder);
+  return Remainder;
+}
+
+APInt APInt::srem(const APInt &RHS) const {
+  if (isNegative()) {
+    if (RHS.isNegative())
+      return -((-(*this)).urem(-RHS));
+    return -((-(*this)).urem(RHS));
+  }
+  if (RHS.isNegative())
+    return this->urem(-RHS);
+  return this->urem(RHS);
+}
+
+void APInt::udivrem(const APInt &LHS, const APInt &RHS,
+                    APInt &Quotient, APInt &Remainder) {
+  assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same");
+
+  // First, deal with the easy case
+  if (LHS.isSingleWord()) {
+    assert(RHS.VAL != 0 && "Divide by zero?");
+    uint64_t QuotVal = LHS.VAL / RHS.VAL;
+    uint64_t RemVal = LHS.VAL % RHS.VAL;
+    Quotient = APInt(LHS.BitWidth, QuotVal);
+    Remainder = APInt(LHS.BitWidth, RemVal);
+    return;
+  }
+
+  // Get some size facts about the dividend and divisor
+  unsigned lhsBits  = LHS.getActiveBits();
+  unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1);
+  unsigned rhsBits  = RHS.getActiveBits();
+  unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
+
+  // Check the degenerate cases
+  if (lhsWords == 0) {
+    Quotient = 0;                // 0 / Y ===> 0
+    Remainder = 0;               // 0 % Y ===> 0
+    return;
+  }
+
+  if (lhsWords < rhsWords || LHS.ult(RHS)) {
+    Remainder = LHS;            // X % Y ===> X, iff X < Y
+    Quotient = 0;               // X / Y ===> 0, iff X < Y
+    return;
+  }
+
+  if (LHS == RHS) {
+    Quotient  = 1;              // X / X ===> 1
+    Remainder = 0;              // X % X ===> 0;
+    return;
+  }
+
+  if (lhsWords == 1 && rhsWords == 1) {
+    // There is only one word to consider so use the native versions.
+    uint64_t lhsValue = LHS.isSingleWord() ? LHS.VAL : LHS.pVal[0];
+    uint64_t rhsValue = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
+    Quotient = APInt(LHS.getBitWidth(), lhsValue / rhsValue);
+    Remainder = APInt(LHS.getBitWidth(), lhsValue % rhsValue);
+    return;
+  }
+
+  // Okay, lets do it the long way
+  divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder);
+}
+
+void APInt::sdivrem(const APInt &LHS, const APInt &RHS,
+                    APInt &Quotient, APInt &Remainder) {
+  if (LHS.isNegative()) {
+    if (RHS.isNegative())
+      APInt::udivrem(-LHS, -RHS, Quotient, Remainder);
+    else {
+      APInt::udivrem(-LHS, RHS, Quotient, Remainder);
+      Quotient = -Quotient;
+    }
+    Remainder = -Remainder;
+  } else if (RHS.isNegative()) {
+    APInt::udivrem(LHS, -RHS, Quotient, Remainder);
+    Quotient = -Quotient;
+  } else {
+    APInt::udivrem(LHS, RHS, Quotient, Remainder);
+  }
+}
+
+APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this+RHS;
+  Overflow = isNonNegative() == RHS.isNonNegative() &&
+             Res.isNonNegative() != isNonNegative();
+  return Res;
+}
+
+APInt APInt::uadd_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this+RHS;
+  Overflow = Res.ult(RHS);
+  return Res;
+}
+
+APInt APInt::ssub_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this - RHS;
+  Overflow = isNonNegative() != RHS.isNonNegative() &&
+             Res.isNonNegative() != isNonNegative();
+  return Res;
+}
+
+APInt APInt::usub_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this-RHS;
+  Overflow = Res.ugt(*this);
+  return Res;
+}
+
+APInt APInt::sdiv_ov(const APInt &RHS, bool &Overflow) const {
+  // MININT/-1  -->  overflow.
+  Overflow = isMinSignedValue() && RHS.isAllOnesValue();
+  return sdiv(RHS);
+}
+
+APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this * RHS;
+  
+  if (*this != 0 && RHS != 0)
+    Overflow = Res.sdiv(RHS) != *this || Res.sdiv(*this) != RHS;
+  else
+    Overflow = false;
+  return Res;
+}
+
+APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this * RHS;
+
+  if (*this != 0 && RHS != 0)
+    Overflow = Res.udiv(RHS) != *this || Res.udiv(*this) != RHS;
+  else
+    Overflow = false;
+  return Res;
+}
+
+APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const {
+  Overflow = ShAmt.uge(getBitWidth());
+  if (Overflow)
+    return APInt(BitWidth, 0);
+
+  if (isNonNegative()) // Don't allow sign change.
+    Overflow = ShAmt.uge(countLeadingZeros());
+  else
+    Overflow = ShAmt.uge(countLeadingOnes());
+  
+  return *this << ShAmt;
+}
+
+APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const {
+  Overflow = ShAmt.uge(getBitWidth());
+  if (Overflow)
+    return APInt(BitWidth, 0);
+
+  Overflow = ShAmt.ugt(countLeadingZeros());
+
+  return *this << ShAmt;
+}
+
+
+
+
+void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
+  // Check our assumptions here
+  assert(!str.empty() && "Invalid string length");
+  assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || 
+          radix == 36) &&
+         "Radix should be 2, 8, 10, 16, or 36!");
+
+  StringRef::iterator p = str.begin();
+  size_t slen = str.size();
+  bool isNeg = *p == '-';
+  if (*p == '-' || *p == '+') {
+    p++;
+    slen--;
+    assert(slen && "String is only a sign, needs a value.");
+  }
+  assert((slen <= numbits || radix != 2) && "Insufficient bit width");
+  assert(((slen-1)*3 <= numbits || radix != 8) && "Insufficient bit width");
+  assert(((slen-1)*4 <= numbits || radix != 16) && "Insufficient bit width");
+  assert((((slen-1)*64)/22 <= numbits || radix != 10) &&
+         "Insufficient bit width");
+
+  // Allocate memory
+  if (!isSingleWord())
+    pVal = getClearedMemory(getNumWords());
+
+  // Figure out if we can shift instead of multiply
+  unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
+
+  // Set up an APInt for the digit to add outside the loop so we don't
+  // constantly construct/destruct it.
+  APInt apdigit(getBitWidth(), 0);
+  APInt apradix(getBitWidth(), radix);
+
+  // Enter digit traversal loop
+  for (StringRef::iterator e = str.end(); p != e; ++p) {
+    unsigned digit = getDigit(*p, radix);
+    assert(digit < radix && "Invalid character in digit string");
+
+    // Shift or multiply the value by the radix
+    if (slen > 1) {
+      if (shift)
+        *this <<= shift;
+      else
+        *this *= apradix;
+    }
+
+    // Add in the digit we just interpreted
+    if (apdigit.isSingleWord())
+      apdigit.VAL = digit;
+    else
+      apdigit.pVal[0] = digit;
+    *this += apdigit;
+  }
+  // If its negative, put it in two's complement form
+  if (isNeg) {
+    --(*this);
+    this->flipAllBits();
+  }
+}
+
+void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
+                     bool Signed, bool formatAsCLiteral) const {
+  assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 || 
+          Radix == 36) &&
+         "Radix should be 2, 8, 10, 16, or 36!");
+
+  const char *Prefix = "";
+  if (formatAsCLiteral) {
+    switch (Radix) {
+      case 2:
+        // Binary literals are a non-standard extension added in gcc 4.3:
+        // http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Binary-constants.html
+        Prefix = "0b";
+        break;
+      case 8:
+        Prefix = "0";
+        break;
+      case 10:
+        break; // No prefix
+      case 16:
+        Prefix = "0x";
+        break;
+      default:
+        llvm_unreachable("Invalid radix!");
+    }
+  }
+
+  // First, check for a zero value and just short circuit the logic below.
+  if (*this == 0) {
+    while (*Prefix) {
+      Str.push_back(*Prefix);
+      ++Prefix;
+    };
+    Str.push_back('0');
+    return;
+  }
+
+  static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+  if (isSingleWord()) {
+    char Buffer[65];
+    char *BufPtr = Buffer+65;
+
+    uint64_t N;
+    if (!Signed) {
+      N = getZExtValue();
+    } else {
+      int64_t I = getSExtValue();
+      if (I >= 0) {
+        N = I;
+      } else {
+        Str.push_back('-');
+        N = -(uint64_t)I;
+      }
+    }
+
+    while (*Prefix) {
+      Str.push_back(*Prefix);
+      ++Prefix;
+    };
+
+    while (N) {
+      *--BufPtr = Digits[N % Radix];
+      N /= Radix;
+    }
+    Str.append(BufPtr, Buffer+65);
+    return;
+  }
+
+  APInt Tmp(*this);
+
+  if (Signed && isNegative()) {
+    // They want to print the signed version and it is a negative value
+    // Flip the bits and add one to turn it into the equivalent positive
+    // value and put a '-' in the result.
+    Tmp.flipAllBits();
+    ++Tmp;
+    Str.push_back('-');
+  }
+
+  while (*Prefix) {
+    Str.push_back(*Prefix);
+    ++Prefix;
+  };
+
+  // We insert the digits backward, then reverse them to get the right order.
+  unsigned StartDig = Str.size();
+
+  // For the 2, 8 and 16 bit cases, we can just shift instead of divide
+  // because the number of bits per digit (1, 3 and 4 respectively) divides
+  // equaly.  We just shift until the value is zero.
+  if (Radix == 2 || Radix == 8 || Radix == 16) {
+    // Just shift tmp right for each digit width until it becomes zero
+    unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1));
+    unsigned MaskAmt = Radix - 1;
+
+    while (Tmp != 0) {
+      unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt;
+      Str.push_back(Digits[Digit]);
+      Tmp = Tmp.lshr(ShiftAmt);
+    }
+  } else {
+    APInt divisor(Radix == 10? 4 : 8, Radix);
+    while (Tmp != 0) {
+      APInt APdigit(1, 0);
+      APInt tmp2(Tmp.getBitWidth(), 0);
+      divide(Tmp, Tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2,
+             &APdigit);
+      unsigned Digit = (unsigned)APdigit.getZExtValue();
+      assert(Digit < Radix && "divide failed");
+      Str.push_back(Digits[Digit]);
+      Tmp = tmp2;
+    }
+  }
+
+  // Reverse the digits before returning.
+  std::reverse(Str.begin()+StartDig, Str.end());
+}
+
+/// Returns the APInt as a std::string. Note that this is an inefficient method.
+/// It is better to pass in a SmallVector/SmallString to the methods above.
+std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const {
+  SmallString<40> S;
+  toString(S, Radix, Signed, /* formatAsCLiteral = */false);
+  return S.str();
+}
+
+
+LLVM_DUMP_METHOD void APInt::dump() const {
+  SmallString<40> S, U;
+  this->toStringUnsigned(U);
+  this->toStringSigned(S);
+  dbgs() << "APInt(" << BitWidth << "b, "
+         << U << "u " << S << "s)";
+}
+
+void APInt::print(raw_ostream &OS, bool isSigned) const {
+  SmallString<40> S;
+  this->toString(S, 10, isSigned, /* formatAsCLiteral = */false);
+  OS << S;
+}
+
+// This implements a variety of operations on a representation of
+// arbitrary precision, two's-complement, bignum integer values.
+
+// Assumed by lowHalf, highHalf, partMSB and partLSB.  A fairly safe
+// and unrestricting assumption.
+static_assert(integerPartWidth % 2 == 0, "Part width must be divisible by 2!");
+
+/* Some handy functions local to this file.  */
+namespace {
+
+  /* Returns the integer part with the least significant BITS set.
+     BITS cannot be zero.  */
+  static inline integerPart
+  lowBitMask(unsigned int bits)
+  {
+    assert(bits != 0 && bits <= integerPartWidth);
+
+    return ~(integerPart) 0 >> (integerPartWidth - bits);
+  }
+
+  /* Returns the value of the lower half of PART.  */
+  static inline integerPart
+  lowHalf(integerPart part)
+  {
+    return part & lowBitMask(integerPartWidth / 2);
+  }
+
+  /* Returns the value of the upper half of PART.  */
+  static inline integerPart
+  highHalf(integerPart part)
+  {
+    return part >> (integerPartWidth / 2);
+  }
+
+  /* Returns the bit number of the most significant set bit of a part.
+     If the input number has no bits set -1U is returned.  */
+  static unsigned int
+  partMSB(integerPart value)
+  {
+    return findLastSet(value, ZB_Max);
+  }
+
+  /* Returns the bit number of the least significant set bit of a
+     part.  If the input number has no bits set -1U is returned.  */
+  static unsigned int
+  partLSB(integerPart value)
+  {
+    return findFirstSet(value, ZB_Max);
+  }
+}
+
+/* Sets the least significant part of a bignum to the input value, and
+   zeroes out higher parts.  */
+void
+APInt::tcSet(integerPart *dst, integerPart part, unsigned int parts)
+{
+  unsigned int i;
+
+  assert(parts > 0);
+
+  dst[0] = part;
+  for (i = 1; i < parts; i++)
+    dst[i] = 0;
+}
+
+/* Assign one bignum to another.  */
+void
+APInt::tcAssign(integerPart *dst, const integerPart *src, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    dst[i] = src[i];
+}
+
+/* Returns true if a bignum is zero, false otherwise.  */
+bool
+APInt::tcIsZero(const integerPart *src, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    if (src[i])
+      return false;
+
+  return true;
+}
+
+/* Extract the given bit of a bignum; returns 0 or 1.  */
+int
+APInt::tcExtractBit(const integerPart *parts, unsigned int bit)
+{
+  return (parts[bit / integerPartWidth] &
+          ((integerPart) 1 << bit % integerPartWidth)) != 0;
+}
+
+/* Set the given bit of a bignum. */
+void
+APInt::tcSetBit(integerPart *parts, unsigned int bit)
+{
+  parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth);
+}
+
+/* Clears the given bit of a bignum. */
+void
+APInt::tcClearBit(integerPart *parts, unsigned int bit)
+{
+  parts[bit / integerPartWidth] &=
+    ~((integerPart) 1 << (bit % integerPartWidth));
+}
+
+/* Returns the bit number of the least significant set bit of a
+   number.  If the input number has no bits set -1U is returned.  */
+unsigned int
+APInt::tcLSB(const integerPart *parts, unsigned int n)
+{
+  unsigned int i, lsb;
+
+  for (i = 0; i < n; i++) {
+      if (parts[i] != 0) {
+          lsb = partLSB(parts[i]);
+
+          return lsb + i * integerPartWidth;
+      }
+  }
+
+  return -1U;
+}
+
+/* Returns the bit number of the most significant set bit of a number.
+   If the input number has no bits set -1U is returned.  */
+unsigned int
+APInt::tcMSB(const integerPart *parts, unsigned int n)
+{
+  unsigned int msb;
+
+  do {
+    --n;
+
+    if (parts[n] != 0) {
+      msb = partMSB(parts[n]);
+
+      return msb + n * integerPartWidth;
+    }
+  } while (n);
+
+  return -1U;
+}
+
+/* Copy the bit vector of width srcBITS from SRC, starting at bit
+   srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes
+   the least significant bit of DST.  All high bits above srcBITS in
+   DST are zero-filled.  */
+void
+APInt::tcExtract(integerPart *dst, unsigned int dstCount,const integerPart *src,
+                 unsigned int srcBits, unsigned int srcLSB)
+{
+  unsigned int firstSrcPart, dstParts, shift, n;
+
+  dstParts = (srcBits + integerPartWidth - 1) / integerPartWidth;
+  assert(dstParts <= dstCount);
+
+  firstSrcPart = srcLSB / integerPartWidth;
+  tcAssign (dst, src + firstSrcPart, dstParts);
+
+  shift = srcLSB % integerPartWidth;
+  tcShiftRight (dst, dstParts, shift);
+
+  /* We now have (dstParts * integerPartWidth - shift) bits from SRC
+     in DST.  If this is less that srcBits, append the rest, else
+     clear the high bits.  */
+  n = dstParts * integerPartWidth - shift;
+  if (n < srcBits) {
+    integerPart mask = lowBitMask (srcBits - n);
+    dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask)
+                          << n % integerPartWidth);
+  } else if (n > srcBits) {
+    if (srcBits % integerPartWidth)
+      dst[dstParts - 1] &= lowBitMask (srcBits % integerPartWidth);
+  }
+
+  /* Clear high parts.  */
+  while (dstParts < dstCount)
+    dst[dstParts++] = 0;
+}
+
+/* DST += RHS + C where C is zero or one.  Returns the carry flag.  */
+integerPart
+APInt::tcAdd(integerPart *dst, const integerPart *rhs,
+             integerPart c, unsigned int parts)
+{
+  unsigned int i;
+
+  assert(c <= 1);
+
+  for (i = 0; i < parts; i++) {
+    integerPart l;
+
+    l = dst[i];
+    if (c) {
+      dst[i] += rhs[i] + 1;
+      c = (dst[i] <= l);
+    } else {
+      dst[i] += rhs[i];
+      c = (dst[i] < l);
+    }
+  }
+
+  return c;
+}
+
+/* DST -= RHS + C where C is zero or one.  Returns the carry flag.  */
+integerPart
+APInt::tcSubtract(integerPart *dst, const integerPart *rhs,
+                  integerPart c, unsigned int parts)
+{
+  unsigned int i;
+
+  assert(c <= 1);
+
+  for (i = 0; i < parts; i++) {
+    integerPart l;
+
+    l = dst[i];
+    if (c) {
+      dst[i] -= rhs[i] + 1;
+      c = (dst[i] >= l);
+    } else {
+      dst[i] -= rhs[i];
+      c = (dst[i] > l);
+    }
+  }
+
+  return c;
+}
+
+/* Negate a bignum in-place.  */
+void
+APInt::tcNegate(integerPart *dst, unsigned int parts)
+{
+  tcComplement(dst, parts);
+  tcIncrement(dst, parts);
+}
+
+/*  DST += SRC * MULTIPLIER + CARRY   if add is true
+    DST  = SRC * MULTIPLIER + CARRY   if add is false
+
+    Requires 0 <= DSTPARTS <= SRCPARTS + 1.  If DST overlaps SRC
+    they must start at the same point, i.e. DST == SRC.
+
+    If DSTPARTS == SRCPARTS + 1 no overflow occurs and zero is
+    returned.  Otherwise DST is filled with the least significant
+    DSTPARTS parts of the result, and if all of the omitted higher
+    parts were zero return zero, otherwise overflow occurred and
+    return one.  */
+int
+APInt::tcMultiplyPart(integerPart *dst, const integerPart *src,
+                      integerPart multiplier, integerPart carry,
+                      unsigned int srcParts, unsigned int dstParts,
+                      bool add)
+{
+  unsigned int i, n;
+
+  /* Otherwise our writes of DST kill our later reads of SRC.  */
+  assert(dst <= src || dst >= src + srcParts);
+  assert(dstParts <= srcParts + 1);
+
+  /* N loops; minimum of dstParts and srcParts.  */
+  n = dstParts < srcParts ? dstParts: srcParts;
+
+  for (i = 0; i < n; i++) {
+    integerPart low, mid, high, srcPart;
+
+      /* [ LOW, HIGH ] = MULTIPLIER * SRC[i] + DST[i] + CARRY.
+
+         This cannot overflow, because
+
+         (n - 1) * (n - 1) + 2 (n - 1) = (n - 1) * (n + 1)
+
+         which is less than n^2.  */
+
+    srcPart = src[i];
+
+    if (multiplier == 0 || srcPart == 0)        {
+      low = carry;
+      high = 0;
+    } else {
+      low = lowHalf(srcPart) * lowHalf(multiplier);
+      high = highHalf(srcPart) * highHalf(multiplier);
+
+      mid = lowHalf(srcPart) * highHalf(multiplier);
+      high += highHalf(mid);
+      mid <<= integerPartWidth / 2;
+      if (low + mid < low)
+        high++;
+      low += mid;
+
+      mid = highHalf(srcPart) * lowHalf(multiplier);
+      high += highHalf(mid);
+      mid <<= integerPartWidth / 2;
+      if (low + mid < low)
+        high++;
+      low += mid;
+
+      /* Now add carry.  */
+      if (low + carry < low)
+        high++;
+      low += carry;
+    }
+
+    if (add) {
+      /* And now DST[i], and store the new low part there.  */
+      if (low + dst[i] < low)
+        high++;
+      dst[i] += low;
+    } else
+      dst[i] = low;
+
+    carry = high;
+  }
+
+  if (i < dstParts) {
+    /* Full multiplication, there is no overflow.  */
+    assert(i + 1 == dstParts);
+    dst[i] = carry;
+    return 0;
+  } else {
+    /* We overflowed if there is carry.  */
+    if (carry)
+      return 1;
+
+    /* We would overflow if any significant unwritten parts would be
+       non-zero.  This is true if any remaining src parts are non-zero
+       and the multiplier is non-zero.  */
+    if (multiplier)
+      for (; i < srcParts; i++)
+        if (src[i])
+          return 1;
+
+    /* We fitted in the narrow destination.  */
+    return 0;
+  }
+}
+
+/* DST = LHS * RHS, where DST has the same width as the operands and
+   is filled with the least significant parts of the result.  Returns
+   one if overflow occurred, otherwise zero.  DST must be disjoint
+   from both operands.  */
+int
+APInt::tcMultiply(integerPart *dst, const integerPart *lhs,
+                  const integerPart *rhs, unsigned int parts)
+{
+  unsigned int i;
+  int overflow;
+
+  assert(dst != lhs && dst != rhs);
+
+  overflow = 0;
+  tcSet(dst, 0, parts);
+
+  for (i = 0; i < parts; i++)
+    overflow |= tcMultiplyPart(&dst[i], lhs, rhs[i], 0, parts,
+                               parts - i, true);
+
+  return overflow;
+}
+
+/* DST = LHS * RHS, where DST has width the sum of the widths of the
+   operands.  No overflow occurs.  DST must be disjoint from both
+   operands.  Returns the number of parts required to hold the
+   result.  */
+unsigned int
+APInt::tcFullMultiply(integerPart *dst, const integerPart *lhs,
+                      const integerPart *rhs, unsigned int lhsParts,
+                      unsigned int rhsParts)
+{
+  /* Put the narrower number on the LHS for less loops below.  */
+  if (lhsParts > rhsParts) {
+    return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts);
+  } else {
+    unsigned int n;
+
+    assert(dst != lhs && dst != rhs);
+
+    tcSet(dst, 0, rhsParts);
+
+    for (n = 0; n < lhsParts; n++)
+      tcMultiplyPart(&dst[n], rhs, lhs[n], 0, rhsParts, rhsParts + 1, true);
+
+    n = lhsParts + rhsParts;
+
+    return n - (dst[n - 1] == 0);
+  }
+}
+
+/* If RHS is zero LHS and REMAINDER are left unchanged, return one.
+   Otherwise set LHS to LHS / RHS with the fractional part discarded,
+   set REMAINDER to the remainder, return zero.  i.e.
+
+   OLD_LHS = RHS * LHS + REMAINDER
+
+   SCRATCH is a bignum of the same size as the operands and result for
+   use by the routine; its contents need not be initialized and are
+   destroyed.  LHS, REMAINDER and SCRATCH must be distinct.
+*/
+int
+APInt::tcDivide(integerPart *lhs, const integerPart *rhs,
+                integerPart *remainder, integerPart *srhs,
+                unsigned int parts)
+{
+  unsigned int n, shiftCount;
+  integerPart mask;
+
+  assert(lhs != remainder && lhs != srhs && remainder != srhs);
+
+  shiftCount = tcMSB(rhs, parts) + 1;
+  if (shiftCount == 0)
+    return true;
+
+  shiftCount = parts * integerPartWidth - shiftCount;
+  n = shiftCount / integerPartWidth;
+  mask = (integerPart) 1 << (shiftCount % integerPartWidth);
+
+  tcAssign(srhs, rhs, parts);
+  tcShiftLeft(srhs, parts, shiftCount);
+  tcAssign(remainder, lhs, parts);
+  tcSet(lhs, 0, parts);
+
+  /* Loop, subtracting SRHS if REMAINDER is greater and adding that to
+     the total.  */
+  for (;;) {
+      int compare;
+
+      compare = tcCompare(remainder, srhs, parts);
+      if (compare >= 0) {
+        tcSubtract(remainder, srhs, 0, parts);
+        lhs[n] |= mask;
+      }
+
+      if (shiftCount == 0)
+        break;
+      shiftCount--;
+      tcShiftRight(srhs, parts, 1);
+      if ((mask >>= 1) == 0) {
+        mask = (integerPart) 1 << (integerPartWidth - 1);
+        n--;
+      }
+  }
+
+  return false;
+}
+
+/* Shift a bignum left COUNT bits in-place.  Shifted in bits are zero.
+   There are no restrictions on COUNT.  */
+void
+APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count)
+{
+  if (count) {
+    unsigned int jump, shift;
+
+    /* Jump is the inter-part jump; shift is is intra-part shift.  */
+    jump = count / integerPartWidth;
+    shift = count % integerPartWidth;
+
+    while (parts > jump) {
+      integerPart part;
+
+      parts--;
+
+      /* dst[i] comes from the two parts src[i - jump] and, if we have
+         an intra-part shift, src[i - jump - 1].  */
+      part = dst[parts - jump];
+      if (shift) {
+        part <<= shift;
+        if (parts >= jump + 1)
+          part |= dst[parts - jump - 1] >> (integerPartWidth - shift);
+      }
+
+      dst[parts] = part;
+    }
+
+    while (parts > 0)
+      dst[--parts] = 0;
+  }
+}
+
+/* Shift a bignum right COUNT bits in-place.  Shifted in bits are
+   zero.  There are no restrictions on COUNT.  */
+void
+APInt::tcShiftRight(integerPart *dst, unsigned int parts, unsigned int count)
+{
+  if (count) {
+    unsigned int i, jump, shift;
+
+    /* Jump is the inter-part jump; shift is is intra-part shift.  */
+    jump = count / integerPartWidth;
+    shift = count % integerPartWidth;
+
+    /* Perform the shift.  This leaves the most significant COUNT bits
+       of the result at zero.  */
+    for (i = 0; i < parts; i++) {
+      integerPart part;
+
+      if (i + jump >= parts) {
+        part = 0;
+      } else {
+        part = dst[i + jump];
+        if (shift) {
+          part >>= shift;
+          if (i + jump + 1 < parts)
+            part |= dst[i + jump + 1] << (integerPartWidth - shift);
+        }
+      }
+
+      dst[i] = part;
+    }
+  }
+}
+
+/* Bitwise and of two bignums.  */
+void
+APInt::tcAnd(integerPart *dst, const integerPart *rhs, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    dst[i] &= rhs[i];
+}
+
+/* Bitwise inclusive or of two bignums.  */
+void
+APInt::tcOr(integerPart *dst, const integerPart *rhs, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    dst[i] |= rhs[i];
+}
+
+/* Bitwise exclusive or of two bignums.  */
+void
+APInt::tcXor(integerPart *dst, const integerPart *rhs, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    dst[i] ^= rhs[i];
+}
+
+/* Complement a bignum in-place.  */
+void
+APInt::tcComplement(integerPart *dst, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    dst[i] = ~dst[i];
+}
+
+/* Comparison (unsigned) of two bignums.  */
+int
+APInt::tcCompare(const integerPart *lhs, const integerPart *rhs,
+                 unsigned int parts)
+{
+  while (parts) {
+      parts--;
+      if (lhs[parts] == rhs[parts])
+        continue;
+
+      if (lhs[parts] > rhs[parts])
+        return 1;
+      else
+        return -1;
+    }
+
+  return 0;
+}
+
+/* Increment a bignum in-place, return the carry flag.  */
+integerPart
+APInt::tcIncrement(integerPart *dst, unsigned int parts)
+{
+  unsigned int i;
+
+  for (i = 0; i < parts; i++)
+    if (++dst[i] != 0)
+      break;
+
+  return i == parts;
+}
+
+/* Decrement a bignum in-place, return the borrow flag.  */
+integerPart
+APInt::tcDecrement(integerPart *dst, unsigned int parts) {
+  for (unsigned int i = 0; i < parts; i++) {
+    // If the current word is non-zero, then the decrement has no effect on the
+    // higher-order words of the integer and no borrow can occur. Exit early.
+    if (dst[i]--)
+      return 0;
+  }
+  // If every word was zero, then there is a borrow.
+  return 1;
+}
+
+
+/* Set the least significant BITS bits of a bignum, clear the
+   rest.  */
+void
+APInt::tcSetLeastSignificantBits(integerPart *dst, unsigned int parts,
+                                 unsigned int bits)
+{
+  unsigned int i;
+
+  i = 0;
+  while (bits > integerPartWidth) {
+    dst[i++] = ~(integerPart) 0;
+    bits -= integerPartWidth;
+  }
+
+  if (bits)
+    dst[i++] = ~(integerPart) 0 >> (integerPartWidth - bits);
+
+  while (i < parts)
+    dst[i++] = 0;
+}
diff --git a/third_party/llvm-subzero/lib/Support/Atomic.cpp b/third_party/llvm-subzero/lib/Support/Atomic.cpp
new file mode 100644
index 0000000..80550e2
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Atomic.cpp
@@ -0,0 +1,58 @@
+//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements atomic operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Atomic.h"
+#include "llvm/Config/llvm-config.h"
+
+using namespace llvm;
+
+#if defined(_MSC_VER)
+#include <Intrin.h>
+#include <windows.h>
+#undef MemoryFence
+#endif
+
+#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210)
+#define GNU_ATOMICS
+#endif
+
+void sys::MemoryFence() {
+#if LLVM_HAS_ATOMICS == 0
+  return;
+#else
+#  if defined(GNU_ATOMICS)
+  __sync_synchronize();
+#  elif defined(_MSC_VER)
+  MemoryBarrier();
+#  else
+# error No memory fence implementation for your platform!
+#  endif
+#endif
+}
+
+sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
+                                  sys::cas_flag new_value,
+                                  sys::cas_flag old_value) {
+#if LLVM_HAS_ATOMICS == 0
+  sys::cas_flag result = *ptr;
+  if (result == old_value)
+    *ptr = new_value;
+  return result;
+#elif defined(GNU_ATOMICS)
+  return __sync_val_compare_and_swap(ptr, old_value, new_value);
+#elif defined(_MSC_VER)
+  return InterlockedCompareExchange(ptr, new_value, old_value);
+#else
+#  error No compare-and-swap implementation for your platform!
+#endif
+}
diff --git a/third_party/llvm-subzero/lib/Support/CommandLine.cpp b/third_party/llvm-subzero/lib/Support/CommandLine.cpp
new file mode 100644
index 0000000..551cdef
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/CommandLine.cpp
@@ -0,0 +1,2136 @@
+//===-- CommandLine.cpp - Command line parser implementation --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements a command line argument processor that is useful when
+// creating a tool.  It provides a simple, minimalistic interface that is easily
+// extensible and supports nonlocal (library) command line options.
+//
+// Note that rather than trying to figure out what this code does, you could try
+// reading the library documentation located in docs/CommandLine.html
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm-c/Support.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+#include <map>
+using namespace llvm;
+using namespace cl;
+
+#define DEBUG_TYPE "commandline"
+
+//===----------------------------------------------------------------------===//
+// Template instantiations and anchors.
+//
+namespace llvm {
+namespace cl {
+template class basic_parser<bool>;
+template class basic_parser<boolOrDefault>;
+template class basic_parser<int>;
+template class basic_parser<unsigned>;
+template class basic_parser<unsigned long long>;
+template class basic_parser<double>;
+template class basic_parser<float>;
+template class basic_parser<std::string>;
+template class basic_parser<char>;
+
+template class opt<unsigned>;
+template class opt<int>;
+template class opt<std::string>;
+template class opt<char>;
+template class opt<bool>;
+}
+} // end namespace llvm::cl
+
+// Pin the vtables to this file.
+void GenericOptionValue::anchor() {}
+void OptionValue<boolOrDefault>::anchor() {}
+void OptionValue<std::string>::anchor() {}
+void Option::anchor() {}
+void basic_parser_impl::anchor() {}
+void parser<bool>::anchor() {}
+void parser<boolOrDefault>::anchor() {}
+void parser<int>::anchor() {}
+void parser<unsigned>::anchor() {}
+void parser<unsigned long long>::anchor() {}
+void parser<double>::anchor() {}
+void parser<float>::anchor() {}
+void parser<std::string>::anchor() {}
+void parser<char>::anchor() {}
+
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class CommandLineParser {
+public:
+  // Globals for name and overview of program.  Program name is not a string to
+  // avoid static ctor/dtor issues.
+  std::string ProgramName;
+  const char *ProgramOverview;
+
+  // This collects additional help to be printed.
+  std::vector<const char *> MoreHelp;
+
+  // This collects the different option categories that have been registered.
+  SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
+
+  // This collects the different subcommands that have been registered.
+  SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;
+
+  CommandLineParser() : ProgramOverview(nullptr), ActiveSubCommand(nullptr) {
+    registerSubCommand(&*TopLevelSubCommand);
+    registerSubCommand(&*AllSubCommands);
+  }
+
+  void ResetAllOptionOccurrences();
+
+  bool ParseCommandLineOptions(int argc, const char *const *argv,
+                               const char *Overview, bool IgnoreErrors);
+
+  void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) {
+    if (Opt.hasArgStr())
+      return;
+    if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
+      errs() << ProgramName << ": CommandLine Error: Option '" << Name
+             << "' registered more than once!\n";
+      report_fatal_error("inconsistency in registered CommandLine options");
+    }
+
+    // If we're adding this to all sub-commands, add it to the ones that have
+    // already been registered.
+    if (SC == &*AllSubCommands) {
+      for (const auto &Sub : RegisteredSubCommands) {
+        if (SC == Sub)
+          continue;
+        addLiteralOption(Opt, Sub, Name);
+      }
+    }
+  }
+
+  void addLiteralOption(Option &Opt, const char *Name) {
+    if (Opt.Subs.empty())
+      addLiteralOption(Opt, &*TopLevelSubCommand, Name);
+    else {
+      for (auto SC : Opt.Subs)
+        addLiteralOption(Opt, SC, Name);
+    }
+  }
+
+  void addOption(Option *O, SubCommand *SC) {
+    bool HadErrors = false;
+    if (O->hasArgStr()) {
+      // Add argument to the argument map!
+      if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
+        errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
+               << "' registered more than once!\n";
+        HadErrors = true;
+      }
+    }
+
+    // Remember information about positional options.
+    if (O->getFormattingFlag() == cl::Positional)
+      SC->PositionalOpts.push_back(O);
+    else if (O->getMiscFlags() & cl::Sink) // Remember sink options
+      SC->SinkOpts.push_back(O);
+    else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
+      if (SC->ConsumeAfterOpt) {
+        O->error("Cannot specify more than one option with cl::ConsumeAfter!");
+        HadErrors = true;
+      }
+      SC->ConsumeAfterOpt = O;
+    }
+
+    // Fail hard if there were errors. These are strictly unrecoverable and
+    // indicate serious issues such as conflicting option names or an
+    // incorrectly
+    // linked LLVM distribution.
+    if (HadErrors)
+      report_fatal_error("inconsistency in registered CommandLine options");
+
+    // If we're adding this to all sub-commands, add it to the ones that have
+    // already been registered.
+    if (SC == &*AllSubCommands) {
+      for (const auto &Sub : RegisteredSubCommands) {
+        if (SC == Sub)
+          continue;
+        addOption(O, Sub);
+      }
+    }
+  }
+
+  void addOption(Option *O) {
+    if (O->Subs.empty()) {
+      addOption(O, &*TopLevelSubCommand);
+    } else {
+      for (auto SC : O->Subs)
+        addOption(O, SC);
+    }
+  }
+
+  void removeOption(Option *O, SubCommand *SC) {
+    SmallVector<StringRef, 16> OptionNames;
+    O->getExtraOptionNames(OptionNames);
+    if (O->hasArgStr())
+      OptionNames.push_back(O->ArgStr);
+
+    SubCommand &Sub = *SC;
+    for (auto Name : OptionNames)
+      Sub.OptionsMap.erase(Name);
+
+    if (O->getFormattingFlag() == cl::Positional)
+      for (auto Opt = Sub.PositionalOpts.begin();
+           Opt != Sub.PositionalOpts.end(); ++Opt) {
+        if (*Opt == O) {
+          Sub.PositionalOpts.erase(Opt);
+          break;
+        }
+      }
+    else if (O->getMiscFlags() & cl::Sink)
+      for (auto Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) {
+        if (*Opt == O) {
+          Sub.SinkOpts.erase(Opt);
+          break;
+        }
+      }
+    else if (O == Sub.ConsumeAfterOpt)
+      Sub.ConsumeAfterOpt = nullptr;
+  }
+
+  void removeOption(Option *O) {
+    if (O->Subs.empty())
+      removeOption(O, &*TopLevelSubCommand);
+    else {
+      if (O->isInAllSubCommands()) {
+        for (auto SC : RegisteredSubCommands)
+          removeOption(O, SC);
+      } else {
+        for (auto SC : O->Subs)
+          removeOption(O, SC);
+      }
+    }
+  }
+
+  bool hasOptions(const SubCommand &Sub) const {
+    return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() ||
+            nullptr != Sub.ConsumeAfterOpt);
+  }
+
+  bool hasOptions() const {
+    for (const auto &S : RegisteredSubCommands) {
+      if (hasOptions(*S))
+        return true;
+    }
+    return false;
+  }
+
+  SubCommand *getActiveSubCommand() { return ActiveSubCommand; }
+
+  void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) {
+    SubCommand &Sub = *SC;
+    if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) {
+      errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
+             << "' registered more than once!\n";
+      report_fatal_error("inconsistency in registered CommandLine options");
+    }
+    Sub.OptionsMap.erase(O->ArgStr);
+  }
+
+  void updateArgStr(Option *O, StringRef NewName) {
+    if (O->Subs.empty())
+      updateArgStr(O, NewName, &*TopLevelSubCommand);
+    else {
+      for (auto SC : O->Subs)
+        updateArgStr(O, NewName, SC);
+    }
+  }
+
+  void printOptionValues();
+
+  void registerCategory(OptionCategory *cat) {
+    assert(count_if(RegisteredOptionCategories,
+                    [cat](const OptionCategory *Category) {
+             return cat->getName() == Category->getName();
+           }) == 0 &&
+           "Duplicate option categories");
+
+    RegisteredOptionCategories.insert(cat);
+  }
+
+  void registerSubCommand(SubCommand *sub) {
+    assert(count_if(RegisteredSubCommands,
+                    [sub](const SubCommand *Sub) {
+                      return (sub->getName() != nullptr) &&
+                             (Sub->getName() == sub->getName());
+                    }) == 0 &&
+           "Duplicate subcommands");
+    RegisteredSubCommands.insert(sub);
+
+    // For all options that have been registered for all subcommands, add the
+    // option to this subcommand now.
+    if (sub != &*AllSubCommands) {
+      for (auto &E : AllSubCommands->OptionsMap) {
+        Option *O = E.second;
+        if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||
+            O->hasArgStr())
+          addOption(O, sub);
+        else
+          addLiteralOption(*O, sub, E.first().str().c_str());
+      }
+    }
+  }
+
+  void unregisterSubCommand(SubCommand *sub) {
+    RegisteredSubCommands.erase(sub);
+  }
+
+  void reset() {
+    ActiveSubCommand = nullptr;
+    ProgramName.clear();
+    ProgramOverview = nullptr;
+
+    MoreHelp.clear();
+    RegisteredOptionCategories.clear();
+
+    ResetAllOptionOccurrences();
+    RegisteredSubCommands.clear();
+
+    TopLevelSubCommand->reset();
+    AllSubCommands->reset();
+    registerSubCommand(&*TopLevelSubCommand);
+    registerSubCommand(&*AllSubCommands);
+  }
+
+private:
+  SubCommand *ActiveSubCommand;
+
+  Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value);
+  SubCommand *LookupSubCommand(const char *Name);
+};
+
+} // namespace
+
+static ManagedStatic<CommandLineParser> GlobalParser;
+
+void cl::AddLiteralOption(Option &O, const char *Name) {
+  GlobalParser->addLiteralOption(O, Name);
+}
+
+extrahelp::extrahelp(const char *Help) : morehelp(Help) {
+  GlobalParser->MoreHelp.push_back(Help);
+}
+
+void Option::addArgument() {
+  GlobalParser->addOption(this);
+  FullyInitialized = true;
+}
+
+void Option::removeArgument() { GlobalParser->removeOption(this); }
+
+void Option::setArgStr(StringRef S) {
+  if (FullyInitialized)
+    GlobalParser->updateArgStr(this, S);
+  ArgStr = S;
+}
+
+// Initialise the general option category.
+OptionCategory llvm::cl::GeneralCategory("General options");
+
+void OptionCategory::registerCategory() {
+  GlobalParser->registerCategory(this);
+}
+
+// A special subcommand representing no subcommand
+ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand;
+
+// A special subcommand that can be used to put an option into all subcommands.
+ManagedStatic<SubCommand> llvm::cl::AllSubCommands;
+
+void SubCommand::registerSubCommand() {
+  GlobalParser->registerSubCommand(this);
+}
+
+void SubCommand::unregisterSubCommand() {
+  GlobalParser->unregisterSubCommand(this);
+}
+
+void SubCommand::reset() {
+  PositionalOpts.clear();
+  SinkOpts.clear();
+  OptionsMap.clear();
+
+  ConsumeAfterOpt = nullptr;
+}
+
+SubCommand::operator bool() const {
+  return (GlobalParser->getActiveSubCommand() == this);
+}
+
+//===----------------------------------------------------------------------===//
+// Basic, shared command line option processing machinery.
+//
+
+/// LookupOption - Lookup the option specified by the specified option on the
+/// command line.  If there is a value specified (after an equal sign) return
+/// that as well.  This assumes that leading dashes have already been stripped.
+Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
+                                        StringRef &Value) {
+  // Reject all dashes.
+  if (Arg.empty())
+    return nullptr;
+  assert(&Sub != &*AllSubCommands);
+
+  size_t EqualPos = Arg.find('=');
+
+  // If we have an equals sign, remember the value.
+  if (EqualPos == StringRef::npos) {
+    // Look up the option.
+    auto I = Sub.OptionsMap.find(Arg);
+    if (I == Sub.OptionsMap.end())
+      return nullptr;
+
+    return I != Sub.OptionsMap.end() ? I->second : nullptr;
+  }
+
+  // If the argument before the = is a valid option name, we match.  If not,
+  // return Arg unmolested.
+  auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos));
+  if (I == Sub.OptionsMap.end())
+    return nullptr;
+
+  Value = Arg.substr(EqualPos + 1);
+  Arg = Arg.substr(0, EqualPos);
+  return I->second;
+}
+
+SubCommand *CommandLineParser::LookupSubCommand(const char *Name) {
+  if (Name == nullptr)
+    return &*TopLevelSubCommand;
+  for (auto S : RegisteredSubCommands) {
+    if (S == &*AllSubCommands)
+      continue;
+    if (S->getName() == nullptr)
+      continue;
+
+    if (StringRef(S->getName()) == StringRef(Name))
+      return S;
+  }
+  return &*TopLevelSubCommand;
+}
+
+/// LookupNearestOption - Lookup the closest match to the option specified by
+/// the specified option on the command line.  If there is a value specified
+/// (after an equal sign) return that as well.  This assumes that leading dashes
+/// have already been stripped.
+static Option *LookupNearestOption(StringRef Arg,
+                                   const StringMap<Option *> &OptionsMap,
+                                   std::string &NearestString) {
+  // Reject all dashes.
+  if (Arg.empty())
+    return nullptr;
+
+  // Split on any equal sign.
+  std::pair<StringRef, StringRef> SplitArg = Arg.split('=');
+  StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present.
+  StringRef &RHS = SplitArg.second;
+
+  // Find the closest match.
+  Option *Best = nullptr;
+  unsigned BestDistance = 0;
+  for (StringMap<Option *>::const_iterator it = OptionsMap.begin(),
+                                           ie = OptionsMap.end();
+       it != ie; ++it) {
+    Option *O = it->second;
+    SmallVector<StringRef, 16> OptionNames;
+    O->getExtraOptionNames(OptionNames);
+    if (O->hasArgStr())
+      OptionNames.push_back(O->ArgStr);
+
+    bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed;
+    StringRef Flag = PermitValue ? LHS : Arg;
+    for (auto Name : OptionNames) {
+      unsigned Distance = StringRef(Name).edit_distance(
+          Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance);
+      if (!Best || Distance < BestDistance) {
+        Best = O;
+        BestDistance = Distance;
+        if (RHS.empty() || !PermitValue)
+          NearestString = Name;
+        else
+          NearestString = (Twine(Name) + "=" + RHS).str();
+      }
+    }
+  }
+
+  return Best;
+}
+
+/// CommaSeparateAndAddOccurrence - A wrapper around Handler->addOccurrence()
+/// that does special handling of cl::CommaSeparated options.
+static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos,
+                                          StringRef ArgName, StringRef Value,
+                                          bool MultiArg = false) {
+  // Check to see if this option accepts a comma separated list of values.  If
+  // it does, we have to split up the value into multiple values.
+  if (Handler->getMiscFlags() & CommaSeparated) {
+    StringRef Val(Value);
+    StringRef::size_type Pos = Val.find(',');
+
+    while (Pos != StringRef::npos) {
+      // Process the portion before the comma.
+      if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg))
+        return true;
+      // Erase the portion before the comma, AND the comma.
+      Val = Val.substr(Pos + 1);
+      // Check for another comma.
+      Pos = Val.find(',');
+    }
+
+    Value = Val;
+  }
+
+  return Handler->addOccurrence(pos, ArgName, Value, MultiArg);
+}
+
+/// ProvideOption - For Value, this differentiates between an empty value ("")
+/// and a null value (StringRef()).  The later is accepted for arguments that
+/// don't allow a value (-foo) the former is rejected (-foo=).
+static inline bool ProvideOption(Option *Handler, StringRef ArgName,
+                                 StringRef Value, int argc,
+                                 const char *const *argv, int &i) {
+  // Is this a multi-argument option?
+  unsigned NumAdditionalVals = Handler->getNumAdditionalVals();
+
+  // Enforce value requirements
+  switch (Handler->getValueExpectedFlag()) {
+  case ValueRequired:
+    if (!Value.data()) { // No value specified?
+      if (i + 1 >= argc)
+        return Handler->error("requires a value!");
+      // Steal the next argument, like for '-o filename'
+      assert(argv && "null check");
+      Value = argv[++i];
+    }
+    break;
+  case ValueDisallowed:
+    if (NumAdditionalVals > 0)
+      return Handler->error("multi-valued option specified"
+                            " with ValueDisallowed modifier!");
+
+    if (Value.data())
+      return Handler->error("does not allow a value! '" + Twine(Value) +
+                            "' specified.");
+    break;
+  case ValueOptional:
+    break;
+  }
+
+  // If this isn't a multi-arg option, just run the handler.
+  if (NumAdditionalVals == 0)
+    return CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value);
+
+  // If it is, run the handle several times.
+  bool MultiArg = false;
+
+  if (Value.data()) {
+    if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg))
+      return true;
+    --NumAdditionalVals;
+    MultiArg = true;
+  }
+
+  while (NumAdditionalVals > 0) {
+    if (i + 1 >= argc)
+      return Handler->error("not enough values!");
+    assert(argv && "null check");
+    Value = argv[++i];
+
+    if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg))
+      return true;
+    MultiArg = true;
+    --NumAdditionalVals;
+  }
+  return false;
+}
+
+static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) {
+  int Dummy = i;
+  return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy);
+}
+
+// Option predicates...
+static inline bool isGrouping(const Option *O) {
+  return O->getFormattingFlag() == cl::Grouping;
+}
+static inline bool isPrefixedOrGrouping(const Option *O) {
+  return isGrouping(O) || O->getFormattingFlag() == cl::Prefix;
+}
+
+// getOptionPred - Check to see if there are any options that satisfy the
+// specified predicate with names that are the prefixes in Name.  This is
+// checked by progressively stripping characters off of the name, checking to
+// see if there options that satisfy the predicate.  If we find one, return it,
+// otherwise return null.
+//
+static Option *getOptionPred(StringRef Name, size_t &Length,
+                             bool (*Pred)(const Option *),
+                             const StringMap<Option *> &OptionsMap) {
+
+  StringMap<Option *>::const_iterator OMI = OptionsMap.find(Name);
+
+  // Loop while we haven't found an option and Name still has at least two
+  // characters in it (so that the next iteration will not be the empty
+  // string.
+  while (OMI == OptionsMap.end() && Name.size() > 1) {
+    Name = Name.substr(0, Name.size() - 1); // Chop off the last character.
+    OMI = OptionsMap.find(Name);
+  }
+
+  if (OMI != OptionsMap.end() && Pred(OMI->second)) {
+    Length = Name.size();
+    return OMI->second; // Found one!
+  }
+  return nullptr; // No option found!
+}
+
+/// HandlePrefixedOrGroupedOption - The specified argument string (which started
+/// with at least one '-') does not fully match an available option.  Check to
+/// see if this is a prefix or grouped option.  If so, split arg into output an
+/// Arg/Value pair and return the Option to parse it with.
+static Option *
+HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value,
+                              bool &ErrorParsing,
+                              const StringMap<Option *> &OptionsMap) {
+  if (Arg.size() == 1)
+    return nullptr;
+
+  // Do the lookup!
+  size_t Length = 0;
+  Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap);
+  if (!PGOpt)
+    return nullptr;
+
+  // If the option is a prefixed option, then the value is simply the
+  // rest of the name...  so fall through to later processing, by
+  // setting up the argument name flags and value fields.
+  if (PGOpt->getFormattingFlag() == cl::Prefix) {
+    Value = Arg.substr(Length);
+    Arg = Arg.substr(0, Length);
+    assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt);
+    return PGOpt;
+  }
+
+  // This must be a grouped option... handle them now.  Grouping options can't
+  // have values.
+  assert(isGrouping(PGOpt) && "Broken getOptionPred!");
+
+  do {
+    // Move current arg name out of Arg into OneArgName.
+    StringRef OneArgName = Arg.substr(0, Length);
+    Arg = Arg.substr(Length);
+
+    // Because ValueRequired is an invalid flag for grouped arguments,
+    // we don't need to pass argc/argv in.
+    assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired &&
+           "Option can not be cl::Grouping AND cl::ValueRequired!");
+    int Dummy = 0;
+    ErrorParsing |=
+        ProvideOption(PGOpt, OneArgName, StringRef(), 0, nullptr, Dummy);
+
+    // Get the next grouping option.
+    PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap);
+  } while (PGOpt && Length != Arg.size());
+
+  // Return the last option with Arg cut down to just the last one.
+  return PGOpt;
+}
+
+static bool RequiresValue(const Option *O) {
+  return O->getNumOccurrencesFlag() == cl::Required ||
+         O->getNumOccurrencesFlag() == cl::OneOrMore;
+}
+
+static bool EatsUnboundedNumberOfValues(const Option *O) {
+  return O->getNumOccurrencesFlag() == cl::ZeroOrMore ||
+         O->getNumOccurrencesFlag() == cl::OneOrMore;
+}
+
+static bool isWhitespace(char C) { return strchr(" \t\n\r\f\v", C); }
+
+static bool isQuote(char C) { return C == '\"' || C == '\''; }
+
+void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
+                                SmallVectorImpl<const char *> &NewArgv,
+                                bool MarkEOLs) {
+  SmallString<128> Token;
+  for (size_t I = 0, E = Src.size(); I != E; ++I) {
+    // Consume runs of whitespace.
+    if (Token.empty()) {
+      while (I != E && isWhitespace(Src[I])) {
+        // Mark the end of lines in response files
+        if (MarkEOLs && Src[I] == '\n')
+          NewArgv.push_back(nullptr);
+        ++I;
+      }
+      if (I == E)
+        break;
+    }
+
+    // Backslash escapes the next character.
+    if (I + 1 < E && Src[I] == '\\') {
+      ++I; // Skip the escape.
+      Token.push_back(Src[I]);
+      continue;
+    }
+
+    // Consume a quoted string.
+    if (isQuote(Src[I])) {
+      char Quote = Src[I++];
+      while (I != E && Src[I] != Quote) {
+        // Backslash escapes the next character.
+        if (Src[I] == '\\' && I + 1 != E)
+          ++I;
+        Token.push_back(Src[I]);
+        ++I;
+      }
+      if (I == E)
+        break;
+      continue;
+    }
+
+    // End the token if this is whitespace.
+    if (isWhitespace(Src[I])) {
+      if (!Token.empty())
+        NewArgv.push_back(Saver.save(Token.c_str()));
+      Token.clear();
+      continue;
+    }
+
+    // This is a normal character.  Append it.
+    Token.push_back(Src[I]);
+  }
+
+  // Append the last token after hitting EOF with no whitespace.
+  if (!Token.empty())
+    NewArgv.push_back(Saver.save(Token.c_str()));
+  // Mark the end of response files
+  if (MarkEOLs)
+    NewArgv.push_back(nullptr);
+}
+
+/// Backslashes are interpreted in a rather complicated way in the Windows-style
+/// command line, because backslashes are used both to separate path and to
+/// escape double quote. This method consumes runs of backslashes as well as the
+/// following double quote if it's escaped.
+///
+///  * If an even number of backslashes is followed by a double quote, one
+///    backslash is output for every pair of backslashes, and the last double
+///    quote remains unconsumed. The double quote will later be interpreted as
+///    the start or end of a quoted string in the main loop outside of this
+///    function.
+///
+///  * If an odd number of backslashes is followed by a double quote, one
+///    backslash is output for every pair of backslashes, and a double quote is
+///    output for the last pair of backslash-double quote. The double quote is
+///    consumed in this case.
+///
+///  * Otherwise, backslashes are interpreted literally.
+static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) {
+  size_t E = Src.size();
+  int BackslashCount = 0;
+  // Skip the backslashes.
+  do {
+    ++I;
+    ++BackslashCount;
+  } while (I != E && Src[I] == '\\');
+
+  bool FollowedByDoubleQuote = (I != E && Src[I] == '"');
+  if (FollowedByDoubleQuote) {
+    Token.append(BackslashCount / 2, '\\');
+    if (BackslashCount % 2 == 0)
+      return I - 1;
+    Token.push_back('"');
+    return I;
+  }
+  Token.append(BackslashCount, '\\');
+  return I - 1;
+}
+
+void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,
+                                    SmallVectorImpl<const char *> &NewArgv,
+                                    bool MarkEOLs) {
+  SmallString<128> Token;
+
+  // This is a small state machine to consume characters until it reaches the
+  // end of the source string.
+  enum { INIT, UNQUOTED, QUOTED } State = INIT;
+  for (size_t I = 0, E = Src.size(); I != E; ++I) {
+    // INIT state indicates that the current input index is at the start of
+    // the string or between tokens.
+    if (State == INIT) {
+      if (isWhitespace(Src[I])) {
+        // Mark the end of lines in response files
+        if (MarkEOLs && Src[I] == '\n')
+          NewArgv.push_back(nullptr);
+        continue;
+      }
+      if (Src[I] == '"') {
+        State = QUOTED;
+        continue;
+      }
+      if (Src[I] == '\\') {
+        I = parseBackslash(Src, I, Token);
+        State = UNQUOTED;
+        continue;
+      }
+      Token.push_back(Src[I]);
+      State = UNQUOTED;
+      continue;
+    }
+
+    // UNQUOTED state means that it's reading a token not quoted by double
+    // quotes.
+    if (State == UNQUOTED) {
+      // Whitespace means the end of the token.
+      if (isWhitespace(Src[I])) {
+        NewArgv.push_back(Saver.save(Token.c_str()));
+        Token.clear();
+        State = INIT;
+        // Mark the end of lines in response files
+        if (MarkEOLs && Src[I] == '\n')
+          NewArgv.push_back(nullptr);
+        continue;
+      }
+      if (Src[I] == '"') {
+        State = QUOTED;
+        continue;
+      }
+      if (Src[I] == '\\') {
+        I = parseBackslash(Src, I, Token);
+        continue;
+      }
+      Token.push_back(Src[I]);
+      continue;
+    }
+
+    // QUOTED state means that it's reading a token quoted by double quotes.
+    if (State == QUOTED) {
+      if (Src[I] == '"') {
+        State = UNQUOTED;
+        continue;
+      }
+      if (Src[I] == '\\') {
+        I = parseBackslash(Src, I, Token);
+        continue;
+      }
+      Token.push_back(Src[I]);
+    }
+  }
+  // Append the last token after hitting EOF with no whitespace.
+  if (!Token.empty())
+    NewArgv.push_back(Saver.save(Token.c_str()));
+  // Mark the end of response files
+  if (MarkEOLs)
+    NewArgv.push_back(nullptr);
+}
+
+// It is called byte order marker but the UTF-8 BOM is actually not affected
+// by the host system's endianness.
+static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {
+  return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
+}
+
+static bool ExpandResponseFile(const char *FName, StringSaver &Saver,
+                               TokenizerCallback Tokenizer,
+                               SmallVectorImpl<const char *> &NewArgv,
+                               bool MarkEOLs = false) {
+  ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
+      MemoryBuffer::getFile(FName);
+  if (!MemBufOrErr)
+    return false;
+  MemoryBuffer &MemBuf = *MemBufOrErr.get();
+  StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());
+
+  // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing.
+  ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd());
+  std::string UTF8Buf;
+  if (hasUTF16ByteOrderMark(BufRef)) {
+    if (!convertUTF16ToUTF8String(BufRef, UTF8Buf))
+      return false;
+    Str = StringRef(UTF8Buf);
+  }
+  // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove
+  // these bytes before parsing.
+  // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark
+  else if (hasUTF8ByteOrderMark(BufRef))
+    Str = StringRef(BufRef.data() + 3, BufRef.size() - 3);
+
+  // Tokenize the contents into NewArgv.
+  Tokenizer(Str, Saver, NewArgv, MarkEOLs);
+
+  return true;
+}
+
+/// \brief Expand response files on a command line recursively using the given
+/// StringSaver and tokenization strategy.
+bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
+                             SmallVectorImpl<const char *> &Argv,
+                             bool MarkEOLs) {
+  unsigned RspFiles = 0;
+  bool AllExpanded = true;
+
+  // Don't cache Argv.size() because it can change.
+  for (unsigned I = 0; I != Argv.size();) {
+    const char *Arg = Argv[I];
+    // Check if it is an EOL marker
+    if (Arg == nullptr) {
+      ++I;
+      continue;
+    }
+    if (Arg[0] != '@') {
+      ++I;
+      continue;
+    }
+
+    // If we have too many response files, leave some unexpanded.  This avoids
+    // crashing on self-referential response files.
+    if (RspFiles++ > 20)
+      return false;
+
+    // Replace this response file argument with the tokenization of its
+    // contents.  Nested response files are expanded in subsequent iterations.
+    // FIXME: If a nested response file uses a relative path, is it relative to
+    // the cwd of the process or the response file?
+    SmallVector<const char *, 0> ExpandedArgv;
+    if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv,
+                            MarkEOLs)) {
+      // We couldn't read this file, so we leave it in the argument stream and
+      // move on.
+      AllExpanded = false;
+      ++I;
+      continue;
+    }
+    Argv.erase(Argv.begin() + I);
+    Argv.insert(Argv.begin() + I, ExpandedArgv.begin(), ExpandedArgv.end());
+  }
+  return AllExpanded;
+}
+
+/// ParseEnvironmentOptions - An alternative entry point to the
+/// CommandLine library, which allows you to read the program's name
+/// from the caller (as PROGNAME) and its command-line arguments from
+/// an environment variable (whose name is given in ENVVAR).
+///
+void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
+                                 const char *Overview) {
+  // Check args.
+  assert(progName && "Program name not specified");
+  assert(envVar && "Environment variable name missing");
+
+  // Get the environment variable they want us to parse options out of.
+  llvm::Optional<std::string> envValue = sys::Process::GetEnv(envVar);
+  if (!envValue)
+    return;
+
+  // Get program's "name", which we wouldn't know without the caller
+  // telling us.
+  SmallVector<const char *, 20> newArgv;
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  newArgv.push_back(Saver.save(progName));
+
+  // Parse the value of the environment variable into a "command line"
+  // and hand it off to ParseCommandLineOptions().
+  TokenizeGNUCommandLine(*envValue, Saver, newArgv);
+  int newArgc = static_cast<int>(newArgv.size());
+  ParseCommandLineOptions(newArgc, &newArgv[0], Overview);
+}
+
+bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
+                                 const char *Overview, bool IgnoreErrors) {
+  return GlobalParser->ParseCommandLineOptions(argc, argv, Overview,
+                                               IgnoreErrors);
+}
+
+void CommandLineParser::ResetAllOptionOccurrences() {
+  // So that we can parse different command lines multiple times in succession
+  // we reset all option values to look like they have never been seen before.
+  for (auto SC : RegisteredSubCommands) {
+    for (auto &O : SC->OptionsMap)
+      O.second->reset();
+  }
+}
+
+bool CommandLineParser::ParseCommandLineOptions(int argc,
+                                                const char *const *argv,
+                                                const char *Overview,
+                                                bool IgnoreErrors) {
+  assert(hasOptions() && "No options specified!");
+
+  // Expand response files.
+  SmallVector<const char *, 20> newArgv(argv, argv + argc);
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv);
+  argv = &newArgv[0];
+  argc = static_cast<int>(newArgv.size());
+
+  // Copy the program name into ProgName, making sure not to overflow it.
+  ProgramName = sys::path::filename(argv[0]);
+
+  ProgramOverview = Overview;
+  bool ErrorParsing = false;
+
+  // Check out the positional arguments to collect information about them.
+  unsigned NumPositionalRequired = 0;
+
+  // Determine whether or not there are an unlimited number of positionals
+  bool HasUnlimitedPositionals = false;
+
+  int FirstArg = 1;
+  SubCommand *ChosenSubCommand = &*TopLevelSubCommand;
+  if (argc >= 2 && argv[FirstArg][0] != '-') {
+    // If the first argument specifies a valid subcommand, start processing
+    // options from the second argument.
+    ChosenSubCommand = LookupSubCommand(argv[FirstArg]);
+    if (ChosenSubCommand != &*TopLevelSubCommand)
+      FirstArg = 2;
+  }
+  GlobalParser->ActiveSubCommand = ChosenSubCommand;
+
+  assert(ChosenSubCommand);
+  auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt;
+  auto &PositionalOpts = ChosenSubCommand->PositionalOpts;
+  auto &SinkOpts = ChosenSubCommand->SinkOpts;
+  auto &OptionsMap = ChosenSubCommand->OptionsMap;
+
+  if (ConsumeAfterOpt) {
+    assert(PositionalOpts.size() > 0 &&
+           "Cannot specify cl::ConsumeAfter without a positional argument!");
+  }
+  if (!PositionalOpts.empty()) {
+
+    // Calculate how many positional values are _required_.
+    bool UnboundedFound = false;
+    for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
+      Option *Opt = PositionalOpts[i];
+      if (RequiresValue(Opt))
+        ++NumPositionalRequired;
+      else if (ConsumeAfterOpt) {
+        // ConsumeAfter cannot be combined with "optional" positional options
+        // unless there is only one positional argument...
+        if (PositionalOpts.size() > 1) {
+          if (!IgnoreErrors)
+            Opt->error("error - this positional option will never be matched, "
+                       "because it does not Require a value, and a "
+                       "cl::ConsumeAfter option is active!");
+          ErrorParsing = true;
+        }
+      } else if (UnboundedFound && !Opt->hasArgStr()) {
+        // This option does not "require" a value...  Make sure this option is
+        // not specified after an option that eats all extra arguments, or this
+        // one will never get any!
+        //
+        if (!IgnoreErrors) {
+          Opt->error("error - option can never match, because "
+                     "another positional argument will match an "
+                     "unbounded number of values, and this option"
+                     " does not require a value!");
+          errs() << ProgramName << ": CommandLine Error: Option '"
+                 << Opt->ArgStr << "' is all messed up!\n";
+          errs() << PositionalOpts.size();
+        }
+        ErrorParsing = true;
+      }
+      UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
+    }
+    HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt;
+  }
+
+  // PositionalVals - A vector of "positional" arguments we accumulate into
+  // the process at the end.
+  //
+  SmallVector<std::pair<StringRef, unsigned>, 4> PositionalVals;
+
+  // If the program has named positional arguments, and the name has been run
+  // across, keep track of which positional argument was named.  Otherwise put
+  // the positional args into the PositionalVals list...
+  Option *ActivePositionalArg = nullptr;
+
+  // Loop over all of the arguments... processing them.
+  bool DashDashFound = false; // Have we read '--'?
+  for (int i = FirstArg; i < argc; ++i) {
+    Option *Handler = nullptr;
+    Option *NearestHandler = nullptr;
+    std::string NearestHandlerString;
+    StringRef Value;
+    StringRef ArgName = "";
+
+    // Check to see if this is a positional argument.  This argument is
+    // considered to be positional if it doesn't start with '-', if it is "-"
+    // itself, or if we have seen "--" already.
+    //
+    if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) {
+      // Positional argument!
+      if (ActivePositionalArg) {
+        ProvidePositionalOption(ActivePositionalArg, argv[i], i);
+        continue; // We are done!
+      }
+
+      if (!PositionalOpts.empty()) {
+        PositionalVals.push_back(std::make_pair(argv[i], i));
+
+        // All of the positional arguments have been fulfulled, give the rest to
+        // the consume after option... if it's specified...
+        //
+        if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) {
+          for (++i; i < argc; ++i)
+            PositionalVals.push_back(std::make_pair(argv[i], i));
+          break; // Handle outside of the argument processing loop...
+        }
+
+        // Delay processing positional arguments until the end...
+        continue;
+      }
+    } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 &&
+               !DashDashFound) {
+      DashDashFound = true; // This is the mythical "--"?
+      continue;             // Don't try to process it as an argument itself.
+    } else if (ActivePositionalArg &&
+               (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) {
+      // If there is a positional argument eating options, check to see if this
+      // option is another positional argument.  If so, treat it as an argument,
+      // otherwise feed it to the eating positional.
+      ArgName = argv[i] + 1;
+      // Eat leading dashes.
+      while (!ArgName.empty() && ArgName[0] == '-')
+        ArgName = ArgName.substr(1);
+
+      Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
+      if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
+        ProvidePositionalOption(ActivePositionalArg, argv[i], i);
+        continue; // We are done!
+      }
+
+    } else { // We start with a '-', must be an argument.
+      ArgName = argv[i] + 1;
+      // Eat leading dashes.
+      while (!ArgName.empty() && ArgName[0] == '-')
+        ArgName = ArgName.substr(1);
+
+      Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
+
+      // Check to see if this "option" is really a prefixed or grouped argument.
+      if (!Handler)
+        Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,
+                                                OptionsMap);
+
+      // Otherwise, look for the closest available option to report to the user
+      // in the upcoming error.
+      if (!Handler && SinkOpts.empty())
+        NearestHandler =
+            LookupNearestOption(ArgName, OptionsMap, NearestHandlerString);
+    }
+
+    if (!Handler) {
+      if (SinkOpts.empty()) {
+        if (!IgnoreErrors) {
+          errs() << ProgramName << ": Unknown command line argument '"
+                 << argv[i] << "'.  Try: '" << argv[0] << " -help'\n";
+
+          if (NearestHandler) {
+            // If we know a near match, report it as well.
+            errs() << ProgramName << ": Did you mean '-" << NearestHandlerString
+                   << "'?\n";
+          }
+        }
+
+        ErrorParsing = true;
+      } else {
+        for (SmallVectorImpl<Option *>::iterator I = SinkOpts.begin(),
+                                                 E = SinkOpts.end();
+             I != E; ++I)
+          (*I)->addOccurrence(i, "", argv[i]);
+      }
+      continue;
+    }
+
+    // If this is a named positional argument, just remember that it is the
+    // active one...
+    if (Handler->getFormattingFlag() == cl::Positional)
+      ActivePositionalArg = Handler;
+    else
+      ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);
+  }
+
+  // Check and handle positional arguments now...
+  if (NumPositionalRequired > PositionalVals.size()) {
+    if (!IgnoreErrors) {
+      errs() << ProgramName
+             << ": Not enough positional command line arguments specified!\n"
+             << "Must specify at least " << NumPositionalRequired
+             << " positional argument" << (NumPositionalRequired > 1 ? "s" : "")
+             << ": See: " << argv[0] << " - help\n";
+    }
+
+    ErrorParsing = true;
+  } else if (!HasUnlimitedPositionals &&
+             PositionalVals.size() > PositionalOpts.size()) {
+    if (!IgnoreErrors) {
+      errs() << ProgramName << ": Too many positional arguments specified!\n"
+             << "Can specify at most " << PositionalOpts.size()
+             << " positional arguments: See: " << argv[0] << " -help\n";
+    }
+    ErrorParsing = true;
+
+  } else if (!ConsumeAfterOpt) {
+    // Positional args have already been handled if ConsumeAfter is specified.
+    unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size());
+    for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
+      if (RequiresValue(PositionalOpts[i])) {
+        ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first,
+                                PositionalVals[ValNo].second);
+        ValNo++;
+        --NumPositionalRequired; // We fulfilled our duty...
+      }
+
+      // If we _can_ give this option more arguments, do so now, as long as we
+      // do not give it values that others need.  'Done' controls whether the
+      // option even _WANTS_ any more.
+      //
+      bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required;
+      while (NumVals - ValNo > NumPositionalRequired && !Done) {
+        switch (PositionalOpts[i]->getNumOccurrencesFlag()) {
+        case cl::Optional:
+          Done = true; // Optional arguments want _at most_ one value
+          LLVM_FALLTHROUGH;
+        case cl::ZeroOrMore: // Zero or more will take all they can get...
+        case cl::OneOrMore:  // One or more will take all they can get...
+          ProvidePositionalOption(PositionalOpts[i],
+                                  PositionalVals[ValNo].first,
+                                  PositionalVals[ValNo].second);
+          ValNo++;
+          break;
+        default:
+          llvm_unreachable("Internal error, unexpected NumOccurrences flag in "
+                           "positional argument processing!");
+        }
+      }
+    }
+  } else {
+    assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size());
+    unsigned ValNo = 0;
+    for (size_t j = 1, e = PositionalOpts.size(); j != e; ++j)
+      if (RequiresValue(PositionalOpts[j])) {
+        ErrorParsing |= ProvidePositionalOption(PositionalOpts[j],
+                                                PositionalVals[ValNo].first,
+                                                PositionalVals[ValNo].second);
+        ValNo++;
+      }
+
+    // Handle the case where there is just one positional option, and it's
+    // optional.  In this case, we want to give JUST THE FIRST option to the
+    // positional option and keep the rest for the consume after.  The above
+    // loop would have assigned no values to positional options in this case.
+    //
+    if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) {
+      ErrorParsing |= ProvidePositionalOption(PositionalOpts[0],
+                                              PositionalVals[ValNo].first,
+                                              PositionalVals[ValNo].second);
+      ValNo++;
+    }
+
+    // Handle over all of the rest of the arguments to the
+    // cl::ConsumeAfter command line option...
+    for (; ValNo != PositionalVals.size(); ++ValNo)
+      ErrorParsing |=
+          ProvidePositionalOption(ConsumeAfterOpt, PositionalVals[ValNo].first,
+                                  PositionalVals[ValNo].second);
+  }
+
+  // Loop over args and make sure all required args are specified!
+  for (const auto &Opt : OptionsMap) {
+    switch (Opt.second->getNumOccurrencesFlag()) {
+    case Required:
+    case OneOrMore:
+      if (Opt.second->getNumOccurrences() == 0) {
+        Opt.second->error("must be specified at least once!");
+        ErrorParsing = true;
+      }
+      LLVM_FALLTHROUGH;
+    default:
+      break;
+    }
+  }
+
+  // Now that we know if -debug is specified, we can use it.
+  // Note that if ReadResponseFiles == true, this must be done before the
+  // memory allocated for the expanded command line is free()d below.
+  DEBUG(dbgs() << "Args: ";
+        for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' ';
+        dbgs() << '\n';);
+
+  // Free all of the memory allocated to the map.  Command line options may only
+  // be processed once!
+  MoreHelp.clear();
+
+  // If we had an error processing our arguments, don't let the program execute
+  if (ErrorParsing) {
+    if (!IgnoreErrors)
+      exit(1);
+    return false;
+  }
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Option Base class implementation
+//
+
+bool Option::error(const Twine &Message, StringRef ArgName) {
+  if (!ArgName.data())
+    ArgName = ArgStr;
+  if (ArgName.empty())
+    errs() << HelpStr; // Be nice for positional arguments
+  else
+    errs() << GlobalParser->ProgramName << ": for the -" << ArgName;
+
+  errs() << " option: " << Message << "\n";
+  return true;
+}
+
+bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value,
+                           bool MultiArg) {
+  if (!MultiArg)
+    NumOccurrences++; // Increment the number of times we have been seen
+
+  switch (getNumOccurrencesFlag()) {
+  case Optional:
+    if (NumOccurrences > 1)
+      return error("may only occur zero or one times!", ArgName);
+    break;
+  case Required:
+    if (NumOccurrences > 1)
+      return error("must occur exactly one time!", ArgName);
+    LLVM_FALLTHROUGH;
+  case OneOrMore:
+  case ZeroOrMore:
+  case ConsumeAfter:
+    break;
+  }
+
+  return handleOccurrence(pos, ArgName, Value);
+}
+
+// getValueStr - Get the value description string, using "DefaultMsg" if nothing
+// has been specified yet.
+//
+static StringRef getValueStr(const Option &O, StringRef DefaultMsg) {
+  if (O.ValueStr.empty())
+    return DefaultMsg;
+  return O.ValueStr;
+}
+
+//===----------------------------------------------------------------------===//
+// cl::alias class implementation
+//
+
+// Return the width of the option tag for printing...
+size_t alias::getOptionWidth() const { return ArgStr.size() + 6; }
+
+static void printHelpStr(StringRef HelpStr, size_t Indent,
+                         size_t FirstLineIndentedBy) {
+  std::pair<StringRef, StringRef> Split = HelpStr.split('\n');
+  outs().indent(Indent - FirstLineIndentedBy) << " - " << Split.first << "\n";
+  while (!Split.second.empty()) {
+    Split = Split.second.split('\n');
+    outs().indent(Indent) << Split.first << "\n";
+  }
+}
+
+// Print out the option for the alias.
+void alias::printOptionInfo(size_t GlobalWidth) const {
+  outs() << "  -" << ArgStr;
+  printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6);
+}
+
+//===----------------------------------------------------------------------===//
+// Parser Implementation code...
+//
+
+// basic_parser implementation
+//
+
+// Return the width of the option tag for printing...
+size_t basic_parser_impl::getOptionWidth(const Option &O) const {
+  size_t Len = O.ArgStr.size();
+  if (const char *ValName = getValueName())
+    Len += getValueStr(O, ValName).size() + 3;
+
+  return Len + 6;
+}
+
+// printOptionInfo - Print out information about this option.  The
+// to-be-maintained width is specified.
+//
+void basic_parser_impl::printOptionInfo(const Option &O,
+                                        size_t GlobalWidth) const {
+  outs() << "  -" << O.ArgStr;
+
+  if (const char *ValName = getValueName())
+    outs() << "=<" << getValueStr(O, ValName) << '>';
+
+  printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O));
+}
+
+void basic_parser_impl::printOptionName(const Option &O,
+                                        size_t GlobalWidth) const {
+  outs() << "  -" << O.ArgStr;
+  outs().indent(GlobalWidth - O.ArgStr.size());
+}
+
+// parser<bool> implementation
+//
+bool parser<bool>::parse(Option &O, StringRef ArgName, StringRef Arg,
+                         bool &Value) {
+  if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
+      Arg == "1") {
+    Value = true;
+    return false;
+  }
+
+  if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
+    Value = false;
+    return false;
+  }
+  return O.error("'" + Arg +
+                 "' is invalid value for boolean argument! Try 0 or 1");
+}
+
+// parser<boolOrDefault> implementation
+//
+bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, StringRef Arg,
+                                  boolOrDefault &Value) {
+  if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
+      Arg == "1") {
+    Value = BOU_TRUE;
+    return false;
+  }
+  if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
+    Value = BOU_FALSE;
+    return false;
+  }
+
+  return O.error("'" + Arg +
+                 "' is invalid value for boolean argument! Try 0 or 1");
+}
+
+// parser<int> implementation
+//
+bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg,
+                        int &Value) {
+  if (Arg.getAsInteger(0, Value))
+    return O.error("'" + Arg + "' value invalid for integer argument!");
+  return false;
+}
+
+// parser<unsigned> implementation
+//
+bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg,
+                             unsigned &Value) {
+
+  if (Arg.getAsInteger(0, Value))
+    return O.error("'" + Arg + "' value invalid for uint argument!");
+  return false;
+}
+
+// parser<unsigned long long> implementation
+//
+bool parser<unsigned long long>::parse(Option &O, StringRef ArgName,
+                                       StringRef Arg,
+                                       unsigned long long &Value) {
+
+  if (Arg.getAsInteger(0, Value))
+    return O.error("'" + Arg + "' value invalid for uint argument!");
+  return false;
+}
+
+// parser<double>/parser<float> implementation
+//
+static bool parseDouble(Option &O, StringRef Arg, double &Value) {
+  SmallString<32> TmpStr(Arg.begin(), Arg.end());
+  const char *ArgStart = TmpStr.c_str();
+  char *End;
+  Value = strtod(ArgStart, &End);
+  if (*End != 0)
+    return O.error("'" + Arg + "' value invalid for floating point argument!");
+  return false;
+}
+
+bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg,
+                           double &Val) {
+  return parseDouble(O, Arg, Val);
+}
+
+bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg,
+                          float &Val) {
+  double dVal;
+  if (parseDouble(O, Arg, dVal))
+    return true;
+  Val = (float)dVal;
+  return false;
+}
+
+// generic_parser_base implementation
+//
+
+// findOption - Return the option number corresponding to the specified
+// argument string.  If the option is not found, getNumOptions() is returned.
+//
+unsigned generic_parser_base::findOption(const char *Name) {
+  unsigned e = getNumOptions();
+
+  for (unsigned i = 0; i != e; ++i) {
+    if (strcmp(getOption(i), Name) == 0)
+      return i;
+  }
+  return e;
+}
+
+// Return the width of the option tag for printing...
+size_t generic_parser_base::getOptionWidth(const Option &O) const {
+  if (O.hasArgStr()) {
+    size_t Size = O.ArgStr.size() + 6;
+    for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
+      Size = std::max(Size, std::strlen(getOption(i)) + 8);
+    return Size;
+  } else {
+    size_t BaseSize = 0;
+    for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
+      BaseSize = std::max(BaseSize, std::strlen(getOption(i)) + 8);
+    return BaseSize;
+  }
+}
+
+// printOptionInfo - Print out information about this option.  The
+// to-be-maintained width is specified.
+//
+void generic_parser_base::printOptionInfo(const Option &O,
+                                          size_t GlobalWidth) const {
+  if (O.hasArgStr()) {
+    outs() << "  -" << O.ArgStr;
+    printHelpStr(O.HelpStr, GlobalWidth, O.ArgStr.size() + 6);
+
+    for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+      size_t NumSpaces = GlobalWidth - strlen(getOption(i)) - 8;
+      outs() << "    =" << getOption(i);
+      outs().indent(NumSpaces) << " -   " << getDescription(i) << '\n';
+    }
+  } else {
+    if (!O.HelpStr.empty())
+      outs() << "  " << O.HelpStr << '\n';
+    for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+      const char *Option = getOption(i);
+      outs() << "    -" << Option;
+      printHelpStr(getDescription(i), GlobalWidth, std::strlen(Option) + 8);
+    }
+  }
+}
+
+static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff
+
+// printGenericOptionDiff - Print the value of this option and it's default.
+//
+// "Generic" options have each value mapped to a name.
+void generic_parser_base::printGenericOptionDiff(
+    const Option &O, const GenericOptionValue &Value,
+    const GenericOptionValue &Default, size_t GlobalWidth) const {
+  outs() << "  -" << O.ArgStr;
+  outs().indent(GlobalWidth - O.ArgStr.size());
+
+  unsigned NumOpts = getNumOptions();
+  for (unsigned i = 0; i != NumOpts; ++i) {
+    if (Value.compare(getOptionValue(i)))
+      continue;
+
+    outs() << "= " << getOption(i);
+    size_t L = std::strlen(getOption(i));
+    size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0;
+    outs().indent(NumSpaces) << " (default: ";
+    for (unsigned j = 0; j != NumOpts; ++j) {
+      if (Default.compare(getOptionValue(j)))
+        continue;
+      outs() << getOption(j);
+      break;
+    }
+    outs() << ")\n";
+    return;
+  }
+  outs() << "= *unknown option value*\n";
+}
+
+// printOptionDiff - Specializations for printing basic value types.
+//
+#define PRINT_OPT_DIFF(T)                                                      \
+  void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D,      \
+                                  size_t GlobalWidth) const {                  \
+    printOptionName(O, GlobalWidth);                                           \
+    std::string Str;                                                           \
+    {                                                                          \
+      raw_string_ostream SS(Str);                                              \
+      SS << V;                                                                 \
+    }                                                                          \
+    outs() << "= " << Str;                                                     \
+    size_t NumSpaces =                                                         \
+        MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0;               \
+    outs().indent(NumSpaces) << " (default: ";                                 \
+    if (D.hasValue())                                                          \
+      outs() << D.getValue();                                                  \
+    else                                                                       \
+      outs() << "*no default*";                                                \
+    outs() << ")\n";                                                           \
+  }
+
+PRINT_OPT_DIFF(bool)
+PRINT_OPT_DIFF(boolOrDefault)
+PRINT_OPT_DIFF(int)
+PRINT_OPT_DIFF(unsigned)
+PRINT_OPT_DIFF(unsigned long long)
+PRINT_OPT_DIFF(double)
+PRINT_OPT_DIFF(float)
+PRINT_OPT_DIFF(char)
+
+void parser<std::string>::printOptionDiff(const Option &O, StringRef V,
+                                          const OptionValue<std::string> &D,
+                                          size_t GlobalWidth) const {
+  printOptionName(O, GlobalWidth);
+  outs() << "= " << V;
+  size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0;
+  outs().indent(NumSpaces) << " (default: ";
+  if (D.hasValue())
+    outs() << D.getValue();
+  else
+    outs() << "*no default*";
+  outs() << ")\n";
+}
+
+// Print a placeholder for options that don't yet support printOptionDiff().
+void basic_parser_impl::printOptionNoValue(const Option &O,
+                                           size_t GlobalWidth) const {
+  printOptionName(O, GlobalWidth);
+  outs() << "= *cannot print option value*\n";
+}
+
+//===----------------------------------------------------------------------===//
+// -help and -help-hidden option implementation
+//
+
+static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
+                          const std::pair<const char *, Option *> *RHS) {
+  return strcmp(LHS->first, RHS->first);
+}
+
+static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS,
+                          const std::pair<const char *, SubCommand *> *RHS) {
+  return strcmp(LHS->first, RHS->first);
+}
+
+// Copy Options into a vector so we can sort them as we like.
+static void sortOpts(StringMap<Option *> &OptMap,
+                     SmallVectorImpl<std::pair<const char *, Option *>> &Opts,
+                     bool ShowHidden) {
+  SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection.
+
+  for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end();
+       I != E; ++I) {
+    // Ignore really-hidden options.
+    if (I->second->getOptionHiddenFlag() == ReallyHidden)
+      continue;
+
+    // Unless showhidden is set, ignore hidden flags.
+    if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
+      continue;
+
+    // If we've already seen this option, don't add it to the list again.
+    if (!OptionSet.insert(I->second).second)
+      continue;
+
+    Opts.push_back(
+        std::pair<const char *, Option *>(I->getKey().data(), I->second));
+  }
+
+  // Sort the options list alphabetically.
+  array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);
+}
+
+static void
+sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap,
+                SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {
+  for (const auto &S : SubMap) {
+    if (S->getName() == nullptr)
+      continue;
+    Subs.push_back(std::make_pair(S->getName(), S));
+  }
+  array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare);
+}
+
+namespace {
+
+class HelpPrinter {
+protected:
+  const bool ShowHidden;
+  typedef SmallVector<std::pair<const char *, Option *>, 128>
+      StrOptionPairVector;
+  typedef SmallVector<std::pair<const char *, SubCommand *>, 128>
+      StrSubCommandPairVector;
+  // Print the options. Opts is assumed to be alphabetically sorted.
+  virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) {
+    for (size_t i = 0, e = Opts.size(); i != e; ++i)
+      Opts[i].second->printOptionInfo(MaxArgLen);
+  }
+
+  void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) {
+    for (const auto &S : Subs) {
+      outs() << "  " << S.first;
+      if (S.second->getDescription()) {
+        outs().indent(MaxSubLen - strlen(S.first));
+        outs() << " - " << S.second->getDescription();
+      }
+      outs() << "\n";
+    }
+  }
+
+public:
+  explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {}
+  virtual ~HelpPrinter() {}
+
+  // Invoke the printer.
+  void operator=(bool Value) {
+    if (!Value)
+      return;
+
+    SubCommand *Sub = GlobalParser->getActiveSubCommand();
+    auto &OptionsMap = Sub->OptionsMap;
+    auto &PositionalOpts = Sub->PositionalOpts;
+    auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt;
+
+    StrOptionPairVector Opts;
+    sortOpts(OptionsMap, Opts, ShowHidden);
+
+    StrSubCommandPairVector Subs;
+    sortSubCommands(GlobalParser->RegisteredSubCommands, Subs);
+
+    if (GlobalParser->ProgramOverview)
+      outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
+
+    if (Sub == &*TopLevelSubCommand)
+      outs() << "USAGE: " << GlobalParser->ProgramName
+             << " [subcommand] [options]";
+    else {
+      if (Sub->getDescription() != nullptr) {
+        outs() << "SUBCOMMAND '" << Sub->getName()
+               << "': " << Sub->getDescription() << "\n\n";
+      }
+      outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName()
+             << " [options]";
+    }
+
+    for (auto Opt : PositionalOpts) {
+      if (Opt->hasArgStr())
+        outs() << " --" << Opt->ArgStr;
+      outs() << " " << Opt->HelpStr;
+    }
+
+    // Print the consume after option info if it exists...
+    if (ConsumeAfterOpt)
+      outs() << " " << ConsumeAfterOpt->HelpStr;
+
+    if (Sub == &*TopLevelSubCommand && Subs.size() > 2) {
+      // Compute the maximum subcommand length...
+      size_t MaxSubLen = 0;
+      for (size_t i = 0, e = Subs.size(); i != e; ++i)
+        MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first));
+
+      outs() << "\n\n";
+      outs() << "SUBCOMMANDS:\n\n";
+      printSubCommands(Subs, MaxSubLen);
+      outs() << "\n";
+      outs() << "  Type \"" << GlobalParser->ProgramName
+             << " <subcommand> -help\" to get more help on a specific "
+                "subcommand";
+    }
+
+    outs() << "\n\n";
+
+    // Compute the maximum argument length...
+    size_t MaxArgLen = 0;
+    for (size_t i = 0, e = Opts.size(); i != e; ++i)
+      MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
+
+    outs() << "OPTIONS:\n";
+    printOptions(Opts, MaxArgLen);
+
+    // Print any extra help the user has declared.
+    for (auto I : GlobalParser->MoreHelp)
+      outs() << I;
+    GlobalParser->MoreHelp.clear();
+
+    // Halt the program since help information was printed
+    exit(0);
+  }
+};
+
+class CategorizedHelpPrinter : public HelpPrinter {
+public:
+  explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {}
+
+  // Helper function for printOptions().
+  // It shall return a negative value if A's name should be lexicographically
+  // ordered before B's name. It returns a value greater equal zero otherwise.
+  static int OptionCategoryCompare(OptionCategory *const *A,
+                                   OptionCategory *const *B) {
+    return strcmp((*A)->getName(), (*B)->getName());
+  }
+
+  // Make sure we inherit our base class's operator=()
+  using HelpPrinter::operator=;
+
+protected:
+  void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override {
+    std::vector<OptionCategory *> SortedCategories;
+    std::map<OptionCategory *, std::vector<Option *>> CategorizedOptions;
+
+    // Collect registered option categories into vector in preparation for
+    // sorting.
+    for (auto I = GlobalParser->RegisteredOptionCategories.begin(),
+              E = GlobalParser->RegisteredOptionCategories.end();
+         I != E; ++I) {
+      SortedCategories.push_back(*I);
+    }
+
+    // Sort the different option categories alphabetically.
+    assert(SortedCategories.size() > 0 && "No option categories registered!");
+    array_pod_sort(SortedCategories.begin(), SortedCategories.end(),
+                   OptionCategoryCompare);
+
+    // Create map to empty vectors.
+    for (std::vector<OptionCategory *>::const_iterator
+             I = SortedCategories.begin(),
+             E = SortedCategories.end();
+         I != E; ++I)
+      CategorizedOptions[*I] = std::vector<Option *>();
+
+    // Walk through pre-sorted options and assign into categories.
+    // Because the options are already alphabetically sorted the
+    // options within categories will also be alphabetically sorted.
+    for (size_t I = 0, E = Opts.size(); I != E; ++I) {
+      Option *Opt = Opts[I].second;
+      assert(CategorizedOptions.count(Opt->Category) > 0 &&
+             "Option has an unregistered category");
+      CategorizedOptions[Opt->Category].push_back(Opt);
+    }
+
+    // Now do printing.
+    for (std::vector<OptionCategory *>::const_iterator
+             Category = SortedCategories.begin(),
+             E = SortedCategories.end();
+         Category != E; ++Category) {
+      // Hide empty categories for -help, but show for -help-hidden.
+      const auto &CategoryOptions = CategorizedOptions[*Category];
+      bool IsEmptyCategory = CategoryOptions.empty();
+      if (!ShowHidden && IsEmptyCategory)
+        continue;
+
+      // Print category information.
+      outs() << "\n";
+      outs() << (*Category)->getName() << ":\n";
+
+      // Check if description is set.
+      if ((*Category)->getDescription() != nullptr)
+        outs() << (*Category)->getDescription() << "\n\n";
+      else
+        outs() << "\n";
+
+      // When using -help-hidden explicitly state if the category has no
+      // options associated with it.
+      if (IsEmptyCategory) {
+        outs() << "  This option category has no options.\n";
+        continue;
+      }
+      // Loop over the options in the category and print.
+      for (const Option *Opt : CategoryOptions)
+        Opt->printOptionInfo(MaxArgLen);
+    }
+  }
+};
+
+// This wraps the Uncategorizing and Categorizing printers and decides
+// at run time which should be invoked.
+class HelpPrinterWrapper {
+private:
+  HelpPrinter &UncategorizedPrinter;
+  CategorizedHelpPrinter &CategorizedPrinter;
+
+public:
+  explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter,
+                              CategorizedHelpPrinter &CategorizedPrinter)
+      : UncategorizedPrinter(UncategorizedPrinter),
+        CategorizedPrinter(CategorizedPrinter) {}
+
+  // Invoke the printer.
+  void operator=(bool Value);
+};
+
+} // End anonymous namespace
+
+// Declare the four HelpPrinter instances that are used to print out help, or
+// help-hidden as an uncategorized list or in categories.
+static HelpPrinter UncategorizedNormalPrinter(false);
+static HelpPrinter UncategorizedHiddenPrinter(true);
+static CategorizedHelpPrinter CategorizedNormalPrinter(false);
+static CategorizedHelpPrinter CategorizedHiddenPrinter(true);
+
+// Declare HelpPrinter wrappers that will decide whether or not to invoke
+// a categorizing help printer
+static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter,
+                                               CategorizedNormalPrinter);
+static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter,
+                                               CategorizedHiddenPrinter);
+
+// Define a category for generic options that all tools should have.
+static cl::OptionCategory GenericCategory("Generic Options");
+
+// Define uncategorized help printers.
+// -help-list is hidden by default because if Option categories are being used
+// then -help behaves the same as -help-list.
+static cl::opt<HelpPrinter, true, parser<bool>> HLOp(
+    "help-list",
+    cl::desc("Display list of available options (-help-list-hidden for more)"),
+    cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed,
+    cl::cat(GenericCategory), cl::sub(*AllSubCommands));
+
+static cl::opt<HelpPrinter, true, parser<bool>>
+    HLHOp("help-list-hidden", cl::desc("Display list of all available options"),
+          cl::location(UncategorizedHiddenPrinter), cl::Hidden,
+          cl::ValueDisallowed, cl::cat(GenericCategory),
+          cl::sub(*AllSubCommands));
+
+// Define uncategorized/categorized help printers. These printers change their
+// behaviour at runtime depending on whether one or more Option categories have
+// been declared.
+static cl::opt<HelpPrinterWrapper, true, parser<bool>>
+    HOp("help", cl::desc("Display available options (-help-hidden for more)"),
+        cl::location(WrappedNormalPrinter), cl::ValueDisallowed,
+        cl::cat(GenericCategory), cl::sub(*AllSubCommands));
+
+static cl::opt<HelpPrinterWrapper, true, parser<bool>>
+    HHOp("help-hidden", cl::desc("Display all available options"),
+         cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed,
+         cl::cat(GenericCategory), cl::sub(*AllSubCommands));
+
+static cl::opt<bool> PrintOptions(
+    "print-options",
+    cl::desc("Print non-default options after command line parsing"),
+    cl::Hidden, cl::init(false), cl::cat(GenericCategory),
+    cl::sub(*AllSubCommands));
+
+static cl::opt<bool> PrintAllOptions(
+    "print-all-options",
+    cl::desc("Print all option values after command line parsing"), cl::Hidden,
+    cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands));
+
+void HelpPrinterWrapper::operator=(bool Value) {
+  if (!Value)
+    return;
+
+  // Decide which printer to invoke. If more than one option category is
+  // registered then it is useful to show the categorized help instead of
+  // uncategorized help.
+  if (GlobalParser->RegisteredOptionCategories.size() > 1) {
+    // unhide -help-list option so user can have uncategorized output if they
+    // want it.
+    HLOp.setHiddenFlag(NotHidden);
+
+    CategorizedPrinter = true; // Invoke categorized printer
+  } else
+    UncategorizedPrinter = true; // Invoke uncategorized printer
+}
+
+// Print the value of each option.
+void cl::PrintOptionValues() { GlobalParser->printOptionValues(); }
+
+void CommandLineParser::printOptionValues() {
+  if (!PrintOptions && !PrintAllOptions)
+    return;
+
+  SmallVector<std::pair<const char *, Option *>, 128> Opts;
+  sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true);
+
+  // Compute the maximum argument length...
+  size_t MaxArgLen = 0;
+  for (size_t i = 0, e = Opts.size(); i != e; ++i)
+    MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
+
+  for (size_t i = 0, e = Opts.size(); i != e; ++i)
+    Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions);
+}
+
+static void (*OverrideVersionPrinter)() = nullptr;
+
+static std::vector<void (*)()> *ExtraVersionPrinters = nullptr;
+
+namespace {
+class VersionPrinter {
+public:
+  void print() {
+    raw_ostream &OS = outs();
+#ifdef PACKAGE_VENDOR
+    OS << PACKAGE_VENDOR << " ";
+#else
+    OS << "LLVM (http://llvm.org/):\n  ";
+#endif
+    OS << PACKAGE_NAME << " version " << PACKAGE_VERSION;
+#ifdef LLVM_VERSION_INFO
+    OS << " " << LLVM_VERSION_INFO;
+#endif
+    OS << "\n  ";
+#ifndef __OPTIMIZE__
+    OS << "DEBUG build";
+#else
+    OS << "Optimized build";
+#endif
+#ifndef NDEBUG
+    OS << " with assertions";
+#endif
+    std::string CPU = sys::getHostCPUName();
+    if (CPU == "generic")
+      CPU = "(unknown)";
+    OS << ".\n"
+       << "  Default target: " << sys::getDefaultTargetTriple() << '\n'
+       << "  Host CPU: " << CPU << '\n';
+  }
+  void operator=(bool OptionWasSpecified) {
+    if (!OptionWasSpecified)
+      return;
+
+    if (OverrideVersionPrinter != nullptr) {
+      (*OverrideVersionPrinter)();
+      exit(0);
+    }
+    print();
+
+    // Iterate over any registered extra printers and call them to add further
+    // information.
+    if (ExtraVersionPrinters != nullptr) {
+      outs() << '\n';
+      for (std::vector<void (*)()>::iterator I = ExtraVersionPrinters->begin(),
+                                             E = ExtraVersionPrinters->end();
+           I != E; ++I)
+        (*I)();
+    }
+
+    exit(0);
+  }
+};
+} // End anonymous namespace
+
+// Define the --version option that prints out the LLVM version for the tool
+static VersionPrinter VersionPrinterInstance;
+
+static cl::opt<VersionPrinter, true, parser<bool>>
+    VersOp("version", cl::desc("Display the version of this program"),
+           cl::location(VersionPrinterInstance), cl::ValueDisallowed,
+           cl::cat(GenericCategory));
+
+// Utility function for printing the help message.
+void cl::PrintHelpMessage(bool Hidden, bool Categorized) {
+  // This looks weird, but it actually prints the help message. The Printers are
+  // types of HelpPrinter and the help gets printed when its operator= is
+  // invoked. That's because the "normal" usages of the help printer is to be
+  // assigned true/false depending on whether -help or -help-hidden was given or
+  // not.  Since we're circumventing that we have to make it look like -help or
+  // -help-hidden were given, so we assign true.
+
+  if (!Hidden && !Categorized)
+    UncategorizedNormalPrinter = true;
+  else if (!Hidden && Categorized)
+    CategorizedNormalPrinter = true;
+  else if (Hidden && !Categorized)
+    UncategorizedHiddenPrinter = true;
+  else
+    CategorizedHiddenPrinter = true;
+}
+
+/// Utility function for printing version number.
+void cl::PrintVersionMessage() { VersionPrinterInstance.print(); }
+
+void cl::SetVersionPrinter(void (*func)()) { OverrideVersionPrinter = func; }
+
+void cl::AddExtraVersionPrinter(void (*func)()) {
+  if (!ExtraVersionPrinters)
+    ExtraVersionPrinters = new std::vector<void (*)()>;
+
+  ExtraVersionPrinters->push_back(func);
+}
+
+StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {
+  auto &Subs = GlobalParser->RegisteredSubCommands;
+  (void)Subs;
+  assert(is_contained(Subs, &Sub));
+  return Sub.OptionsMap;
+}
+
+void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
+  for (auto &I : Sub.OptionsMap) {
+    if (I.second->Category != &Category &&
+        I.second->Category != &GenericCategory)
+      I.second->setHiddenFlag(cl::ReallyHidden);
+  }
+}
+
+void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
+                              SubCommand &Sub) {
+  auto CategoriesBegin = Categories.begin();
+  auto CategoriesEnd = Categories.end();
+  for (auto &I : Sub.OptionsMap) {
+    if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
+            CategoriesEnd &&
+        I.second->Category != &GenericCategory)
+      I.second->setHiddenFlag(cl::ReallyHidden);
+  }
+}
+
+void cl::ResetCommandLineParser() { GlobalParser->reset(); }
+void cl::ResetAllOptionOccurrences() {
+  GlobalParser->ResetAllOptionOccurrences();
+}
+
+void LLVMParseCommandLineOptions(int argc, const char *const *argv,
+                                 const char *Overview) {
+  llvm::cl::ParseCommandLineOptions(argc, argv, Overview, true);
+}
diff --git a/third_party/llvm-subzero/lib/Support/ConvertUTF.c b/third_party/llvm-subzero/lib/Support/ConvertUTF.c
new file mode 100644
index 0000000..128459a
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/ConvertUTF.c
@@ -0,0 +1,708 @@
+/*===--- ConvertUTF.c - Universal Character Names conversions ---------------===
+ *
+ *                     The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *===------------------------------------------------------------------------=*/
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ * 
+ * Disclaimer
+ * 
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ * 
+ * Limitations on Rights to Redistribute This Code
+ * 
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+    Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+    Author: Mark E. Davis, 1994.
+    Rev History: Rick McGowan, fixes & updates May 2001.
+    Sept 2001: fixed const & error conditions per
+        mods suggested by S. Parent & A. Lillich.
+    June 2002: Tim Dodd added detection and handling of incomplete
+        source sequences, enhanced error detection, added casts
+        to eliminate compiler warnings.
+    July 2003: slight mods to back out aggressive FFFE detection.
+    Jan 2004: updated switches in from-UTF8 conversions.
+    Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+
+    See the header file "ConvertUTF.h" for complete documentation.
+
+------------------------------------------------------------------------ */
+
+
+#include "llvm/Support/ConvertUTF.h"
+#ifdef CVTUTF_DEBUG
+#include <stdio.h>
+#endif
+#include <assert.h>
+
+static const int halfShift  = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START  (UTF32)0xD800
+#define UNI_SUR_HIGH_END    (UTF32)0xDBFF
+#define UNI_SUR_LOW_START   (UTF32)0xDC00
+#define UNI_SUR_LOW_END     (UTF32)0xDFFF
+#define false      0
+#define true        1
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms.
+ */
+static const char trailingBytesForUTF8[256] = {
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 
+                     0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow.  There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
+ */
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "isLegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16 (
+        const UTF32** sourceStart, const UTF32* sourceEnd, 
+        UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+    ConversionResult result = conversionOK;
+    const UTF32* source = *sourceStart;
+    UTF16* target = *targetStart;
+    while (source < sourceEnd) {
+        UTF32 ch;
+        if (target >= targetEnd) {
+            result = targetExhausted; break;
+        }
+        ch = *source++;
+        if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+            /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+                if (flags == strictConversion) {
+                    --source; /* return to the illegal value itself */
+                    result = sourceIllegal;
+                    break;
+                } else {
+                    *target++ = UNI_REPLACEMENT_CHAR;
+                }
+            } else {
+                *target++ = (UTF16)ch; /* normal case */
+            }
+        } else if (ch > UNI_MAX_LEGAL_UTF32) {
+            if (flags == strictConversion) {
+                result = sourceIllegal;
+            } else {
+                *target++ = UNI_REPLACEMENT_CHAR;
+            }
+        } else {
+            /* target is a character in range 0xFFFF - 0x10FFFF. */
+            if (target + 1 >= targetEnd) {
+                --source; /* Back up source pointer! */
+                result = targetExhausted; break;
+            }
+            ch -= halfBase;
+            *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+            *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+        }
+    }
+    *sourceStart = source;
+    *targetStart = target;
+    return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF32 (
+        const UTF16** sourceStart, const UTF16* sourceEnd, 
+        UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+    ConversionResult result = conversionOK;
+    const UTF16* source = *sourceStart;
+    UTF32* target = *targetStart;
+    UTF32 ch, ch2;
+    while (source < sourceEnd) {
+        const UTF16* oldSource = source; /*  In case we have to back up because of target overflow. */
+        ch = *source++;
+        /* If we have a surrogate pair, convert to UTF32 first. */
+        if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+            /* If the 16 bits following the high surrogate are in the source buffer... */
+            if (source < sourceEnd) {
+                ch2 = *source;
+                /* If it's a low surrogate, convert to UTF32. */
+                if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+                    ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+                        + (ch2 - UNI_SUR_LOW_START) + halfBase;
+                    ++source;
+                } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+                    --source; /* return to the illegal value itself */
+                    result = sourceIllegal;
+                    break;
+                }
+            } else { /* We don't have the 16 bits following the high surrogate. */
+                --source; /* return to the high surrogate */
+                result = sourceExhausted;
+                break;
+            }
+        } else if (flags == strictConversion) {
+            /* UTF-16 surrogate values are illegal in UTF-32 */
+            if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+                --source; /* return to the illegal value itself */
+                result = sourceIllegal;
+                break;
+            }
+        }
+        if (target >= targetEnd) {
+            source = oldSource; /* Back up source pointer! */
+            result = targetExhausted; break;
+        }
+        *target++ = ch;
+    }
+    *sourceStart = source;
+    *targetStart = target;
+#ifdef CVTUTF_DEBUG
+if (result == sourceIllegal) {
+    fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
+    fflush(stderr);
+}
+#endif
+    return result;
+}
+ConversionResult ConvertUTF16toUTF8 (
+        const UTF16** sourceStart, const UTF16* sourceEnd, 
+        UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+    ConversionResult result = conversionOK;
+    const UTF16* source = *sourceStart;
+    UTF8* target = *targetStart;
+    while (source < sourceEnd) {
+        UTF32 ch;
+        unsigned short bytesToWrite = 0;
+        const UTF32 byteMask = 0xBF;
+        const UTF32 byteMark = 0x80; 
+        const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+        ch = *source++;
+        /* If we have a surrogate pair, convert to UTF32 first. */
+        if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+            /* If the 16 bits following the high surrogate are in the source buffer... */
+            if (source < sourceEnd) {
+                UTF32 ch2 = *source;
+                /* If it's a low surrogate, convert to UTF32. */
+                if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+                    ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+                        + (ch2 - UNI_SUR_LOW_START) + halfBase;
+                    ++source;
+                } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+                    --source; /* return to the illegal value itself */
+                    result = sourceIllegal;
+                    break;
+                }
+            } else { /* We don't have the 16 bits following the high surrogate. */
+                --source; /* return to the high surrogate */
+                result = sourceExhausted;
+                break;
+            }
+        } else if (flags == strictConversion) {
+            /* UTF-16 surrogate values are illegal in UTF-32 */
+            if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+                --source; /* return to the illegal value itself */
+                result = sourceIllegal;
+                break;
+            }
+        }
+        /* Figure out how many bytes the result will require */
+        if (ch < (UTF32)0x80) {      bytesToWrite = 1;
+        } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
+        } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
+        } else if (ch < (UTF32)0x110000) {  bytesToWrite = 4;
+        } else {                            bytesToWrite = 3;
+                                            ch = UNI_REPLACEMENT_CHAR;
+        }
+
+        target += bytesToWrite;
+        if (target > targetEnd) {
+            source = oldSource; /* Back up source pointer! */
+            target -= bytesToWrite; result = targetExhausted; break;
+        }
+        switch (bytesToWrite) { /* note: everything falls through. */
+            case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+            case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+            case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+            case 1: *--target =  (UTF8)(ch | firstByteMark[bytesToWrite]);
+        }
+        target += bytesToWrite;
+    }
+    *sourceStart = source;
+    *targetStart = target;
+    return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF8 (
+        const UTF32** sourceStart, const UTF32* sourceEnd, 
+        UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+    ConversionResult result = conversionOK;
+    const UTF32* source = *sourceStart;
+    UTF8* target = *targetStart;
+    while (source < sourceEnd) {
+        UTF32 ch;
+        unsigned short bytesToWrite = 0;
+        const UTF32 byteMask = 0xBF;
+        const UTF32 byteMark = 0x80; 
+        ch = *source++;
+        if (flags == strictConversion ) {
+            /* UTF-16 surrogate values are illegal in UTF-32 */
+            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+                --source; /* return to the illegal value itself */
+                result = sourceIllegal;
+                break;
+            }
+        }
+        /*
+         * Figure out how many bytes the result will require. Turn any
+         * illegally large UTF32 things (> Plane 17) into replacement chars.
+         */
+        if (ch < (UTF32)0x80) {      bytesToWrite = 1;
+        } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
+        } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
+        } else if (ch <= UNI_MAX_LEGAL_UTF32) {  bytesToWrite = 4;
+        } else {                            bytesToWrite = 3;
+                                            ch = UNI_REPLACEMENT_CHAR;
+                                            result = sourceIllegal;
+        }
+        
+        target += bytesToWrite;
+        if (target > targetEnd) {
+            --source; /* Back up source pointer! */
+            target -= bytesToWrite; result = targetExhausted; break;
+        }
+        switch (bytesToWrite) { /* note: everything falls through. */
+            case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+            case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+            case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+            case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+        }
+        target += bytesToWrite;
+    }
+    *sourceStart = source;
+    *targetStart = target;
+    return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
+ *  length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns false.  The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static Boolean isLegalUTF8(const UTF8 *source, int length) {
+    UTF8 a;
+    const UTF8 *srcptr = source+length;
+    switch (length) {
+    default: return false;
+        /* Everything else falls through when "true"... */
+    case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+    case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+    case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+
+        switch (*source) {
+            /* no fall-through in this inner switch */
+            case 0xE0: if (a < 0xA0) return false; break;
+            case 0xED: if (a > 0x9F) return false; break;
+            case 0xF0: if (a < 0x90) return false; break;
+            case 0xF4: if (a > 0x8F) return false; break;
+            default:   if (a < 0x80) return false;
+        }
+
+    case 1: if (*source >= 0x80 && *source < 0xC2) return false;
+    }
+    if (*source > 0xF4) return false;
+    return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
+    int length = trailingBytesForUTF8[*source]+1;
+    if (length > sourceEnd - source) {
+        return false;
+    }
+    return isLegalUTF8(source, length);
+}
+
+/* --------------------------------------------------------------------- */
+
+static unsigned
+findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source,
+                                          const UTF8 *sourceEnd) {
+  UTF8 b1, b2, b3;
+
+  assert(!isLegalUTF8Sequence(source, sourceEnd));
+
+  /*
+   * Unicode 6.3.0, D93b:
+   *
+   *   Maximal subpart of an ill-formed subsequence: The longest code unit
+   *   subsequence starting at an unconvertible offset that is either:
+   *   a. the initial subsequence of a well-formed code unit sequence, or
+   *   b. a subsequence of length one.
+   */
+
+  if (source == sourceEnd)
+    return 0;
+
+  /*
+   * Perform case analysis.  See Unicode 6.3.0, Table 3-7. Well-Formed UTF-8
+   * Byte Sequences.
+   */
+
+  b1 = *source;
+  ++source;
+  if (b1 >= 0xC2 && b1 <= 0xDF) {
+    /*
+     * First byte is valid, but we know that this code unit sequence is
+     * invalid, so the maximal subpart has to end after the first byte.
+     */
+    return 1;
+  }
+
+  if (source == sourceEnd)
+    return 1;
+
+  b2 = *source;
+  ++source;
+
+  if (b1 == 0xE0) {
+    return (b2 >= 0xA0 && b2 <= 0xBF) ? 2 : 1;
+  }
+  if (b1 >= 0xE1 && b1 <= 0xEC) {
+    return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1;
+  }
+  if (b1 == 0xED) {
+    return (b2 >= 0x80 && b2 <= 0x9F) ? 2 : 1;
+  }
+  if (b1 >= 0xEE && b1 <= 0xEF) {
+    return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1;
+  }
+  if (b1 == 0xF0) {
+    if (b2 >= 0x90 && b2 <= 0xBF) {
+      if (source == sourceEnd)
+        return 2;
+
+      b3 = *source;
+      return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
+    }
+    return 1;
+  }
+  if (b1 >= 0xF1 && b1 <= 0xF3) {
+    if (b2 >= 0x80 && b2 <= 0xBF) {
+      if (source == sourceEnd)
+        return 2;
+
+      b3 = *source;
+      return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
+    }
+    return 1;
+  }
+  if (b1 == 0xF4) {
+    if (b2 >= 0x80 && b2 <= 0x8F) {
+      if (source == sourceEnd)
+        return 2;
+
+      b3 = *source;
+      return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
+    }
+    return 1;
+  }
+
+  assert((b1 >= 0x80 && b1 <= 0xC1) || b1 >= 0xF5);
+  /*
+   * There are no valid sequences that start with these bytes.  Maximal subpart
+   * is defined to have length 1 in these cases.
+   */
+  return 1;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return the total number of bytes in a codepoint
+ * represented in UTF-8, given the value of the first byte.
+ */
+unsigned getNumBytesForUTF8(UTF8 first) {
+  return trailingBytesForUTF8[first] + 1;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 string is legal or not.
+ * This is not used here; it's just exported.
+ */
+Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) {
+    while (*source != sourceEnd) {
+        int length = trailingBytesForUTF8[**source] + 1;
+        if (length > sourceEnd - *source || !isLegalUTF8(*source, length))
+            return false;
+        *source += length;
+    }
+    return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16 (
+        const UTF8** sourceStart, const UTF8* sourceEnd, 
+        UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+    ConversionResult result = conversionOK;
+    const UTF8* source = *sourceStart;
+    UTF16* target = *targetStart;
+    while (source < sourceEnd) {
+        UTF32 ch = 0;
+        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+        if (extraBytesToRead >= sourceEnd - source) {
+            result = sourceExhausted; break;
+        }
+        /* Do this check whether lenient or strict */
+        if (!isLegalUTF8(source, extraBytesToRead+1)) {
+            result = sourceIllegal;
+            break;
+        }
+        /*
+         * The cases all fall through. See "Note A" below.
+         */
+        switch (extraBytesToRead) {
+            case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+            case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+            case 3: ch += *source++; ch <<= 6;
+            case 2: ch += *source++; ch <<= 6;
+            case 1: ch += *source++; ch <<= 6;
+            case 0: ch += *source++;
+        }
+        ch -= offsetsFromUTF8[extraBytesToRead];
+
+        if (target >= targetEnd) {
+            source -= (extraBytesToRead+1); /* Back up source pointer! */
+            result = targetExhausted; break;
+        }
+        if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+            /* UTF-16 surrogate values are illegal in UTF-32 */
+            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+                if (flags == strictConversion) {
+                    source -= (extraBytesToRead+1); /* return to the illegal value itself */
+                    result = sourceIllegal;
+                    break;
+                } else {
+                    *target++ = UNI_REPLACEMENT_CHAR;
+                }
+            } else {
+                *target++ = (UTF16)ch; /* normal case */
+            }
+        } else if (ch > UNI_MAX_UTF16) {
+            if (flags == strictConversion) {
+                result = sourceIllegal;
+                source -= (extraBytesToRead+1); /* return to the start */
+                break; /* Bail out; shouldn't continue */
+            } else {
+                *target++ = UNI_REPLACEMENT_CHAR;
+            }
+        } else {
+            /* target is a character in range 0xFFFF - 0x10FFFF. */
+            if (target + 1 >= targetEnd) {
+                source -= (extraBytesToRead+1); /* Back up source pointer! */
+                result = targetExhausted; break;
+            }
+            ch -= halfBase;
+            *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+            *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+        }
+    }
+    *sourceStart = source;
+    *targetStart = target;
+    return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+static ConversionResult ConvertUTF8toUTF32Impl(
+        const UTF8** sourceStart, const UTF8* sourceEnd, 
+        UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags,
+        Boolean InputIsPartial) {
+    ConversionResult result = conversionOK;
+    const UTF8* source = *sourceStart;
+    UTF32* target = *targetStart;
+    while (source < sourceEnd) {
+        UTF32 ch = 0;
+        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+        if (extraBytesToRead >= sourceEnd - source) {
+            if (flags == strictConversion || InputIsPartial) {
+                result = sourceExhausted;
+                break;
+            } else {
+                result = sourceIllegal;
+
+                /*
+                 * Replace the maximal subpart of ill-formed sequence with
+                 * replacement character.
+                 */
+                source += findMaximalSubpartOfIllFormedUTF8Sequence(source,
+                                                                    sourceEnd);
+                *target++ = UNI_REPLACEMENT_CHAR;
+                continue;
+            }
+        }
+        if (target >= targetEnd) {
+            result = targetExhausted; break;
+        }
+
+        /* Do this check whether lenient or strict */
+        if (!isLegalUTF8(source, extraBytesToRead+1)) {
+            result = sourceIllegal;
+            if (flags == strictConversion) {
+                /* Abort conversion. */
+                break;
+            } else {
+                /*
+                 * Replace the maximal subpart of ill-formed sequence with
+                 * replacement character.
+                 */
+                source += findMaximalSubpartOfIllFormedUTF8Sequence(source,
+                                                                    sourceEnd);
+                *target++ = UNI_REPLACEMENT_CHAR;
+                continue;
+            }
+        }
+        /*
+         * The cases all fall through. See "Note A" below.
+         */
+        switch (extraBytesToRead) {
+            case 5: ch += *source++; ch <<= 6;
+            case 4: ch += *source++; ch <<= 6;
+            case 3: ch += *source++; ch <<= 6;
+            case 2: ch += *source++; ch <<= 6;
+            case 1: ch += *source++; ch <<= 6;
+            case 0: ch += *source++;
+        }
+        ch -= offsetsFromUTF8[extraBytesToRead];
+
+        if (ch <= UNI_MAX_LEGAL_UTF32) {
+            /*
+             * UTF-16 surrogate values are illegal in UTF-32, and anything
+             * over Plane 17 (> 0x10FFFF) is illegal.
+             */
+            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+                if (flags == strictConversion) {
+                    source -= (extraBytesToRead+1); /* return to the illegal value itself */
+                    result = sourceIllegal;
+                    break;
+                } else {
+                    *target++ = UNI_REPLACEMENT_CHAR;
+                }
+            } else {
+                *target++ = ch;
+            }
+        } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+            result = sourceIllegal;
+            *target++ = UNI_REPLACEMENT_CHAR;
+        }
+    }
+    *sourceStart = source;
+    *targetStart = target;
+    return result;
+}
+
+ConversionResult ConvertUTF8toUTF32Partial(const UTF8 **sourceStart,
+                                           const UTF8 *sourceEnd,
+                                           UTF32 **targetStart,
+                                           UTF32 *targetEnd,
+                                           ConversionFlags flags) {
+  return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd,
+                                flags, /*InputIsPartial=*/true);
+}
+
+ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
+                                    const UTF8 *sourceEnd, UTF32 **targetStart,
+                                    UTF32 *targetEnd, ConversionFlags flags) {
+  return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd,
+                                flags, /*InputIsPartial=*/false);
+}
+
+/* ---------------------------------------------------------------------
+
+    Note A.
+    The fall-through switches in UTF-8 reading code save a
+    temp variable, some decrements & conditionals.  The switches
+    are equivalent to the following loop:
+        {
+            int tmpBytesToRead = extraBytesToRead+1;
+            do {
+                ch += *source++;
+                --tmpBytesToRead;
+                if (tmpBytesToRead) ch <<= 6;
+            } while (tmpBytesToRead > 0);
+        }
+    In UTF-8 writing code, the switches on "bytesToWrite" are
+    similarly unrolled loops.
+
+   --------------------------------------------------------------------- */
diff --git a/third_party/llvm-subzero/lib/Support/ConvertUTFWrapper.cpp b/third_party/llvm-subzero/lib/Support/ConvertUTFWrapper.cpp
new file mode 100644
index 0000000..217cedb
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/ConvertUTFWrapper.cpp
@@ -0,0 +1,251 @@
+//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----===
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
+                       char *&ResultPtr, const UTF8 *&ErrorPtr) {
+  assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4);
+  ConversionResult result = conversionOK;
+  // Copy the character span over.
+  if (WideCharWidth == 1) {
+    const UTF8 *Pos = reinterpret_cast<const UTF8*>(Source.begin());
+    if (!isLegalUTF8String(&Pos, reinterpret_cast<const UTF8*>(Source.end()))) {
+      result = sourceIllegal;
+      ErrorPtr = Pos;
+    } else {
+      memcpy(ResultPtr, Source.data(), Source.size());
+      ResultPtr += Source.size();
+    }
+  } else if (WideCharWidth == 2) {
+    const UTF8 *sourceStart = (const UTF8*)Source.data();
+    // FIXME: Make the type of the result buffer correct instead of
+    // using reinterpret_cast.
+    UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr);
+    ConversionFlags flags = strictConversion;
+    result = ConvertUTF8toUTF16(
+        &sourceStart, sourceStart + Source.size(),
+        &targetStart, targetStart + Source.size(), flags);
+    if (result == conversionOK)
+      ResultPtr = reinterpret_cast<char*>(targetStart);
+    else
+      ErrorPtr = sourceStart;
+  } else if (WideCharWidth == 4) {
+    const UTF8 *sourceStart = (const UTF8*)Source.data();
+    // FIXME: Make the type of the result buffer correct instead of
+    // using reinterpret_cast.
+    UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr);
+    ConversionFlags flags = strictConversion;
+    result = ConvertUTF8toUTF32(
+        &sourceStart, sourceStart + Source.size(),
+        &targetStart, targetStart + Source.size(), flags);
+    if (result == conversionOK)
+      ResultPtr = reinterpret_cast<char*>(targetStart);
+    else
+      ErrorPtr = sourceStart;
+  }
+  assert((result != targetExhausted)
+         && "ConvertUTF8toUTFXX exhausted target buffer");
+  return result == conversionOK;
+}
+
+bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
+  const UTF32 *SourceStart = &Source;
+  const UTF32 *SourceEnd = SourceStart + 1;
+  UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr);
+  UTF8 *TargetEnd = TargetStart + 4;
+  ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd,
+                                           &TargetStart, TargetEnd,
+                                           strictConversion);
+  if (CR != conversionOK)
+    return false;
+
+  ResultPtr = reinterpret_cast<char*>(TargetStart);
+  return true;
+}
+
+bool hasUTF16ByteOrderMark(ArrayRef<char> S) {
+  return (S.size() >= 2 &&
+          ((S[0] == '\xff' && S[1] == '\xfe') ||
+           (S[0] == '\xfe' && S[1] == '\xff')));
+}
+
+bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
+  assert(Out.empty());
+
+  // Error out on an uneven byte count.
+  if (SrcBytes.size() % 2)
+    return false;
+
+  // Avoid OOB by returning early on empty input.
+  if (SrcBytes.empty())
+    return true;
+
+  const UTF16 *Src = reinterpret_cast<const UTF16 *>(SrcBytes.begin());
+  const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(SrcBytes.end());
+
+  // Byteswap if necessary.
+  std::vector<UTF16> ByteSwapped;
+  if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
+    ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
+    for (unsigned I = 0, E = ByteSwapped.size(); I != E; ++I)
+      ByteSwapped[I] = llvm::sys::SwapByteOrder_16(ByteSwapped[I]);
+    Src = &ByteSwapped[0];
+    SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
+  }
+
+  // Skip the BOM for conversion.
+  if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE)
+    Src++;
+
+  // Just allocate enough space up front.  We'll shrink it later.  Allocate
+  // enough that we can fit a null terminator without reallocating.
+  Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
+  UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
+  UTF8 *DstEnd = Dst + Out.size();
+
+  ConversionResult CR =
+      ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
+  assert(CR != targetExhausted);
+
+  if (CR != conversionOK) {
+    Out.clear();
+    return false;
+  }
+
+  Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
+  Out.push_back(0);
+  Out.pop_back();
+  return true;
+}
+
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out)
+{
+  return convertUTF16ToUTF8String(
+      llvm::ArrayRef<char>(reinterpret_cast<const char *>(Src.data()),
+      Src.size() * sizeof(UTF16)), Out);
+}
+
+bool convertUTF8ToUTF16String(StringRef SrcUTF8,
+                              SmallVectorImpl<UTF16> &DstUTF16) {
+  assert(DstUTF16.empty());
+
+  // Avoid OOB by returning early on empty input.
+  if (SrcUTF8.empty()) {
+    DstUTF16.push_back(0);
+    DstUTF16.pop_back();
+    return true;
+  }
+
+  const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.begin());
+  const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.end());
+
+  // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding
+  // as UTF-16 should always require the same amount or less code units than the
+  // UTF-8 encoding.  Allocate one extra byte for the null terminator though,
+  // so that someone calling DstUTF16.data() gets a null terminated string.
+  // We resize down later so we don't have to worry that this over allocates.
+  DstUTF16.resize(SrcUTF8.size()+1);
+  UTF16 *Dst = &DstUTF16[0];
+  UTF16 *DstEnd = Dst + DstUTF16.size();
+
+  ConversionResult CR =
+      ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
+  assert(CR != targetExhausted);
+
+  if (CR != conversionOK) {
+    DstUTF16.clear();
+    return false;
+  }
+
+  DstUTF16.resize(Dst - &DstUTF16[0]);
+  DstUTF16.push_back(0);
+  DstUTF16.pop_back();
+  return true;
+}
+
+static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
+                  sizeof(wchar_t) == 4,
+              "Expected wchar_t to be 1, 2, or 4 bytes");
+
+template <typename TResult>
+static inline bool ConvertUTF8toWideInternal(llvm::StringRef Source,
+                                             TResult &Result) {
+  // Even in the case of UTF-16, the number of bytes in a UTF-8 string is
+  // at least as large as the number of elements in the resulting wide
+  // string, because surrogate pairs take at least 4 bytes in UTF-8.
+  Result.resize(Source.size() + 1);
+  char *ResultPtr = reinterpret_cast<char *>(&Result[0]);
+  const UTF8 *ErrorPtr;
+  if (!ConvertUTF8toWide(sizeof(wchar_t), Source, ResultPtr, ErrorPtr)) {
+    Result.clear();
+    return false;
+  }
+  Result.resize(reinterpret_cast<wchar_t *>(ResultPtr) - &Result[0]);
+  return true;
+}
+
+bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result) {
+  return ConvertUTF8toWideInternal(Source, Result);
+}
+
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
+  if (!Source) {
+    Result.clear();
+    return true;
+  }
+  return ConvertUTF8toWide(llvm::StringRef(Source), Result);
+}
+
+bool convertWideToUTF8(const std::wstring &Source, std::string &Result) {
+  if (sizeof(wchar_t) == 1) {
+    const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data());
+    const UTF8 *End =
+        reinterpret_cast<const UTF8 *>(Source.data() + Source.size());
+    if (!isLegalUTF8String(&Start, End))
+      return false;
+    Result.resize(Source.size());
+    memcpy(&Result[0], Source.data(), Source.size());
+    return true;
+  } else if (sizeof(wchar_t) == 2) {
+    return convertUTF16ToUTF8String(
+        llvm::ArrayRef<UTF16>(reinterpret_cast<const UTF16 *>(Source.data()),
+                              Source.size()),
+        Result);
+  } else if (sizeof(wchar_t) == 4) {
+    const UTF32 *Start = reinterpret_cast<const UTF32 *>(Source.data());
+    const UTF32 *End =
+        reinterpret_cast<const UTF32 *>(Source.data() + Source.size());
+    Result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * Source.size());
+    UTF8 *ResultPtr = reinterpret_cast<UTF8 *>(&Result[0]);
+    UTF8 *ResultEnd = reinterpret_cast<UTF8 *>(&Result[0] + Result.size());
+    if (ConvertUTF32toUTF8(&Start, End, &ResultPtr, ResultEnd,
+                           strictConversion) == conversionOK) {
+      Result.resize(reinterpret_cast<char *>(ResultPtr) - &Result[0]);
+      return true;
+    } else {
+      Result.clear();
+      return false;
+    }
+  } else {
+    llvm_unreachable(
+        "Control should never reach this point; see static_assert further up");
+  }
+}
+
+} // end namespace llvm
+
diff --git a/third_party/llvm-subzero/lib/Support/Debug.cpp b/third_party/llvm-subzero/lib/Support/Debug.cpp
new file mode 100644
index 0000000..323d532
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Debug.cpp
@@ -0,0 +1,158 @@
+//===-- Debug.cpp - An easy way to add debug output to your code ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a handy way of adding debugging information to your
+// code, without it being enabled all of the time, and without having to add
+// command line options to enable it.
+//
+// In particular, just wrap your code with the DEBUG() macro, and it will be
+// enabled automatically if you specify '-debug' on the command-line.
+// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify
+// that your debug code belongs to class "foo".  Then, on the command line, you
+// can specify '-debug-only=foo' to enable JUST the debug information for the
+// foo class.
+//
+// When compiling without assertions, the -debug-* options and all code in
+// DEBUG() statements disappears, so it does not affect the runtime of the code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/circular_raw_ostream.h"
+#include "llvm/Support/raw_ostream.h"
+
+#undef isCurrentDebugType
+#undef setCurrentDebugType
+
+using namespace llvm;
+
+// Even though LLVM might be built with NDEBUG, define symbols that the code
+// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
+namespace llvm {
+/// Exported boolean set by the -debug option.
+bool DebugFlag = false;
+
+static ManagedStatic<std::vector<std::string>> CurrentDebugType;
+
+/// Return true if the specified string is the debug type
+/// specified on the command line, or if none was specified on the command line
+/// with the -debug-only=X option.
+bool isCurrentDebugType(const char *DebugType) {
+  if (CurrentDebugType->empty())
+    return true;
+  // See if DebugType is in list. Note: do not use find() as that forces us to
+  // unnecessarily create an std::string instance.
+  for (auto &d : *CurrentDebugType) {
+    if (d == DebugType)
+      return true;
+  }
+  return false;
+}
+
+/// Set the current debug type, as if the -debug-only=X
+/// option were specified.  Note that DebugFlag also needs to be set to true for
+/// debug output to be produced.
+///
+void setCurrentDebugType(const char *Type) {
+  CurrentDebugType->clear();
+  CurrentDebugType->push_back(Type);
+}
+
+} // namespace llvm
+
+// All Debug.h functionality is a no-op in NDEBUG mode.
+#ifndef NDEBUG
+
+// -debug - Command line option to enable the DEBUG statements in the passes.
+// This flag may only be enabled in debug builds.
+static cl::opt<bool, true>
+Debug("debug", cl::desc("Enable debug output"), cl::Hidden,
+      cl::location(DebugFlag));
+
+// -debug-buffer-size - Buffer the last N characters of debug output
+//until program termination.
+static cl::opt<unsigned>
+DebugBufferSize("debug-buffer-size",
+                cl::desc("Buffer the last N characters of debug output "
+                         "until program termination. "
+                         "[default 0 -- immediate print-out]"),
+                cl::Hidden,
+                cl::init(0));
+
+namespace {
+
+struct DebugOnlyOpt {
+  void operator=(const std::string &Val) const {
+    if (Val.empty())
+      return;
+    DebugFlag = true;
+    SmallVector<StringRef,8> dbgTypes;
+    StringRef(Val).split(dbgTypes, ',', -1, false);
+    for (auto dbgType : dbgTypes)
+      CurrentDebugType->push_back(dbgType);
+  }
+};
+
+}
+
+static DebugOnlyOpt DebugOnlyOptLoc;
+
+static cl::opt<DebugOnlyOpt, true, cl::parser<std::string> >
+DebugOnly("debug-only", cl::desc("Enable a specific type of debug output (comma separated list of types)"),
+          cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"),
+          cl::location(DebugOnlyOptLoc), cl::ValueRequired);
+// Signal handlers - dump debug output on termination.
+static void debug_user_sig_handler(void *Cookie) {
+  // This is a bit sneaky.  Since this is under #ifndef NDEBUG, we
+  // know that debug mode is enabled and dbgs() really is a
+  // circular_raw_ostream.  If NDEBUG is defined, then dbgs() ==
+  // errs() but this will never be invoked.
+  llvm::circular_raw_ostream &dbgout =
+      static_cast<circular_raw_ostream &>(llvm::dbgs());
+  dbgout.flushBufferWithBanner();
+}
+
+/// dbgs - Return a circular-buffered debug stream.
+raw_ostream &llvm::dbgs() {
+  // Do one-time initialization in a thread-safe way.
+  static struct dbgstream {
+    circular_raw_ostream strm;
+
+    dbgstream() :
+        strm(errs(), "*** Debug Log Output ***\n",
+             (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) {
+      if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0)
+        // TODO: Add a handler for SIGUSER1-type signals so the user can
+        // force a debug dump.
+        sys::AddSignalHandler(&debug_user_sig_handler, nullptr);
+      // Otherwise we've already set the debug stream buffer size to
+      // zero, disabling buffering so it will output directly to errs().
+    }
+  } thestrm;
+
+  return thestrm.strm;
+}
+
+#else
+// Avoid "has no symbols" warning.
+namespace llvm {
+  /// dbgs - Return errs().
+  raw_ostream &dbgs() {
+    return errs();
+  }
+}
+
+#endif
+
+/// EnableDebugBuffering - Turn on signal handler installation.
+///
+bool llvm::EnableDebugBuffering = false;
diff --git a/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp b/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp
new file mode 100644
index 0000000..a7d3a18
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp
@@ -0,0 +1,207 @@
+//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an API used to indicate fatal error conditions.  Non-fatal
+// errors (most of them) should be handled through LLVMContext.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm-c/ErrorHandling.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/MutexGuard.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/WindowsError.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdlib>
+
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+#if defined(_MSC_VER)
+# include <io.h>
+# include <fcntl.h>
+#endif
+
+using namespace llvm;
+
+static fatal_error_handler_t ErrorHandler = nullptr;
+static void *ErrorHandlerUserData = nullptr;
+
+static ManagedStatic<sys::Mutex> ErrorHandlerMutex;
+
+void llvm::install_fatal_error_handler(fatal_error_handler_t handler,
+                                       void *user_data) {
+  llvm::MutexGuard Lock(*ErrorHandlerMutex);
+  assert(!ErrorHandler && "Error handler already registered!\n");
+  ErrorHandler = handler;
+  ErrorHandlerUserData = user_data;
+}
+
+void llvm::remove_fatal_error_handler() {
+  llvm::MutexGuard Lock(*ErrorHandlerMutex);
+  ErrorHandler = nullptr;
+  ErrorHandlerUserData = nullptr;
+}
+
+void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) {
+  report_fatal_error(Twine(Reason), GenCrashDiag);
+}
+
+void llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) {
+  report_fatal_error(Twine(Reason), GenCrashDiag);
+}
+
+void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
+  report_fatal_error(Twine(Reason), GenCrashDiag);
+}
+
+void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
+  llvm::fatal_error_handler_t handler = nullptr;
+  void* handlerData = nullptr;
+  {
+    // Only acquire the mutex while reading the handler, so as not to invoke a
+    // user-supplied callback under a lock.
+    llvm::MutexGuard Lock(*ErrorHandlerMutex);
+    handler = ErrorHandler;
+    handlerData = ErrorHandlerUserData;
+  }
+
+  if (handler) {
+    handler(handlerData, Reason.str(), GenCrashDiag);
+  } else {
+    // Blast the result out to stderr.  We don't try hard to make sure this
+    // succeeds (e.g. handling EINTR) and we can't use errs() here because
+    // raw ostreams can call report_fatal_error.
+    SmallVector<char, 64> Buffer;
+    raw_svector_ostream OS(Buffer);
+    OS << "LLVM ERROR: " << Reason << "\n";
+    StringRef MessageStr = OS.str();
+    ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
+    (void)written; // If something went wrong, we deliberately just give up.
+  }
+
+  // If we reached here, we are failing ungracefully. Run the interrupt handlers
+  // to make sure any special cleanups get done, in particular that we remove
+  // files registered with RemoveFileOnSignal.
+  sys::RunInterruptHandlers();
+
+  exit(1);
+}
+
+void llvm::llvm_unreachable_internal(const char *msg, const char *file,
+                                     unsigned line) {
+  // This code intentionally doesn't call the ErrorHandler callback, because
+  // llvm_unreachable is intended to be used to indicate "impossible"
+  // situations, and not legitimate runtime errors.
+  if (msg)
+    dbgs() << msg << "\n";
+  dbgs() << "UNREACHABLE executed";
+  if (file)
+    dbgs() << " at " << file << ":" << line;
+  dbgs() << "!\n";
+  abort();
+#ifdef LLVM_BUILTIN_UNREACHABLE
+  // Windows systems and possibly others don't declare abort() to be noreturn,
+  // so use the unreachable builtin to avoid a Clang self-host warning.
+  LLVM_BUILTIN_UNREACHABLE;
+#endif
+}
+
+static void bindingsErrorHandler(void *user_data, const std::string& reason,
+                                 bool gen_crash_diag) {
+  LLVMFatalErrorHandler handler =
+      LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data);
+  handler(reason.c_str());
+}
+
+void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) {
+  install_fatal_error_handler(bindingsErrorHandler,
+                              LLVM_EXTENSION reinterpret_cast<void *>(Handler));
+}
+
+void LLVMResetFatalErrorHandler() {
+  remove_fatal_error_handler();
+}
+
+#ifdef LLVM_ON_WIN32
+
+#include <winerror.h>
+
+// I'd rather not double the line count of the following.
+#define MAP_ERR_TO_COND(x, y)                                                  \
+  case x:                                                                      \
+    return make_error_code(errc::y)
+
+std::error_code llvm::mapWindowsError(unsigned EV) {
+  switch (EV) {
+    MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
+    MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
+    MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
+    MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
+    MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
+    MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
+    MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
+    MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
+    MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
+    MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
+    MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
+    MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
+    MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
+    MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
+    MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
+    MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
+    MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
+    MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
+    MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
+    MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
+    MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
+    MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
+    MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
+    MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
+    MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
+    MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
+    MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
+    MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
+    MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
+    MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
+    MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
+    MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
+    MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
+    MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
+    MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
+    MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
+    MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
+    MAP_ERR_TO_COND(ERROR_SEEK, io_error);
+    MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
+    MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
+    MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
+    MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
+    MAP_ERR_TO_COND(WSAEACCES, permission_denied);
+    MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
+    MAP_ERR_TO_COND(WSAEFAULT, bad_address);
+    MAP_ERR_TO_COND(WSAEINTR, interrupted);
+    MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
+    MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
+    MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
+  default:
+    return std::error_code(EV, std::system_category());
+  }
+}
+
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/FoldingSet.cpp b/third_party/llvm-subzero/lib/Support/FoldingSet.cpp
new file mode 100644
index 0000000..a27d317
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/FoldingSet.cpp
@@ -0,0 +1,462 @@
+//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a hash set that can be used to remove duplication of
+// nodes in a graph.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstring>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// FoldingSetNodeIDRef Implementation
+
+/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
+/// used to lookup the node in the FoldingSetImpl.
+unsigned FoldingSetNodeIDRef::ComputeHash() const {
+  return static_cast<unsigned>(hash_combine_range(Data, Data+Size));
+}
+
+bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const {
+  if (Size != RHS.Size) return false;
+  return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0;
+}
+
+/// Used to compare the "ordering" of two nodes as defined by the
+/// profiled bits and their ordering defined by memcmp().
+bool FoldingSetNodeIDRef::operator<(FoldingSetNodeIDRef RHS) const {
+  if (Size != RHS.Size)
+    return Size < RHS.Size;
+  return memcmp(Data, RHS.Data, Size*sizeof(*Data)) < 0;
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSetNodeID Implementation
+
+/// Add* - Add various data types to Bit data.
+///
+void FoldingSetNodeID::AddPointer(const void *Ptr) {
+  // Note: this adds pointers to the hash using sizes and endianness that
+  // depend on the host. It doesn't matter, however, because hashing on
+  // pointer values is inherently unstable. Nothing should depend on the
+  // ordering of nodes in the folding set.
+  Bits.append(reinterpret_cast<unsigned *>(&Ptr),
+              reinterpret_cast<unsigned *>(&Ptr+1));
+}
+void FoldingSetNodeID::AddInteger(signed I) {
+  Bits.push_back(I);
+}
+void FoldingSetNodeID::AddInteger(unsigned I) {
+  Bits.push_back(I);
+}
+void FoldingSetNodeID::AddInteger(long I) {
+  AddInteger((unsigned long)I);
+}
+void FoldingSetNodeID::AddInteger(unsigned long I) {
+  if (sizeof(long) == sizeof(int))
+    AddInteger(unsigned(I));
+  else if (sizeof(long) == sizeof(long long)) {
+    AddInteger((unsigned long long)I);
+  } else {
+    llvm_unreachable("unexpected sizeof(long)");
+  }
+}
+void FoldingSetNodeID::AddInteger(long long I) {
+  AddInteger((unsigned long long)I);
+}
+void FoldingSetNodeID::AddInteger(unsigned long long I) {
+  AddInteger(unsigned(I));
+  if ((uint64_t)(unsigned)I != I)
+    Bits.push_back(unsigned(I >> 32));
+}
+
+void FoldingSetNodeID::AddString(StringRef String) {
+  unsigned Size =  String.size();
+  Bits.push_back(Size);
+  if (!Size) return;
+
+  unsigned Units = Size / 4;
+  unsigned Pos = 0;
+  const unsigned *Base = (const unsigned*) String.data();
+  
+  // If the string is aligned do a bulk transfer.
+  if (!((intptr_t)Base & 3)) {
+    Bits.append(Base, Base + Units);
+    Pos = (Units + 1) * 4;
+  } else {
+    // Otherwise do it the hard way.
+    // To be compatible with above bulk transfer, we need to take endianness
+    // into account.
+    static_assert(sys::IsBigEndianHost || sys::IsLittleEndianHost,
+                  "Unexpected host endianness");
+    if (sys::IsBigEndianHost) {
+      for (Pos += 4; Pos <= Size; Pos += 4) {
+        unsigned V = ((unsigned char)String[Pos - 4] << 24) |
+                     ((unsigned char)String[Pos - 3] << 16) |
+                     ((unsigned char)String[Pos - 2] << 8) |
+                      (unsigned char)String[Pos - 1];
+        Bits.push_back(V);
+      }
+    } else {  // Little-endian host
+      for (Pos += 4; Pos <= Size; Pos += 4) {
+        unsigned V = ((unsigned char)String[Pos - 1] << 24) |
+                     ((unsigned char)String[Pos - 2] << 16) |
+                     ((unsigned char)String[Pos - 3] << 8) |
+                      (unsigned char)String[Pos - 4];
+        Bits.push_back(V);
+      }
+    }
+  }
+  
+  // With the leftover bits.
+  unsigned V = 0;
+  // Pos will have overshot size by 4 - #bytes left over.
+  // No need to take endianness into account here - this is always executed.
+  switch (Pos - Size) {
+  case 1: V = (V << 8) | (unsigned char)String[Size - 3]; LLVM_FALLTHROUGH;
+  case 2: V = (V << 8) | (unsigned char)String[Size - 2]; LLVM_FALLTHROUGH;
+  case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break;
+  default: return; // Nothing left.
+  }
+
+  Bits.push_back(V);
+}
+
+// AddNodeID - Adds the Bit data of another ID to *this.
+void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) {
+  Bits.append(ID.Bits.begin(), ID.Bits.end());
+}
+
+/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to 
+/// lookup the node in the FoldingSetImpl.
+unsigned FoldingSetNodeID::ComputeHash() const {
+  return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
+}
+
+/// operator== - Used to compare two nodes to each other.
+///
+bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const {
+  return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
+}
+
+/// operator== - Used to compare two nodes to each other.
+///
+bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const {
+  return FoldingSetNodeIDRef(Bits.data(), Bits.size()) == RHS;
+}
+
+/// Used to compare the "ordering" of two nodes as defined by the
+/// profiled bits and their ordering defined by memcmp().
+bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS) const {
+  return *this < FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
+}
+
+bool FoldingSetNodeID::operator<(FoldingSetNodeIDRef RHS) const {
+  return FoldingSetNodeIDRef(Bits.data(), Bits.size()) < RHS;
+}
+
+/// Intern - Copy this node's data to a memory region allocated from the
+/// given allocator and return a FoldingSetNodeIDRef describing the
+/// interned data.
+FoldingSetNodeIDRef
+FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const {
+  unsigned *New = Allocator.Allocate<unsigned>(Bits.size());
+  std::uninitialized_copy(Bits.begin(), Bits.end(), New);
+  return FoldingSetNodeIDRef(New, Bits.size());
+}
+
+//===----------------------------------------------------------------------===//
+/// Helper functions for FoldingSetImpl.
+
+/// GetNextPtr - In order to save space, each bucket is a
+/// singly-linked-list. In order to make deletion more efficient, we make
+/// the list circular, so we can delete a node without computing its hash.
+/// The problem with this is that the start of the hash buckets are not
+/// Nodes.  If NextInBucketPtr is a bucket pointer, this method returns null:
+/// use GetBucketPtr when this happens.
+static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) {
+  // The low bit is set if this is the pointer back to the bucket.
+  if (reinterpret_cast<intptr_t>(NextInBucketPtr) & 1)
+    return nullptr;
+  
+  return static_cast<FoldingSetImpl::Node*>(NextInBucketPtr);
+}
+
+
+/// testing.
+static void **GetBucketPtr(void *NextInBucketPtr) {
+  intptr_t Ptr = reinterpret_cast<intptr_t>(NextInBucketPtr);
+  assert((Ptr & 1) && "Not a bucket pointer");
+  return reinterpret_cast<void**>(Ptr & ~intptr_t(1));
+}
+
+/// GetBucketFor - Hash the specified node ID and return the hash bucket for
+/// the specified ID.
+static void **GetBucketFor(unsigned Hash, void **Buckets, unsigned NumBuckets) {
+  // NumBuckets is always a power of 2.
+  unsigned BucketNum = Hash & (NumBuckets-1);
+  return Buckets + BucketNum;
+}
+
+/// AllocateBuckets - Allocated initialized bucket memory.
+static void **AllocateBuckets(unsigned NumBuckets) {
+  void **Buckets = static_cast<void**>(calloc(NumBuckets+1, sizeof(void*)));
+  // Set the very last bucket to be a non-null "pointer".
+  Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
+  return Buckets;
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSetImpl Implementation
+
+void FoldingSetImpl::anchor() {}
+
+FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) {
+  assert(5 < Log2InitSize && Log2InitSize < 32 &&
+         "Initial hash table size out of range");
+  NumBuckets = 1 << Log2InitSize;
+  Buckets = AllocateBuckets(NumBuckets);
+  NumNodes = 0;
+}
+
+FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg)
+    : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) {
+  Arg.Buckets = nullptr;
+  Arg.NumBuckets = 0;
+  Arg.NumNodes = 0;
+}
+
+FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) {
+  free(Buckets); // This may be null if the set is in a moved-from state.
+  Buckets = RHS.Buckets;
+  NumBuckets = RHS.NumBuckets;
+  NumNodes = RHS.NumNodes;
+  RHS.Buckets = nullptr;
+  RHS.NumBuckets = 0;
+  RHS.NumNodes = 0;
+  return *this;
+}
+
+FoldingSetImpl::~FoldingSetImpl() {
+  free(Buckets);
+}
+
+void FoldingSetImpl::clear() {
+  // Set all but the last bucket to null pointers.
+  memset(Buckets, 0, NumBuckets*sizeof(void*));
+
+  // Set the very last bucket to be a non-null "pointer".
+  Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
+
+  // Reset the node count to zero.
+  NumNodes = 0;
+}
+
+void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
+  assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount");
+  assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
+  void **OldBuckets = Buckets;
+  unsigned OldNumBuckets = NumBuckets;
+  NumBuckets = NewBucketCount;
+  
+  // Clear out new buckets.
+  Buckets = AllocateBuckets(NumBuckets);
+  NumNodes = 0;
+
+  // Walk the old buckets, rehashing nodes into their new place.
+  FoldingSetNodeID TempID;
+  for (unsigned i = 0; i != OldNumBuckets; ++i) {
+    void *Probe = OldBuckets[i];
+    if (!Probe) continue;
+    while (Node *NodeInBucket = GetNextPtr(Probe)) {
+      // Figure out the next link, remove NodeInBucket from the old link.
+      Probe = NodeInBucket->getNextInBucket();
+      NodeInBucket->SetNextInBucket(nullptr);
+
+      // Insert the node into the new bucket, after recomputing the hash.
+      InsertNode(NodeInBucket,
+                 GetBucketFor(ComputeNodeHash(NodeInBucket, TempID),
+                              Buckets, NumBuckets));
+      TempID.clear();
+    }
+  }
+  
+  free(OldBuckets);
+}
+
+/// GrowHashTable - Double the size of the hash table and rehash everything.
+///
+void FoldingSetImpl::GrowHashTable() {
+  GrowBucketCount(NumBuckets * 2);
+}
+
+void FoldingSetImpl::reserve(unsigned EltCount) {
+  // This will give us somewhere between EltCount / 2 and
+  // EltCount buckets.  This puts us in the load factor
+  // range of 1.0 - 2.0.
+  if(EltCount < capacity())
+    return;
+  GrowBucketCount(PowerOf2Floor(EltCount));
+}
+
+/// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
+/// return it.  If not, return the insertion token that will make insertion
+/// faster.
+FoldingSetImpl::Node
+*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
+                                     void *&InsertPos) {
+  unsigned IDHash = ID.ComputeHash();
+  void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets);
+  void *Probe = *Bucket;
+  
+  InsertPos = nullptr;
+  
+  FoldingSetNodeID TempID;
+  while (Node *NodeInBucket = GetNextPtr(Probe)) {
+    if (NodeEquals(NodeInBucket, ID, IDHash, TempID))
+      return NodeInBucket;
+    TempID.clear();
+
+    Probe = NodeInBucket->getNextInBucket();
+  }
+  
+  // Didn't find the node, return null with the bucket as the InsertPos.
+  InsertPos = Bucket;
+  return nullptr;
+}
+
+/// InsertNode - Insert the specified node into the folding set, knowing that it
+/// is not already in the map.  InsertPos must be obtained from 
+/// FindNodeOrInsertPos.
+void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
+  assert(!N->getNextInBucket());
+  // Do we need to grow the hashtable?
+  if (NumNodes+1 > capacity()) {
+    GrowHashTable();
+    FoldingSetNodeID TempID;
+    InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets);
+  }
+
+  ++NumNodes;
+  
+  /// The insert position is actually a bucket pointer.
+  void **Bucket = static_cast<void**>(InsertPos);
+  
+  void *Next = *Bucket;
+  
+  // If this is the first insertion into this bucket, its next pointer will be
+  // null.  Pretend as if it pointed to itself, setting the low bit to indicate
+  // that it is a pointer to the bucket.
+  if (!Next)
+    Next = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(Bucket)|1);
+
+  // Set the node's next pointer, and make the bucket point to the node.
+  N->SetNextInBucket(Next);
+  *Bucket = N;
+}
+
+/// RemoveNode - Remove a node from the folding set, returning true if one was
+/// removed or false if the node was not in the folding set.
+bool FoldingSetImpl::RemoveNode(Node *N) {
+  // Because each bucket is a circular list, we don't need to compute N's hash
+  // to remove it.
+  void *Ptr = N->getNextInBucket();
+  if (!Ptr) return false;  // Not in folding set.
+
+  --NumNodes;
+  N->SetNextInBucket(nullptr);
+
+  // Remember what N originally pointed to, either a bucket or another node.
+  void *NodeNextPtr = Ptr;
+  
+  // Chase around the list until we find the node (or bucket) which points to N.
+  while (true) {
+    if (Node *NodeInBucket = GetNextPtr(Ptr)) {
+      // Advance pointer.
+      Ptr = NodeInBucket->getNextInBucket();
+      
+      // We found a node that points to N, change it to point to N's next node,
+      // removing N from the list.
+      if (Ptr == N) {
+        NodeInBucket->SetNextInBucket(NodeNextPtr);
+        return true;
+      }
+    } else {
+      void **Bucket = GetBucketPtr(Ptr);
+      Ptr = *Bucket;
+      
+      // If we found that the bucket points to N, update the bucket to point to
+      // whatever is next.
+      if (Ptr == N) {
+        *Bucket = NodeNextPtr;
+        return true;
+      }
+    }
+  }
+}
+
+/// GetOrInsertNode - If there is an existing simple Node exactly
+/// equal to the specified node, return it.  Otherwise, insert 'N' and it
+/// instead.
+FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) {
+  FoldingSetNodeID ID;
+  GetNodeProfile(N, ID);
+  void *IP;
+  if (Node *E = FindNodeOrInsertPos(ID, IP))
+    return E;
+  InsertNode(N, IP);
+  return N;
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSetIteratorImpl Implementation
+
+FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) {
+  // Skip to the first non-null non-self-cycle bucket.
+  while (*Bucket != reinterpret_cast<void*>(-1) &&
+         (!*Bucket || !GetNextPtr(*Bucket)))
+    ++Bucket;
+  
+  NodePtr = static_cast<FoldingSetNode*>(*Bucket);
+}
+
+void FoldingSetIteratorImpl::advance() {
+  // If there is another link within this bucket, go to it.
+  void *Probe = NodePtr->getNextInBucket();
+
+  if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe))
+    NodePtr = NextNodeInBucket;
+  else {
+    // Otherwise, this is the last link in this bucket.  
+    void **Bucket = GetBucketPtr(Probe);
+
+    // Skip to the next non-null non-self-cycle bucket.
+    do {
+      ++Bucket;
+    } while (*Bucket != reinterpret_cast<void*>(-1) &&
+             (!*Bucket || !GetNextPtr(*Bucket)));
+    
+    NodePtr = static_cast<FoldingSetNode*>(*Bucket);
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSetBucketIteratorImpl Implementation
+
+FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) {
+  Ptr = (!*Bucket || !GetNextPtr(*Bucket)) ? (void*) Bucket : *Bucket;
+}
diff --git a/third_party/llvm-subzero/lib/Support/Hashing.cpp b/third_party/llvm-subzero/lib/Support/Hashing.cpp
new file mode 100644
index 0000000..c69efb7
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Hashing.cpp
@@ -0,0 +1,29 @@
+//===-------------- lib/Support/Hashing.cpp -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides implementation bits for the LLVM common hashing
+// infrastructure. Documentation and most of the other information is in the
+// header file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Hashing.h"
+
+using namespace llvm;
+
+// Provide a definition and static initializer for the fixed seed. This
+// initializer should always be zero to ensure its value can never appear to be
+// non-zero, even during dynamic initialization.
+size_t llvm::hashing::detail::fixed_seed_override = 0;
+
+// Implement the function for forced setting of the fixed seed.
+// FIXME: Use atomic operations here so that there is no data race.
+void llvm::set_fixed_execution_hash_seed(size_t fixed_value) {
+  hashing::detail::fixed_seed_override = fixed_value;
+}
diff --git a/third_party/llvm-subzero/lib/Support/Host.cpp b/third_party/llvm-subzero/lib/Support/Host.cpp
new file mode 100644
index 0000000..689e050
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Host.cpp
@@ -0,0 +1,1349 @@
+//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the operating system Host concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Host.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string.h>
+#include <assert.h>
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Host.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Host.inc"
+#endif
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
+#include <mach/host_info.h>
+#include <mach/mach.h>
+#include <mach/mach_host.h>
+#include <mach/machine.h>
+#endif
+
+#define DEBUG_TYPE "host-detection"
+
+//===----------------------------------------------------------------------===//
+//
+//  Implementations of the CPU detection routines
+//
+//===----------------------------------------------------------------------===//
+
+using namespace llvm;
+
+#if defined(__linux__)
+static ssize_t LLVM_ATTRIBUTE_UNUSED readCpuInfo(void *Buf, size_t Size) {
+  // Note: We cannot mmap /proc/cpuinfo here and then process the resulting
+  // memory buffer because the 'file' has 0 size (it can be read from only
+  // as a stream).
+
+  int FD;
+  std::error_code EC = sys::fs::openFileForRead("/proc/cpuinfo", FD);
+  if (EC) {
+    DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << EC.message() << "\n");
+    return -1;
+  }
+  int Ret = read(FD, Buf, Size);
+  int CloseStatus = close(FD);
+  if (CloseStatus)
+    return -1;
+  return Ret;
+}
+#endif
+
+#if defined(__i386__) || defined(_M_IX86) || \
+    defined(__x86_64__) || defined(_M_X64)
+
+#if defined(__GNUC__) || defined(__clang__)
+#include <cpuid.h>
+#endif
+
+enum VendorSignatures {
+  SIG_INTEL = 0x756e6547 /* Genu */,
+  SIG_AMD = 0x68747541 /* Auth */
+};
+
+enum ProcessorVendors {
+  VENDOR_INTEL = 1,
+  VENDOR_AMD,
+  VENDOR_OTHER,
+  VENDOR_MAX
+};
+
+enum ProcessorTypes {
+  INTEL_ATOM = 1,
+  INTEL_CORE2,
+  INTEL_COREI7,
+  AMDFAM10H,
+  AMDFAM15H,
+  INTEL_i386,
+  INTEL_i486,
+  INTEL_PENTIUM,
+  INTEL_PENTIUM_PRO,
+  INTEL_PENTIUM_II,
+  INTEL_PENTIUM_III,
+  INTEL_PENTIUM_IV,
+  INTEL_PENTIUM_M,
+  INTEL_CORE_DUO,
+  INTEL_XEONPHI,
+  INTEL_X86_64,
+  INTEL_NOCONA,
+  INTEL_PRESCOTT,
+  AMD_i486,
+  AMDPENTIUM,
+  AMDATHLON,
+  AMDFAM14H,
+  AMDFAM16H,
+  CPU_TYPE_MAX
+};
+
+enum ProcessorSubtypes {
+  INTEL_COREI7_NEHALEM = 1,
+  INTEL_COREI7_WESTMERE,
+  INTEL_COREI7_SANDYBRIDGE,
+  AMDFAM10H_BARCELONA,
+  AMDFAM10H_SHANGHAI,
+  AMDFAM10H_ISTANBUL,
+  AMDFAM15H_BDVER1,
+  AMDFAM15H_BDVER2,
+  INTEL_PENTIUM_MMX,
+  INTEL_CORE2_65,
+  INTEL_CORE2_45,
+  INTEL_COREI7_IVYBRIDGE,
+  INTEL_COREI7_HASWELL,
+  INTEL_COREI7_BROADWELL,
+  INTEL_COREI7_SKYLAKE,
+  INTEL_COREI7_SKYLAKE_AVX512,
+  INTEL_ATOM_BONNELL,
+  INTEL_ATOM_SILVERMONT,
+  INTEL_KNIGHTS_LANDING,
+  AMDPENTIUM_K6,
+  AMDPENTIUM_K62,
+  AMDPENTIUM_K63,
+  AMDPENTIUM_GEODE,
+  AMDATHLON_TBIRD,
+  AMDATHLON_MP,
+  AMDATHLON_XP,
+  AMDATHLON_K8SSE3,
+  AMDATHLON_OPTERON,
+  AMDATHLON_FX,
+  AMDATHLON_64,
+  AMD_BTVER1,
+  AMD_BTVER2,
+  AMDFAM15H_BDVER3,
+  AMDFAM15H_BDVER4,
+  CPU_SUBTYPE_MAX
+};
+
+enum ProcessorFeatures {
+  FEATURE_CMOV = 0,
+  FEATURE_MMX,
+  FEATURE_POPCNT,
+  FEATURE_SSE,
+  FEATURE_SSE2,
+  FEATURE_SSE3,
+  FEATURE_SSSE3,
+  FEATURE_SSE4_1,
+  FEATURE_SSE4_2,
+  FEATURE_AVX,
+  FEATURE_AVX2,
+  FEATURE_AVX512,
+  FEATURE_AVX512SAVE,
+  FEATURE_MOVBE,
+  FEATURE_ADX,
+  FEATURE_EM64T
+};
+
+/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
+/// the specified arguments.  If we can't run cpuid on the host, return true.
+static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
+                               unsigned *rECX, unsigned *rEDX) {
+#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(__clang__)
+#if defined(__x86_64__)
+  // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
+  // FIXME: should we save this for Clang?
+  __asm__("movq\t%%rbx, %%rsi\n\t"
+          "cpuid\n\t"
+          "xchgq\t%%rbx, %%rsi\n\t"
+          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+          : "a"(value));
+#elif defined(__i386__)
+  __asm__("movl\t%%ebx, %%esi\n\t"
+          "cpuid\n\t"
+          "xchgl\t%%ebx, %%esi\n\t"
+          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+          : "a"(value));
+#else
+  assert(0 && "This method is defined only for x86.");
+#endif
+#elif defined(_MSC_VER)
+  // The MSVC intrinsic is portable across x86 and x64.
+  int registers[4];
+  __cpuid(registers, value);
+  *rEAX = registers[0];
+  *rEBX = registers[1];
+  *rECX = registers[2];
+  *rEDX = registers[3];
+#endif
+  return false;
+#else
+  return true;
+#endif
+}
+
+/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
+/// the 4 values in the specified arguments.  If we can't run cpuid on the host,
+/// return true.
+static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
+                                 unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
+                                 unsigned *rEDX) {
+#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
+#if defined(__x86_64__) || defined(_M_X64)
+#if defined(__GNUC__) || defined(__clang__)
+  // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
+  // FIXME: should we save this for Clang?
+  __asm__("movq\t%%rbx, %%rsi\n\t"
+          "cpuid\n\t"
+          "xchgq\t%%rbx, %%rsi\n\t"
+          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+          : "a"(value), "c"(subleaf));
+#elif defined(_MSC_VER)
+  int registers[4];
+  __cpuidex(registers, value, subleaf);
+  *rEAX = registers[0];
+  *rEBX = registers[1];
+  *rECX = registers[2];
+  *rEDX = registers[3];
+#endif
+#elif defined(__i386__) || defined(_M_IX86)
+#if defined(__GNUC__) || defined(__clang__)
+  __asm__("movl\t%%ebx, %%esi\n\t"
+          "cpuid\n\t"
+          "xchgl\t%%ebx, %%esi\n\t"
+          : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
+          : "a"(value), "c"(subleaf));
+#elif defined(_MSC_VER)
+  __asm {
+      mov   eax,value
+      mov   ecx,subleaf
+      cpuid
+      mov   esi,rEAX
+      mov   dword ptr [esi],eax
+      mov   esi,rEBX
+      mov   dword ptr [esi],ebx
+      mov   esi,rECX
+      mov   dword ptr [esi],ecx
+      mov   esi,rEDX
+      mov   dword ptr [esi],edx
+  }
+#endif
+#else
+  assert(0 && "This method is defined only for x86.");
+#endif
+  return false;
+#else
+  return true;
+#endif
+}
+
+static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
+#if defined(__GNUC__) || defined(__clang__)
+  // Check xgetbv; this uses a .byte sequence instead of the instruction
+  // directly because older assemblers do not include support for xgetbv and
+  // there is no easy way to conditionally compile based on the assembler used.
+  __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
+  return false;
+#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
+  unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+  *rEAX = Result;
+  *rEDX = Result >> 32;
+  return false;
+#else
+  return true;
+#endif
+}
+
+static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
+                                 unsigned *Model) {
+  *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
+  *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
+  if (*Family == 6 || *Family == 0xf) {
+    if (*Family == 0xf)
+      // Examine extended family ID if family ID is F.
+      *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
+    // Examine extended model ID if family ID is 6 or F.
+    *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
+  }
+}
+
+static void
+getIntelProcessorTypeAndSubtype(unsigned int Family, unsigned int Model,
+                                unsigned int Brand_id, unsigned int Features,
+                                unsigned *Type, unsigned *Subtype) {
+  if (Brand_id != 0)
+    return;
+  switch (Family) {
+  case 3:
+    *Type = INTEL_i386;
+    break;
+  case 4:
+    switch (Model) {
+    case 0: // Intel486 DX processors
+    case 1: // Intel486 DX processors
+    case 2: // Intel486 SX processors
+    case 3: // Intel487 processors, IntelDX2 OverDrive processors,
+            // IntelDX2 processors
+    case 4: // Intel486 SL processor
+    case 5: // IntelSX2 processors
+    case 7: // Write-Back Enhanced IntelDX2 processors
+    case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
+    default:
+      *Type = INTEL_i486;
+      break;
+    }
+    break;
+  case 5:
+    switch (Model) {
+    case 1: // Pentium OverDrive processor for Pentium processor (60, 66),
+            // Pentium processors (60, 66)
+    case 2: // Pentium OverDrive processor for Pentium processor (75, 90,
+            // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133,
+            // 150, 166, 200)
+    case 3: // Pentium OverDrive processors for Intel486 processor-based
+            // systems
+      *Type = INTEL_PENTIUM;
+      break;
+    case 4: // Pentium OverDrive processor with MMX technology for Pentium
+            // processor (75, 90, 100, 120, 133), Pentium processor with
+            // MMX technology (166, 200)
+      *Type = INTEL_PENTIUM;
+      *Subtype = INTEL_PENTIUM_MMX;
+      break;
+    default:
+      *Type = INTEL_PENTIUM;
+      break;
+    }
+    break;
+  case 6:
+    switch (Model) {
+    case 0x01: // Pentium Pro processor
+      *Type = INTEL_PENTIUM_PRO;
+      break;
+    case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor,
+               // model 03
+    case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor,
+               // model 05, and Intel Celeron processor, model 05
+    case 0x06: // Celeron processor, model 06
+      *Type = INTEL_PENTIUM_II;
+      break;
+    case 0x07: // Pentium III processor, model 07, and Pentium III Xeon
+               // processor, model 07
+    case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor,
+               // model 08, and Celeron processor, model 08
+    case 0x0a: // Pentium III Xeon processor, model 0Ah
+    case 0x0b: // Pentium III processor, model 0Bh
+      *Type = INTEL_PENTIUM_III;
+      break;
+    case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09.
+    case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model
+               // 0Dh. All processors are manufactured using the 90 nm process.
+    case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579
+               // Integrated Processor with Intel QuickAssist Technology
+      *Type = INTEL_PENTIUM_M;
+      break;
+    case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model
+               // 0Eh. All processors are manufactured using the 65 nm process.
+      *Type = INTEL_CORE_DUO;
+      break;   // yonah
+    case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
+               // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
+               // mobile processor, Intel Core 2 Extreme processor, Intel
+               // Pentium Dual-Core processor, Intel Xeon processor, model
+               // 0Fh. All processors are manufactured using the 65 nm process.
+    case 0x16: // Intel Celeron processor model 16h. All processors are
+               // manufactured using the 65 nm process
+      *Type = INTEL_CORE2; // "core2"
+      *Subtype = INTEL_CORE2_65;
+      break;
+    case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
+               // 17h. All processors are manufactured using the 45 nm process.
+               //
+               // 45nm: Penryn , Wolfdale, Yorkfield (XE)
+    case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
+               // the 45 nm process.
+      *Type = INTEL_CORE2; // "penryn"
+      *Subtype = INTEL_CORE2_45;
+      break;
+    case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
+               // processors are manufactured using the 45 nm process.
+    case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
+               // As found in a Summer 2010 model iMac.
+    case 0x1f:
+    case 0x2e:             // Nehalem EX
+      *Type = INTEL_COREI7; // "nehalem"
+      *Subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25: // Intel Core i7, laptop version.
+    case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
+               // processors are manufactured using the 32 nm process.
+    case 0x2f: // Westmere EX
+      *Type = INTEL_COREI7; // "westmere"
+      *Subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a: // Intel Core i7 processor. All processors are manufactured
+               // using the 32 nm process.
+    case 0x2d:
+      *Type = INTEL_COREI7; //"sandybridge"
+      *Subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:             // Ivy Bridge EP
+      *Type = INTEL_COREI7; // "ivybridge"
+      *Subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+
+    // Haswell:
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      *Type = INTEL_COREI7; // "haswell"
+      *Subtype = INTEL_COREI7_HASWELL;
+      break;
+
+    // Broadwell:
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      *Type = INTEL_COREI7; // "broadwell"
+      *Subtype = INTEL_COREI7_BROADWELL;
+      break;
+
+    // Skylake:
+    case 0x4e:
+      *Type = INTEL_COREI7; // "skylake-avx512"
+      *Subtype = INTEL_COREI7_SKYLAKE_AVX512;
+      break;
+    case 0x5e:
+      *Type = INTEL_COREI7; // "skylake"
+      *Subtype = INTEL_COREI7_SKYLAKE;
+      break;
+
+    case 0x1c: // Most 45 nm Intel Atom processors
+    case 0x26: // 45 nm Atom Lincroft
+    case 0x27: // 32 nm Atom Medfield
+    case 0x35: // 32 nm Atom Midview
+    case 0x36: // 32 nm Atom Midview
+      *Type = INTEL_ATOM;
+      *Subtype = INTEL_ATOM_BONNELL;
+      break; // "bonnell"
+
+    // Atom Silvermont codes from the Intel software optimization guide.
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5a:
+    case 0x5d:
+    case 0x4c: // really airmont
+      *Type = INTEL_ATOM;
+      *Subtype = INTEL_ATOM_SILVERMONT;
+      break; // "silvermont"
+
+    case 0x57:
+      *Type = INTEL_XEONPHI; // knl
+      *Subtype = INTEL_KNIGHTS_LANDING;
+      break;
+
+    default: // Unknown family 6 CPU, try to guess.
+      if (Features & (1 << FEATURE_AVX512)) {
+        *Type = INTEL_XEONPHI; // knl
+        *Subtype = INTEL_KNIGHTS_LANDING;
+        break;
+      }
+      if (Features & (1 << FEATURE_ADX)) {
+        *Type = INTEL_COREI7;
+        *Subtype = INTEL_COREI7_BROADWELL;
+        break;
+      }
+      if (Features & (1 << FEATURE_AVX2)) {
+        *Type = INTEL_COREI7;
+        *Subtype = INTEL_COREI7_HASWELL;
+        break;
+      }
+      if (Features & (1 << FEATURE_AVX)) {
+        *Type = INTEL_COREI7;
+        *Subtype = INTEL_COREI7_SANDYBRIDGE;
+        break;
+      }
+      if (Features & (1 << FEATURE_SSE4_2)) {
+        if (Features & (1 << FEATURE_MOVBE)) {
+          *Type = INTEL_ATOM;
+          *Subtype = INTEL_ATOM_SILVERMONT;
+        } else {
+          *Type = INTEL_COREI7;
+          *Subtype = INTEL_COREI7_NEHALEM;
+        }
+        break;
+      }
+      if (Features & (1 << FEATURE_SSE4_1)) {
+        *Type = INTEL_CORE2; // "penryn"
+        *Subtype = INTEL_CORE2_45;
+        break;
+      }
+      if (Features & (1 << FEATURE_SSSE3)) {
+        if (Features & (1 << FEATURE_MOVBE)) {
+          *Type = INTEL_ATOM;
+          *Subtype = INTEL_ATOM_BONNELL; // "bonnell"
+        } else {
+          *Type = INTEL_CORE2; // "core2"
+          *Subtype = INTEL_CORE2_65;
+        }
+        break;
+      }
+      if (Features & (1 << FEATURE_EM64T)) {
+        *Type = INTEL_X86_64;
+        break; // x86-64
+      }
+      if (Features & (1 << FEATURE_SSE2)) {
+        *Type = INTEL_PENTIUM_M;
+        break;
+      }
+      if (Features & (1 << FEATURE_SSE)) {
+        *Type = INTEL_PENTIUM_III;
+        break;
+      }
+      if (Features & (1 << FEATURE_MMX)) {
+        *Type = INTEL_PENTIUM_II;
+        break;
+      }
+      *Type = INTEL_PENTIUM_PRO;
+      break;
+    }
+    break;
+  case 15: {
+    switch (Model) {
+    case 0: // Pentium 4 processor, Intel Xeon processor. All processors are
+            // model 00h and manufactured using the 0.18 micron process.
+    case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon
+            // processor MP, and Intel Celeron processor. All processors are
+            // model 01h and manufactured using the 0.18 micron process.
+    case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
+            // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron
+            // processor, and Mobile Intel Celeron processor. All processors
+            // are model 02h and manufactured using the 0.13 micron process.
+      *Type =
+          ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV);
+      break;
+
+    case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D
+            // processor. All processors are model 03h and manufactured using
+            // the 90 nm process.
+    case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition,
+            // Pentium D processor, Intel Xeon processor, Intel Xeon
+            // processor MP, Intel Celeron D processor. All processors are
+            // model 04h and manufactured using the 90 nm process.
+    case 6: // Pentium 4 processor, Pentium D processor, Pentium processor
+            // Extreme Edition, Intel Xeon processor, Intel Xeon processor
+            // MP, Intel Celeron D processor. All processors are model 06h
+            // and manufactured using the 65 nm process.
+      *Type =
+          ((Features & (1 << FEATURE_EM64T)) ? INTEL_NOCONA : INTEL_PRESCOTT);
+      break;
+
+    default:
+      *Type =
+          ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV);
+      break;
+    }
+    break;
+  }
+  default:
+    break; /*"generic"*/
+  }
+}
+
+static void getAMDProcessorTypeAndSubtype(unsigned int Family,
+                                          unsigned int Model,
+                                          unsigned int Features,
+                                          unsigned *Type,
+                                          unsigned *Subtype) {
+  // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
+  // appears to be no way to generate the wide variety of AMD-specific targets
+  // from the information returned from CPUID.
+  switch (Family) {
+  case 4:
+    *Type = AMD_i486;
+    break;
+  case 5:
+    *Type = AMDPENTIUM;
+    switch (Model) {
+    case 6:
+    case 7:
+      *Subtype = AMDPENTIUM_K6;
+      break; // "k6"
+    case 8:
+      *Subtype = AMDPENTIUM_K62;
+      break; // "k6-2"
+    case 9:
+    case 13:
+      *Subtype = AMDPENTIUM_K63;
+      break; // "k6-3"
+    case 10:
+      *Subtype = AMDPENTIUM_GEODE;
+      break; // "geode"
+    }
+    break;
+  case 6:
+    *Type = AMDATHLON;
+    switch (Model) {
+    case 4:
+      *Subtype = AMDATHLON_TBIRD;
+      break; // "athlon-tbird"
+    case 6:
+    case 7:
+    case 8:
+      *Subtype = AMDATHLON_MP;
+      break; // "athlon-mp"
+    case 10:
+      *Subtype = AMDATHLON_XP;
+      break; // "athlon-xp"
+    }
+    break;
+  case 15:
+    *Type = AMDATHLON;
+    if (Features & (1 << FEATURE_SSE3)) {
+      *Subtype = AMDATHLON_K8SSE3;
+      break; // "k8-sse3"
+    }
+    switch (Model) {
+    case 1:
+      *Subtype = AMDATHLON_OPTERON;
+      break; // "opteron"
+    case 5:
+      *Subtype = AMDATHLON_FX;
+      break; // "athlon-fx"; also opteron
+    default:
+      *Subtype = AMDATHLON_64;
+      break; // "athlon64"
+    }
+    break;
+  case 16:
+    *Type = AMDFAM10H; // "amdfam10"
+    switch (Model) {
+    case 2:
+      *Subtype = AMDFAM10H_BARCELONA;
+      break;
+    case 4:
+      *Subtype = AMDFAM10H_SHANGHAI;
+      break;
+    case 8:
+      *Subtype = AMDFAM10H_ISTANBUL;
+      break;
+    }
+    break;
+  case 20:
+    *Type = AMDFAM14H;
+    *Subtype = AMD_BTVER1;
+    break; // "btver1";
+  case 21:
+    *Type = AMDFAM15H;
+    if (!(Features &
+          (1 << FEATURE_AVX))) { // If no AVX support, provide a sane fallback.
+      *Subtype = AMD_BTVER1;
+      break; // "btver1"
+    }
+    if (Model >= 0x50 && Model <= 0x6f) {
+      *Subtype = AMDFAM15H_BDVER4;
+      break; // "bdver4"; 50h-6Fh: Excavator
+    }
+    if (Model >= 0x30 && Model <= 0x3f) {
+      *Subtype = AMDFAM15H_BDVER3;
+      break; // "bdver3"; 30h-3Fh: Steamroller
+    }
+    if (Model >= 0x10 && Model <= 0x1f) {
+      *Subtype = AMDFAM15H_BDVER2;
+      break; // "bdver2"; 10h-1Fh: Piledriver
+    }
+    if (Model <= 0x0f) {
+      *Subtype = AMDFAM15H_BDVER1;
+      break; // "bdver1"; 00h-0Fh: Bulldozer
+    }
+    break;
+  case 22:
+    *Type = AMDFAM16H;
+    if (!(Features &
+          (1 << FEATURE_AVX))) { // If no AVX support provide a sane fallback.
+      *Subtype = AMD_BTVER1;
+      break; // "btver1";
+    }
+    *Subtype = AMD_BTVER2;
+    break; // "btver2"
+  default:
+    break; // "generic"
+  }
+}
+
+static unsigned getAvailableFeatures(unsigned int ECX, unsigned int EDX,
+                                     unsigned MaxLeaf) {
+  unsigned Features = 0;
+  unsigned int EAX, EBX;
+  Features |= (((EDX >> 23) & 1) << FEATURE_MMX);
+  Features |= (((EDX >> 25) & 1) << FEATURE_SSE);
+  Features |= (((EDX >> 26) & 1) << FEATURE_SSE2);
+  Features |= (((ECX >> 0) & 1) << FEATURE_SSE3);
+  Features |= (((ECX >> 9) & 1) << FEATURE_SSSE3);
+  Features |= (((ECX >> 19) & 1) << FEATURE_SSE4_1);
+  Features |= (((ECX >> 20) & 1) << FEATURE_SSE4_2);
+  Features |= (((ECX >> 22) & 1) << FEATURE_MOVBE);
+
+  // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
+  // indicates that the AVX registers will be saved and restored on context
+  // switch, then we have full AVX support.
+  const unsigned AVXBits = (1 << 27) | (1 << 28);
+  bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
+                ((EAX & 0x6) == 0x6);
+  bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
+  bool HasLeaf7 =
+      MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+  bool HasADX = HasLeaf7 && ((EBX >> 19) & 1);
+  bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20);
+  bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1);
+  Features |= (HasAVX << FEATURE_AVX);
+  Features |= (HasAVX2 << FEATURE_AVX2);
+  Features |= (HasAVX512 << FEATURE_AVX512);
+  Features |= (HasAVX512Save << FEATURE_AVX512SAVE);
+  Features |= (HasADX << FEATURE_ADX);
+
+  getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+  Features |= (((EDX >> 29) & 0x1) << FEATURE_EM64T);
+  return Features;
+}
+
+StringRef sys::getHostCPUName() {
+  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+  unsigned MaxLeaf, Vendor;
+
+#if defined(__GNUC__) || defined(__clang__)
+  //FIXME: include cpuid.h from clang or copy __get_cpuid_max here
+  // and simplify it to not invoke __cpuid (like cpu_model.c in
+  // compiler-rt/lib/builtins/cpu_model.c?
+  if(!__get_cpuid_max(0, &Vendor))
+    return "generic";
+#endif
+  if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX))
+    return "generic";
+  if (getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
+    return "generic";
+
+  unsigned Brand_id = EBX & 0xff;
+  unsigned Family = 0, Model = 0;
+  unsigned Features = 0;
+  detectX86FamilyModel(EAX, &Family, &Model);
+  Features = getAvailableFeatures(ECX, EDX, MaxLeaf);
+
+  unsigned Type;
+  unsigned Subtype;
+
+  if (Vendor == SIG_INTEL) {
+    getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, &Type,
+                                    &Subtype);
+    switch (Type) {
+    case INTEL_i386:
+      return "i386";
+    case INTEL_i486:
+      return "i486";
+    case INTEL_PENTIUM:
+      if (Subtype == INTEL_PENTIUM_MMX)
+        return "pentium-mmx";
+      return "pentium";
+    case INTEL_PENTIUM_PRO:
+      return "pentiumpro";
+    case INTEL_PENTIUM_II:
+      return "pentium2";
+    case INTEL_PENTIUM_III:
+      return "pentium3";
+    case INTEL_PENTIUM_IV:
+      return "pentium4";
+    case INTEL_PENTIUM_M:
+      return "pentium-m";
+    case INTEL_CORE_DUO:
+      return "yonah";
+    case INTEL_CORE2:
+      switch (Subtype) {
+      case INTEL_CORE2_65:
+        return "core2";
+      case INTEL_CORE2_45:
+        return "penryn";
+      default:
+        return "core2";
+      }
+    case INTEL_COREI7:
+      switch (Subtype) {
+      case INTEL_COREI7_NEHALEM:
+        return "nehalem";
+      case INTEL_COREI7_WESTMERE:
+        return "westmere";
+      case INTEL_COREI7_SANDYBRIDGE:
+        return "sandybridge";
+      case INTEL_COREI7_IVYBRIDGE:
+        return "ivybridge";
+      case INTEL_COREI7_HASWELL:
+        return "haswell";
+      case INTEL_COREI7_BROADWELL:
+        return "broadwell";
+      case INTEL_COREI7_SKYLAKE:
+        return "skylake";
+      case INTEL_COREI7_SKYLAKE_AVX512:
+        return "skylake-avx512";
+      default:
+        return "corei7";
+      }
+    case INTEL_ATOM:
+      switch (Subtype) {
+      case INTEL_ATOM_BONNELL:
+        return "bonnell";
+      case INTEL_ATOM_SILVERMONT:
+        return "silvermont";
+      default:
+        return "atom";
+      }
+    case INTEL_XEONPHI:
+      return "knl"; /*update for more variants added*/
+    case INTEL_X86_64:
+      return "x86-64";
+    case INTEL_NOCONA:
+      return "nocona";
+    case INTEL_PRESCOTT:
+      return "prescott";
+    default:
+      return "generic";
+    }
+  } else if (Vendor == SIG_AMD) {
+    getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype);
+    switch (Type) {
+    case AMD_i486:
+      return "i486";
+    case AMDPENTIUM:
+      switch (Subtype) {
+      case AMDPENTIUM_K6:
+        return "k6";
+      case AMDPENTIUM_K62:
+        return "k6-2";
+      case AMDPENTIUM_K63:
+        return "k6-3";
+      case AMDPENTIUM_GEODE:
+        return "geode";
+      default:
+        return "pentium";
+      }
+    case AMDATHLON:
+      switch (Subtype) {
+      case AMDATHLON_TBIRD:
+        return "athlon-tbird";
+      case AMDATHLON_MP:
+        return "athlon-mp";
+      case AMDATHLON_XP:
+        return "athlon-xp";
+      case AMDATHLON_K8SSE3:
+        return "k8-sse3";
+      case AMDATHLON_OPTERON:
+        return "opteron";
+      case AMDATHLON_FX:
+        return "athlon-fx";
+      case AMDATHLON_64:
+        return "athlon64";
+      default:
+        return "athlon";
+      }
+    case AMDFAM10H:
+      if(Subtype == AMDFAM10H_BARCELONA)
+        return "barcelona";
+      return "amdfam10";
+    case AMDFAM14H:
+      return "btver1";
+    case AMDFAM15H:
+      switch (Subtype) {
+      case AMDFAM15H_BDVER1:
+        return "bdver1";
+      case AMDFAM15H_BDVER2:
+        return "bdver2";
+      case AMDFAM15H_BDVER3:
+        return "bdver3";
+      case AMDFAM15H_BDVER4:
+        return "bdver4";
+      case AMD_BTVER1:
+        return "btver1";
+      default:
+        return "amdfam15";
+      }
+    case AMDFAM16H:
+      switch (Subtype) {
+      case AMD_BTVER1:
+        return "btver1";
+      case AMD_BTVER2:
+        return "btver2";
+      default:
+        return "amdfam16";
+      }
+    default:
+      return "generic";
+    }
+  }
+  return "generic";
+}
+
+#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
+StringRef sys::getHostCPUName() {
+  host_basic_info_data_t hostInfo;
+  mach_msg_type_number_t infoCount;
+
+  infoCount = HOST_BASIC_INFO_COUNT;
+  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
+            &infoCount);
+
+  if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
+    return "generic";
+
+  switch (hostInfo.cpu_subtype) {
+  case CPU_SUBTYPE_POWERPC_601:
+    return "601";
+  case CPU_SUBTYPE_POWERPC_602:
+    return "602";
+  case CPU_SUBTYPE_POWERPC_603:
+    return "603";
+  case CPU_SUBTYPE_POWERPC_603e:
+    return "603e";
+  case CPU_SUBTYPE_POWERPC_603ev:
+    return "603ev";
+  case CPU_SUBTYPE_POWERPC_604:
+    return "604";
+  case CPU_SUBTYPE_POWERPC_604e:
+    return "604e";
+  case CPU_SUBTYPE_POWERPC_620:
+    return "620";
+  case CPU_SUBTYPE_POWERPC_750:
+    return "750";
+  case CPU_SUBTYPE_POWERPC_7400:
+    return "7400";
+  case CPU_SUBTYPE_POWERPC_7450:
+    return "7450";
+  case CPU_SUBTYPE_POWERPC_970:
+    return "970";
+  default:;
+  }
+
+  return "generic";
+}
+#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
+StringRef sys::getHostCPUName() {
+  // Access to the Processor Version Register (PVR) on PowerPC is privileged,
+  // and so we must use an operating-system interface to determine the current
+  // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
+  const char *generic = "generic";
+
+  // The cpu line is second (after the 'processor: 0' line), so if this
+  // buffer is too small then something has changed (or is wrong).
+  char buffer[1024];
+  ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer));
+  if (CPUInfoSize == -1)
+    return generic;
+
+  const char *CPUInfoStart = buffer;
+  const char *CPUInfoEnd = buffer + CPUInfoSize;
+
+  const char *CIP = CPUInfoStart;
+
+  const char *CPUStart = 0;
+  size_t CPULen = 0;
+
+  // We need to find the first line which starts with cpu, spaces, and a colon.
+  // After the colon, there may be some additional spaces and then the cpu type.
+  while (CIP < CPUInfoEnd && CPUStart == 0) {
+    if (CIP < CPUInfoEnd && *CIP == '\n')
+      ++CIP;
+
+    if (CIP < CPUInfoEnd && *CIP == 'c') {
+      ++CIP;
+      if (CIP < CPUInfoEnd && *CIP == 'p') {
+        ++CIP;
+        if (CIP < CPUInfoEnd && *CIP == 'u') {
+          ++CIP;
+          while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
+            ++CIP;
+
+          if (CIP < CPUInfoEnd && *CIP == ':') {
+            ++CIP;
+            while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
+              ++CIP;
+
+            if (CIP < CPUInfoEnd) {
+              CPUStart = CIP;
+              while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
+                                          *CIP != ',' && *CIP != '\n'))
+                ++CIP;
+              CPULen = CIP - CPUStart;
+            }
+          }
+        }
+      }
+    }
+
+    if (CPUStart == 0)
+      while (CIP < CPUInfoEnd && *CIP != '\n')
+        ++CIP;
+  }
+
+  if (CPUStart == 0)
+    return generic;
+
+  return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
+      .Case("604e", "604e")
+      .Case("604", "604")
+      .Case("7400", "7400")
+      .Case("7410", "7400")
+      .Case("7447", "7400")
+      .Case("7455", "7450")
+      .Case("G4", "g4")
+      .Case("POWER4", "970")
+      .Case("PPC970FX", "970")
+      .Case("PPC970MP", "970")
+      .Case("G5", "g5")
+      .Case("POWER5", "g5")
+      .Case("A2", "a2")
+      .Case("POWER6", "pwr6")
+      .Case("POWER7", "pwr7")
+      .Case("POWER8", "pwr8")
+      .Case("POWER8E", "pwr8")
+      .Case("POWER9", "pwr9")
+      .Default(generic);
+}
+#elif defined(__linux__) && defined(__arm__)
+StringRef sys::getHostCPUName() {
+  // The cpuid register on arm is not accessible from user space. On Linux,
+  // it is exposed through the /proc/cpuinfo file.
+
+  // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line
+  // in all cases.
+  char buffer[1024];
+  ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer));
+  if (CPUInfoSize == -1)
+    return "generic";
+
+  StringRef Str(buffer, CPUInfoSize);
+
+  SmallVector<StringRef, 32> Lines;
+  Str.split(Lines, "\n");
+
+  // Look for the CPU implementer line.
+  StringRef Implementer;
+  for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+    if (Lines[I].startswith("CPU implementer"))
+      Implementer = Lines[I].substr(15).ltrim("\t :");
+
+  if (Implementer == "0x41") // ARM Ltd.
+    // Look for the CPU part line.
+    for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+      if (Lines[I].startswith("CPU part"))
+        // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
+        // values correspond to the "Part number" in the CP15/c0 register. The
+        // contents are specified in the various processor manuals.
+        return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
+            .Case("0x926", "arm926ej-s")
+            .Case("0xb02", "mpcore")
+            .Case("0xb36", "arm1136j-s")
+            .Case("0xb56", "arm1156t2-s")
+            .Case("0xb76", "arm1176jz-s")
+            .Case("0xc08", "cortex-a8")
+            .Case("0xc09", "cortex-a9")
+            .Case("0xc0f", "cortex-a15")
+            .Case("0xc20", "cortex-m0")
+            .Case("0xc23", "cortex-m3")
+            .Case("0xc24", "cortex-m4")
+            .Default("generic");
+
+  if (Implementer == "0x51") // Qualcomm Technologies, Inc.
+    // Look for the CPU part line.
+    for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+      if (Lines[I].startswith("CPU part"))
+        // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
+        // values correspond to the "Part number" in the CP15/c0 register. The
+        // contents are specified in the various processor manuals.
+        return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
+            .Case("0x06f", "krait") // APQ8064
+            .Default("generic");
+
+  return "generic";
+}
+#elif defined(__linux__) && defined(__s390x__)
+StringRef sys::getHostCPUName() {
+  // STIDP is a privileged operation, so use /proc/cpuinfo instead.
+
+  // The "processor 0:" line comes after a fair amount of other information,
+  // including a cache breakdown, but this should be plenty.
+  char buffer[2048];
+  ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer));
+  if (CPUInfoSize == -1)
+    return "generic";
+
+  StringRef Str(buffer, CPUInfoSize);
+  SmallVector<StringRef, 32> Lines;
+  Str.split(Lines, "\n");
+
+  // Look for the CPU features.
+  SmallVector<StringRef, 32> CPUFeatures;
+  for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+    if (Lines[I].startswith("features")) {
+      size_t Pos = Lines[I].find(":");
+      if (Pos != StringRef::npos) {
+        Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
+        break;
+      }
+    }
+
+  // We need to check for the presence of vector support independently of
+  // the machine type, since we may only use the vector register set when
+  // supported by the kernel (and hypervisor).
+  bool HaveVectorSupport = false;
+  for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
+    if (CPUFeatures[I] == "vx")
+      HaveVectorSupport = true;
+  }
+
+  // Now check the processor machine type.
+  for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
+    if (Lines[I].startswith("processor ")) {
+      size_t Pos = Lines[I].find("machine = ");
+      if (Pos != StringRef::npos) {
+        Pos += sizeof("machine = ") - 1;
+        unsigned int Id;
+        if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
+          if (Id >= 2964 && HaveVectorSupport)
+            return "z13";
+          if (Id >= 2827)
+            return "zEC12";
+          if (Id >= 2817)
+            return "z196";
+        }
+      }
+      break;
+    }
+  }
+
+  return "generic";
+}
+#else
+StringRef sys::getHostCPUName() { return "generic"; }
+#endif
+
+#if defined(__i386__) || defined(_M_IX86) || \
+    defined(__x86_64__) || defined(_M_X64)
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
+  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+  unsigned MaxLevel;
+  union {
+    unsigned u[3];
+    char c[12];
+  } text;
+
+  if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) ||
+      MaxLevel < 1)
+    return false;
+
+  getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
+
+  Features["cmov"] = (EDX >> 15) & 1;
+  Features["mmx"] = (EDX >> 23) & 1;
+  Features["sse"] = (EDX >> 25) & 1;
+  Features["sse2"] = (EDX >> 26) & 1;
+  Features["sse3"] = (ECX >> 0) & 1;
+  Features["ssse3"] = (ECX >> 9) & 1;
+  Features["sse4.1"] = (ECX >> 19) & 1;
+  Features["sse4.2"] = (ECX >> 20) & 1;
+
+  Features["pclmul"] = (ECX >> 1) & 1;
+  Features["cx16"] = (ECX >> 13) & 1;
+  Features["movbe"] = (ECX >> 22) & 1;
+  Features["popcnt"] = (ECX >> 23) & 1;
+  Features["aes"] = (ECX >> 25) & 1;
+  Features["rdrnd"] = (ECX >> 30) & 1;
+
+  // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
+  // indicates that the AVX registers will be saved and restored on context
+  // switch, then we have full AVX support.
+  bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
+                    !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
+  Features["avx"] = HasAVXSave;
+  Features["fma"] = HasAVXSave && (ECX >> 12) & 1;
+  Features["f16c"] = HasAVXSave && (ECX >> 29) & 1;
+
+  // Only enable XSAVE if OS has enabled support for saving YMM state.
+  Features["xsave"] = HasAVXSave && (ECX >> 26) & 1;
+
+  // AVX512 requires additional context to be saved by the OS.
+  bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
+
+  unsigned MaxExtLevel;
+  getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
+
+  bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
+                     !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+  Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
+  Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
+  Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
+  Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
+  Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
+  Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
+  Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
+
+  bool HasLeaf7 =
+      MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+
+  // AVX2 is only supported if we have the OS save support from AVX.
+  Features["avx2"] = HasAVXSave && HasLeaf7 && ((EBX >> 5) & 1);
+
+  Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
+  Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1);
+  Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
+  Features["hle"] = HasLeaf7 && ((EBX >> 4) & 1);
+  Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
+  Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1);
+  Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
+  Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
+  Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
+  Features["smap"] = HasLeaf7 && ((EBX >> 20) & 1);
+  Features["pcommit"] = HasLeaf7 && ((EBX >> 22) & 1);
+  Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
+  Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1);
+  Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
+
+  // AVX512 is only supported if the OS supports the context save for it.
+  Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
+  Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
+  Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
+  Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
+  Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
+  Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
+  Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
+  Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
+
+  Features["prefetchwt1"] = HasLeaf7 && (ECX & 1);
+  Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save;
+  // Enable protection keys
+  Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);
+
+  bool HasLeafD = MaxLevel >= 0xd &&
+                  !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
+
+  // Only enable XSAVE if OS has enabled support for saving YMM state.
+  Features["xsaveopt"] = HasAVXSave && HasLeafD && ((EAX >> 0) & 1);
+  Features["xsavec"] = HasAVXSave && HasLeafD && ((EAX >> 1) & 1);
+  Features["xsaves"] = HasAVXSave && HasLeafD && ((EAX >> 3) & 1);
+
+  return true;
+}
+#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
+  // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line
+  // in all cases.
+  char buffer[1024];
+  ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer));
+  if (CPUInfoSize == -1)
+    return false;
+
+  StringRef Str(buffer, CPUInfoSize);
+
+  SmallVector<StringRef, 32> Lines;
+  Str.split(Lines, "\n");
+
+  SmallVector<StringRef, 32> CPUFeatures;
+
+  // Look for the CPU features.
+  for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+    if (Lines[I].startswith("Features")) {
+      Lines[I].split(CPUFeatures, ' ');
+      break;
+    }
+
+#if defined(__aarch64__)
+  // Keep track of which crypto features we have seen
+  enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
+  uint32_t crypto = 0;
+#endif
+
+  for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
+    StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
+#if defined(__aarch64__)
+                                   .Case("asimd", "neon")
+                                   .Case("fp", "fp-armv8")
+                                   .Case("crc32", "crc")
+#else
+                                   .Case("half", "fp16")
+                                   .Case("neon", "neon")
+                                   .Case("vfpv3", "vfp3")
+                                   .Case("vfpv3d16", "d16")
+                                   .Case("vfpv4", "vfp4")
+                                   .Case("idiva", "hwdiv-arm")
+                                   .Case("idivt", "hwdiv")
+#endif
+                                   .Default("");
+
+#if defined(__aarch64__)
+    // We need to check crypto separately since we need all of the crypto
+    // extensions to enable the subtarget feature
+    if (CPUFeatures[I] == "aes")
+      crypto |= CAP_AES;
+    else if (CPUFeatures[I] == "pmull")
+      crypto |= CAP_PMULL;
+    else if (CPUFeatures[I] == "sha1")
+      crypto |= CAP_SHA1;
+    else if (CPUFeatures[I] == "sha2")
+      crypto |= CAP_SHA2;
+#endif
+
+    if (LLVMFeatureStr != "")
+      Features[LLVMFeatureStr] = true;
+  }
+
+#if defined(__aarch64__)
+  // If we have all crypto bits we can add the feature
+  if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
+    Features["crypto"] = true;
+#endif
+
+  return true;
+}
+#else
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
+#endif
+
+std::string sys::getProcessTriple() {
+  Triple PT(Triple::normalize(LLVM_HOST_TRIPLE));
+
+  if (sizeof(void *) == 8 && PT.isArch32Bit())
+    PT = PT.get64BitArchVariant();
+  if (sizeof(void *) == 4 && PT.isArch64Bit())
+    PT = PT.get32BitArchVariant();
+
+  return PT.str();
+}
diff --git a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
new file mode 100644
index 0000000..7dd3131
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
@@ -0,0 +1,88 @@
+//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ManagedStatic class and llvm_shutdown().
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/MutexGuard.h"
+#include "llvm/Support/Threading.h"
+#include <cassert>
+using namespace llvm;
+
+static const ManagedStaticBase *StaticList = nullptr;
+static sys::Mutex *ManagedStaticMutex = nullptr;
+LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
+
+static void initializeMutex() {
+  ManagedStaticMutex = new sys::Mutex();
+}
+
+static sys::Mutex* getManagedStaticMutex() {
+  // We need to use a function local static here, since this can get called
+  // during a static constructor and we need to guarantee that it's initialized
+  // correctly.
+  llvm::call_once(mutex_init_flag, initializeMutex);
+  return ManagedStaticMutex;
+}
+
+void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
+                                              void (*Deleter)(void*)) const {
+  assert(Creator);
+  if (llvm_is_multithreaded()) {
+    MutexGuard Lock(*getManagedStaticMutex());
+
+    if (!Ptr.load(std::memory_order_relaxed)) {
+      void *Tmp = Creator();
+
+      Ptr.store(Tmp, std::memory_order_release);
+      DeleterFn = Deleter;
+      
+      // Add to list of managed statics.
+      Next = StaticList;
+      StaticList = this;
+    }
+  } else {
+    assert(!Ptr && !DeleterFn && !Next &&
+           "Partially initialized ManagedStatic!?");
+    Ptr = Creator();
+    DeleterFn = Deleter;
+  
+    // Add to list of managed statics.
+    Next = StaticList;
+    StaticList = this;
+  }
+}
+
+void ManagedStaticBase::destroy() const {
+  assert(DeleterFn && "ManagedStatic not initialized correctly!");
+  assert(StaticList == this &&
+         "Not destroyed in reverse order of construction?");
+  // Unlink from list.
+  StaticList = Next;
+  Next = nullptr;
+
+  // Destroy memory.
+  DeleterFn(Ptr);
+  
+  // Cleanup.
+  Ptr = nullptr;
+  DeleterFn = nullptr;
+}
+
+/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
+void llvm::llvm_shutdown() {
+  MutexGuard Lock(*getManagedStaticMutex());
+
+  while (StaticList)
+    StaticList->destroy();
+}
diff --git a/third_party/llvm-subzero/lib/Support/MemoryBuffer.cpp b/third_party/llvm-subzero/lib/Support/MemoryBuffer.cpp
new file mode 100644
index 0000000..b935cbf
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/MemoryBuffer.cpp
@@ -0,0 +1,445 @@
+//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the MemoryBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <new>
+#include <sys/types.h>
+#include <system_error>
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// MemoryBuffer implementation itself.
+//===----------------------------------------------------------------------===//
+
+MemoryBuffer::~MemoryBuffer() { }
+
+/// init - Initialize this MemoryBuffer as a reference to externally allocated
+/// memory, memory that we know is already null terminated.
+void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
+                        bool RequiresNullTerminator) {
+  assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
+         "Buffer is not null terminated!");
+  BufferStart = BufStart;
+  BufferEnd = BufEnd;
+}
+
+//===----------------------------------------------------------------------===//
+// MemoryBufferMem implementation.
+//===----------------------------------------------------------------------===//
+
+/// CopyStringRef - Copies contents of a StringRef into a block of memory and
+/// null-terminates it.
+static void CopyStringRef(char *Memory, StringRef Data) {
+  if (!Data.empty())
+    memcpy(Memory, Data.data(), Data.size());
+  Memory[Data.size()] = 0; // Null terminate string.
+}
+
+namespace {
+struct NamedBufferAlloc {
+  const Twine &Name;
+  NamedBufferAlloc(const Twine &Name) : Name(Name) {}
+};
+}
+
+void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
+  SmallString<256> NameBuf;
+  StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
+
+  char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1));
+  CopyStringRef(Mem + N, NameRef);
+  return Mem;
+}
+
+namespace {
+/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
+class MemoryBufferMem : public MemoryBuffer {
+public:
+  MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
+    init(InputData.begin(), InputData.end(), RequiresNullTerminator);
+  }
+
+  /// Disable sized deallocation for MemoryBufferMem, because it has
+  /// tail-allocated data.
+  void operator delete(void *p) { ::operator delete(p); }
+
+  const char *getBufferIdentifier() const override {
+     // The name is stored after the class itself.
+    return reinterpret_cast<const char*>(this + 1);
+  }
+
+  BufferKind getBufferKind() const override {
+    return MemoryBuffer_Malloc;
+  }
+};
+}
+
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, 
+           uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
+
+std::unique_ptr<MemoryBuffer>
+MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
+                           bool RequiresNullTerminator) {
+  auto *Ret = new (NamedBufferAlloc(BufferName))
+      MemoryBufferMem(InputData, RequiresNullTerminator);
+  return std::unique_ptr<MemoryBuffer>(Ret);
+}
+
+std::unique_ptr<MemoryBuffer>
+MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) {
+  return std::unique_ptr<MemoryBuffer>(getMemBuffer(
+      Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
+}
+
+std::unique_ptr<MemoryBuffer>
+MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) {
+  std::unique_ptr<MemoryBuffer> Buf =
+      getNewUninitMemBuffer(InputData.size(), BufferName);
+  if (!Buf)
+    return nullptr;
+  memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
+         InputData.size());
+  return Buf;
+}
+
+std::unique_ptr<MemoryBuffer>
+MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
+  // Allocate space for the MemoryBuffer, the data and the name. It is important
+  // that MemoryBuffer and data are aligned so PointerIntPair works with them.
+  // TODO: Is 16-byte alignment enough?  We copy small object files with large
+  // alignment expectations into this buffer.
+  SmallString<256> NameBuf;
+  StringRef NameRef = BufferName.toStringRef(NameBuf);
+  size_t AlignedStringLen =
+      alignTo(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);
+  size_t RealLen = AlignedStringLen + Size + 1;
+  char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
+  if (!Mem)
+    return nullptr;
+
+  // The name is stored after the class itself.
+  CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef);
+
+  // The buffer begins after the name and must be aligned.
+  char *Buf = Mem + AlignedStringLen;
+  Buf[Size] = 0; // Null terminate buffer.
+
+  auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
+  return std::unique_ptr<MemoryBuffer>(Ret);
+}
+
+std::unique_ptr<MemoryBuffer>
+MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
+  std::unique_ptr<MemoryBuffer> SB = getNewUninitMemBuffer(Size, BufferName);
+  if (!SB)
+    return nullptr;
+  memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
+  return SB;
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize,
+                             bool RequiresNullTerminator) {
+  SmallString<256> NameBuf;
+  StringRef NameRef = Filename.toStringRef(NameBuf);
+
+  if (NameRef == "-")
+    return getSTDIN();
+  return getFile(Filename, FileSize, RequiresNullTerminator);
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, 
+                           uint64_t Offset) {
+  return getFileAux(FilePath, -1, MapSize, Offset, false, false);
+}
+
+
+//===----------------------------------------------------------------------===//
+// MemoryBuffer::getFile implementation.
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// \brief Memory maps a file descriptor using sys::fs::mapped_file_region.
+///
+/// This handles converting the offset into a legal offset on the platform.
+class MemoryBufferMMapFile : public MemoryBuffer {
+  sys::fs::mapped_file_region MFR;
+
+  static uint64_t getLegalMapOffset(uint64_t Offset) {
+    return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
+  }
+
+  static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
+    return Len + (Offset - getLegalMapOffset(Offset));
+  }
+
+  const char *getStart(uint64_t Len, uint64_t Offset) {
+    return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
+  }
+
+public:
+  MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
+                       uint64_t Offset, std::error_code &EC)
+      : MFR(FD, sys::fs::mapped_file_region::readonly,
+            getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
+    if (!EC) {
+      const char *Start = getStart(Len, Offset);
+      init(Start, Start + Len, RequiresNullTerminator);
+    }
+  }
+
+  /// Disable sized deallocation for MemoryBufferMMapFile, because it has
+  /// tail-allocated data.
+  void operator delete(void *p) { ::operator delete(p); }
+
+  const char *getBufferIdentifier() const override {
+    // The name is stored after the class itself.
+    return reinterpret_cast<const char *>(this + 1);
+  }
+
+  BufferKind getBufferKind() const override {
+    return MemoryBuffer_MMap;
+  }
+};
+}
+
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getMemoryBufferForStream(int FD, const Twine &BufferName) {
+  const ssize_t ChunkSize = 4096*4;
+  SmallString<ChunkSize> Buffer;
+  ssize_t ReadBytes;
+  // Read into Buffer until we hit EOF.
+  do {
+    Buffer.reserve(Buffer.size() + ChunkSize);
+    ReadBytes = read(FD, Buffer.end(), ChunkSize);
+    if (ReadBytes == -1) {
+      if (errno == EINTR) continue;
+      return std::error_code(errno, std::generic_category());
+    }
+    Buffer.set_size(Buffer.size() + ReadBytes);
+  } while (ReadBytes != 0);
+
+  return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);
+}
+
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
+                      bool RequiresNullTerminator, bool IsVolatileSize) {
+  return getFileAux(Filename, FileSize, FileSize, 0,
+                    RequiresNullTerminator, IsVolatileSize);
+}
+
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
+                uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
+                bool IsVolatileSize);
+
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
+           uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
+  int FD;
+  std::error_code EC = sys::fs::openFileForRead(Filename, FD);
+  if (EC)
+    return EC;
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> Ret =
+      getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
+                      RequiresNullTerminator, IsVolatileSize);
+  close(FD);
+  return Ret;
+}
+
+static bool shouldUseMmap(int FD,
+                          size_t FileSize,
+                          size_t MapSize,
+                          off_t Offset,
+                          bool RequiresNullTerminator,
+                          int PageSize,
+                          bool IsVolatileSize) {
+  // mmap may leave the buffer without null terminator if the file size changed
+  // by the time the last page is mapped in, so avoid it if the file size is
+  // likely to change.
+  if (IsVolatileSize)
+    return false;
+
+  // We don't use mmap for small files because this can severely fragment our
+  // address space.
+  if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
+    return false;
+
+  if (!RequiresNullTerminator)
+    return true;
+
+
+  // If we don't know the file size, use fstat to find out.  fstat on an open
+  // file descriptor is cheaper than stat on a random path.
+  // FIXME: this chunk of code is duplicated, but it avoids a fstat when
+  // RequiresNullTerminator = false and MapSize != -1.
+  if (FileSize == size_t(-1)) {
+    sys::fs::file_status Status;
+    if (sys::fs::status(FD, Status))
+      return false;
+    FileSize = Status.getSize();
+  }
+
+  // If we need a null terminator and the end of the map is inside the file,
+  // we cannot use mmap.
+  size_t End = Offset + MapSize;
+  assert(End <= FileSize);
+  if (End != FileSize)
+    return false;
+
+  // Don't try to map files that are exactly a multiple of the system page size
+  // if we need a null terminator.
+  if ((FileSize & (PageSize -1)) == 0)
+    return false;
+
+#if defined(__CYGWIN__)
+  // Don't try to map files that are exactly a multiple of the physical page size
+  // if we need a null terminator.
+  // FIXME: We should reorganize again getPageSize() on Win32.
+  if ((FileSize & (4096 - 1)) == 0)
+    return false;
+#endif
+
+  return true;
+}
+
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
+                uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
+                bool IsVolatileSize) {
+  static int PageSize = sys::Process::getPageSize();
+
+  // Default is to map the full file.
+  if (MapSize == uint64_t(-1)) {
+    // If we don't know the file size, use fstat to find out.  fstat on an open
+    // file descriptor is cheaper than stat on a random path.
+    if (FileSize == uint64_t(-1)) {
+      sys::fs::file_status Status;
+      std::error_code EC = sys::fs::status(FD, Status);
+      if (EC)
+        return EC;
+
+      // If this not a file or a block device (e.g. it's a named pipe
+      // or character device), we can't trust the size. Create the memory
+      // buffer by copying off the stream.
+      sys::fs::file_type Type = Status.type();
+      if (Type != sys::fs::file_type::regular_file &&
+          Type != sys::fs::file_type::block_file)
+        return getMemoryBufferForStream(FD, Filename);
+
+      FileSize = Status.getSize();
+    }
+    MapSize = FileSize;
+  }
+
+  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
+                    PageSize, IsVolatileSize)) {
+    std::error_code EC;
+    std::unique_ptr<MemoryBuffer> Result(
+        new (NamedBufferAlloc(Filename))
+        MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC));
+    if (!EC)
+      return std::move(Result);
+  }
+
+  std::unique_ptr<MemoryBuffer> Buf =
+      MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
+  if (!Buf) {
+    // Failed to create a buffer. The only way it can fail is if
+    // new(std::nothrow) returns 0.
+    return make_error_code(errc::not_enough_memory);
+  }
+
+  char *BufPtr = const_cast<char *>(Buf->getBufferStart());
+
+  size_t BytesLeft = MapSize;
+#ifndef HAVE_PREAD
+  if (lseek(FD, Offset, SEEK_SET) == -1)
+    return std::error_code(errno, std::generic_category());
+#endif
+
+  while (BytesLeft) {
+#ifdef HAVE_PREAD
+    ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
+#else
+    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
+#endif
+    if (NumRead == -1) {
+      if (errno == EINTR)
+        continue;
+      // Error while reading.
+      return std::error_code(errno, std::generic_category());
+    }
+    if (NumRead == 0) {
+      memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.
+      break;
+    }
+    BytesLeft -= NumRead;
+    BufPtr += NumRead;
+  }
+
+  return std::move(Buf);
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
+                          bool RequiresNullTerminator, bool IsVolatileSize) {
+  return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
+                         RequiresNullTerminator, IsVolatileSize);
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
+                               int64_t Offset) {
+  assert(MapSize != uint64_t(-1));
+  return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false,
+                         /*IsVolatileSize*/ false);
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
+  // Read in all of the data from stdin, we cannot mmap stdin.
+  //
+  // FIXME: That isn't necessarily true, we should try to mmap stdin and
+  // fallback if it fails.
+  sys::ChangeStdinToBinary();
+
+  return getMemoryBufferForStream(0, "<stdin>");
+}
+
+MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
+  StringRef Data = getBuffer();
+  StringRef Identifier = getBufferIdentifier();
+  return MemoryBufferRef(Data, Identifier);
+}
diff --git a/third_party/llvm-subzero/lib/Support/Mutex.cpp b/third_party/llvm-subzero/lib/Support/Mutex.cpp
new file mode 100644
index 0000000..c8d3844
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Mutex.cpp
@@ -0,0 +1,122 @@
+//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the llvm::sys::Mutex class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/Mutex.h"
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//===          independent code.
+//===----------------------------------------------------------------------===//
+
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+// Define all methods as no-ops if threading is explicitly disabled
+namespace llvm {
+using namespace sys;
+MutexImpl::MutexImpl( bool recursive) { }
+MutexImpl::~MutexImpl() { }
+bool MutexImpl::acquire() { return true; }
+bool MutexImpl::release() { return true; }
+bool MutexImpl::tryacquire() { return true; }
+}
+#else
+
+#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace llvm {
+using namespace sys;
+
+// Construct a Mutex using pthread calls
+MutexImpl::MutexImpl( bool recursive)
+  : data_(nullptr)
+{
+  // Declare the pthread_mutex data structures
+  pthread_mutex_t* mutex =
+    static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
+  pthread_mutexattr_t attr;
+
+  // Initialize the mutex attributes
+  int errorcode = pthread_mutexattr_init(&attr);
+  assert(errorcode == 0); (void)errorcode;
+
+  // Initialize the mutex as a recursive mutex, if requested, or normal
+  // otherwise.
+  int kind = ( recursive  ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
+  errorcode = pthread_mutexattr_settype(&attr, kind);
+  assert(errorcode == 0);
+
+  // Initialize the mutex
+  errorcode = pthread_mutex_init(mutex, &attr);
+  assert(errorcode == 0);
+
+  // Destroy the attributes
+  errorcode = pthread_mutexattr_destroy(&attr);
+  assert(errorcode == 0);
+
+  // Assign the data member
+  data_ = mutex;
+}
+
+// Destruct a Mutex
+MutexImpl::~MutexImpl()
+{
+  pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+  assert(mutex != nullptr);
+  pthread_mutex_destroy(mutex);
+  free(mutex);
+}
+
+bool
+MutexImpl::acquire()
+{
+  pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+  assert(mutex != nullptr);
+
+  int errorcode = pthread_mutex_lock(mutex);
+  return errorcode == 0;
+}
+
+bool
+MutexImpl::release()
+{
+  pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+  assert(mutex != nullptr);
+
+  int errorcode = pthread_mutex_unlock(mutex);
+  return errorcode == 0;
+}
+
+bool
+MutexImpl::tryacquire()
+{
+  pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+  assert(mutex != nullptr);
+
+  int errorcode = pthread_mutex_trylock(mutex);
+  return errorcode == 0;
+}
+
+}
+
+#elif defined(LLVM_ON_UNIX)
+#include "Unix/Mutex.inc"
+#elif defined( LLVM_ON_WIN32)
+#include "Windows/Mutex.inc"
+#else
+#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp
+#endif
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/Path.cpp b/third_party/llvm-subzero/lib/Support/Path.cpp
new file mode 100644
index 0000000..f6355d1
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Path.cpp
@@ -0,0 +1,1188 @@
+//===-- Path.cpp - Implement OS Path Concept ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the operating system Path API.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/MachO.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include <cctype>
+#include <cstring>
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+using namespace llvm;
+using namespace llvm::support::endian;
+
+namespace {
+  using llvm::StringRef;
+  using llvm::sys::path::is_separator;
+
+#ifdef LLVM_ON_WIN32
+  const char *separators = "\\/";
+  const char preferred_separator = '\\';
+#else
+  const char  separators = '/';
+  const char preferred_separator = '/';
+#endif
+
+  StringRef find_first_component(StringRef path) {
+    // Look for this first component in the following order.
+    // * empty (in this case we return an empty string)
+    // * either C: or {//,\\}net.
+    // * {/,\}
+    // * {file,directory}name
+
+    if (path.empty())
+      return path;
+
+#ifdef LLVM_ON_WIN32
+    // C:
+    if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) &&
+        path[1] == ':')
+      return path.substr(0, 2);
+#endif
+
+    // //net
+    if ((path.size() > 2) &&
+        is_separator(path[0]) &&
+        path[0] == path[1] &&
+        !is_separator(path[2])) {
+      // Find the next directory separator.
+      size_t end = path.find_first_of(separators, 2);
+      return path.substr(0, end);
+    }
+
+    // {/,\}
+    if (is_separator(path[0]))
+      return path.substr(0, 1);
+
+    // * {file,directory}name
+    size_t end = path.find_first_of(separators);
+    return path.substr(0, end);
+  }
+
+  size_t filename_pos(StringRef str) {
+    if (str.size() == 2 &&
+        is_separator(str[0]) &&
+        str[0] == str[1])
+      return 0;
+
+    if (str.size() > 0 && is_separator(str[str.size() - 1]))
+      return str.size() - 1;
+
+    size_t pos = str.find_last_of(separators, str.size() - 1);
+
+#ifdef LLVM_ON_WIN32
+    if (pos == StringRef::npos)
+      pos = str.find_last_of(':', str.size() - 2);
+#endif
+
+    if (pos == StringRef::npos ||
+        (pos == 1 && is_separator(str[0])))
+      return 0;
+
+    return pos + 1;
+  }
+
+  size_t root_dir_start(StringRef str) {
+    // case "c:/"
+#ifdef LLVM_ON_WIN32
+    if (str.size() > 2 &&
+        str[1] == ':' &&
+        is_separator(str[2]))
+      return 2;
+#endif
+
+    // case "//"
+    if (str.size() == 2 &&
+        is_separator(str[0]) &&
+        str[0] == str[1])
+      return StringRef::npos;
+
+    // case "//net"
+    if (str.size() > 3 &&
+        is_separator(str[0]) &&
+        str[0] == str[1] &&
+        !is_separator(str[2])) {
+      return str.find_first_of(separators, 2);
+    }
+
+    // case "/"
+    if (str.size() > 0 && is_separator(str[0]))
+      return 0;
+
+    return StringRef::npos;
+  }
+
+  size_t parent_path_end(StringRef path) {
+    size_t end_pos = filename_pos(path);
+
+    bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
+
+    // Skip separators except for root dir.
+    size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
+
+    while(end_pos > 0 &&
+          (end_pos - 1) != root_dir_pos &&
+          is_separator(path[end_pos - 1]))
+      --end_pos;
+
+    if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
+      return StringRef::npos;
+
+    return end_pos;
+  }
+} // end unnamed namespace
+
+enum FSEntity {
+  FS_Dir,
+  FS_File,
+  FS_Name
+};
+
+static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
+                                          SmallVectorImpl<char> &ResultPath,
+                                          bool MakeAbsolute, unsigned Mode,
+                                          FSEntity Type) {
+  SmallString<128> ModelStorage;
+  Model.toVector(ModelStorage);
+
+  if (MakeAbsolute) {
+    // Make model absolute by prepending a temp directory if it's not already.
+    if (!sys::path::is_absolute(Twine(ModelStorage))) {
+      SmallString<128> TDir;
+      sys::path::system_temp_directory(true, TDir);
+      sys::path::append(TDir, Twine(ModelStorage));
+      ModelStorage.swap(TDir);
+    }
+  }
+
+  // From here on, DO NOT modify model. It may be needed if the randomly chosen
+  // path already exists.
+  ResultPath = ModelStorage;
+  // Null terminate.
+  ResultPath.push_back(0);
+  ResultPath.pop_back();
+
+retry_random_path:
+  // Replace '%' with random chars.
+  for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
+    if (ModelStorage[i] == '%')
+      ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
+  }
+
+  // Try to open + create the file.
+  switch (Type) {
+  case FS_File: {
+    if (std::error_code EC =
+            sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
+                                      sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
+      if (EC == errc::file_exists)
+        goto retry_random_path;
+      return EC;
+    }
+
+    return std::error_code();
+  }
+
+  case FS_Name: {
+    std::error_code EC =
+        sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
+    if (EC == errc::no_such_file_or_directory)
+      return std::error_code();
+    if (EC)
+      return EC;
+    goto retry_random_path;
+  }
+
+  case FS_Dir: {
+    if (std::error_code EC =
+            sys::fs::create_directory(ResultPath.begin(), false)) {
+      if (EC == errc::file_exists)
+        goto retry_random_path;
+      return EC;
+    }
+    return std::error_code();
+  }
+  }
+  llvm_unreachable("Invalid Type");
+}
+
+namespace llvm {
+namespace sys  {
+namespace path {
+
+const_iterator begin(StringRef path) {
+  const_iterator i;
+  i.Path      = path;
+  i.Component = find_first_component(path);
+  i.Position  = 0;
+  return i;
+}
+
+const_iterator end(StringRef path) {
+  const_iterator i;
+  i.Path      = path;
+  i.Position  = path.size();
+  return i;
+}
+
+const_iterator &const_iterator::operator++() {
+  assert(Position < Path.size() && "Tried to increment past end!");
+
+  // Increment Position to past the current component
+  Position += Component.size();
+
+  // Check for end.
+  if (Position == Path.size()) {
+    Component = StringRef();
+    return *this;
+  }
+
+  // Both POSIX and Windows treat paths that begin with exactly two separators
+  // specially.
+  bool was_net = Component.size() > 2 &&
+    is_separator(Component[0]) &&
+    Component[1] == Component[0] &&
+    !is_separator(Component[2]);
+
+  // Handle separators.
+  if (is_separator(Path[Position])) {
+    // Root dir.
+    if (was_net
+#ifdef LLVM_ON_WIN32
+        // c:/
+        || Component.endswith(":")
+#endif
+        ) {
+      Component = Path.substr(Position, 1);
+      return *this;
+    }
+
+    // Skip extra separators.
+    while (Position != Path.size() &&
+           is_separator(Path[Position])) {
+      ++Position;
+    }
+
+    // Treat trailing '/' as a '.'.
+    if (Position == Path.size()) {
+      --Position;
+      Component = ".";
+      return *this;
+    }
+  }
+
+  // Find next component.
+  size_t end_pos = Path.find_first_of(separators, Position);
+  Component = Path.slice(Position, end_pos);
+
+  return *this;
+}
+
+bool const_iterator::operator==(const const_iterator &RHS) const {
+  return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
+}
+
+ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
+  return Position - RHS.Position;
+}
+
+reverse_iterator rbegin(StringRef Path) {
+  reverse_iterator I;
+  I.Path = Path;
+  I.Position = Path.size();
+  return ++I;
+}
+
+reverse_iterator rend(StringRef Path) {
+  reverse_iterator I;
+  I.Path = Path;
+  I.Component = Path.substr(0, 0);
+  I.Position = 0;
+  return I;
+}
+
+reverse_iterator &reverse_iterator::operator++() {
+  // If we're at the end and the previous char was a '/', return '.' unless
+  // we are the root path.
+  size_t root_dir_pos = root_dir_start(Path);
+  if (Position == Path.size() &&
+      Path.size() > root_dir_pos + 1 &&
+      is_separator(Path[Position - 1])) {
+    --Position;
+    Component = ".";
+    return *this;
+  }
+
+  // Skip separators unless it's the root directory.
+  size_t end_pos = Position;
+
+  while(end_pos > 0 &&
+        (end_pos - 1) != root_dir_pos &&
+        is_separator(Path[end_pos - 1]))
+    --end_pos;
+
+  // Find next separator.
+  size_t start_pos = filename_pos(Path.substr(0, end_pos));
+  Component = Path.slice(start_pos, end_pos);
+  Position = start_pos;
+  return *this;
+}
+
+bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
+  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
+         Position == RHS.Position;
+}
+
+ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
+  return Position - RHS.Position;
+}
+
+StringRef root_path(StringRef path) {
+  const_iterator b = begin(path),
+                 pos = b,
+                 e = end(path);
+  if (b != e) {
+    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
+    bool has_drive =
+#ifdef LLVM_ON_WIN32
+      b->endswith(":");
+#else
+      false;
+#endif
+
+    if (has_net || has_drive) {
+      if ((++pos != e) && is_separator((*pos)[0])) {
+        // {C:/,//net/}, so get the first two components.
+        return path.substr(0, b->size() + pos->size());
+      } else {
+        // just {C:,//net}, return the first component.
+        return *b;
+      }
+    }
+
+    // POSIX style root directory.
+    if (is_separator((*b)[0])) {
+      return *b;
+    }
+  }
+
+  return StringRef();
+}
+
+StringRef root_name(StringRef path) {
+  const_iterator b = begin(path),
+                 e = end(path);
+  if (b != e) {
+    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
+    bool has_drive =
+#ifdef LLVM_ON_WIN32
+      b->endswith(":");
+#else
+      false;
+#endif
+
+    if (has_net || has_drive) {
+      // just {C:,//net}, return the first component.
+      return *b;
+    }
+  }
+
+  // No path or no name.
+  return StringRef();
+}
+
+StringRef root_directory(StringRef path) {
+  const_iterator b = begin(path),
+                 pos = b,
+                 e = end(path);
+  if (b != e) {
+    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
+    bool has_drive =
+#ifdef LLVM_ON_WIN32
+      b->endswith(":");
+#else
+      false;
+#endif
+
+    if ((has_net || has_drive) &&
+        // {C:,//net}, skip to the next component.
+        (++pos != e) && is_separator((*pos)[0])) {
+      return *pos;
+    }
+
+    // POSIX style root directory.
+    if (!has_net && is_separator((*b)[0])) {
+      return *b;
+    }
+  }
+
+  // No path or no root.
+  return StringRef();
+}
+
+StringRef relative_path(StringRef path) {
+  StringRef root = root_path(path);
+  return path.substr(root.size());
+}
+
+void append(SmallVectorImpl<char> &path, const Twine &a,
+                                         const Twine &b,
+                                         const Twine &c,
+                                         const Twine &d) {
+  SmallString<32> a_storage;
+  SmallString<32> b_storage;
+  SmallString<32> c_storage;
+  SmallString<32> d_storage;
+
+  SmallVector<StringRef, 4> components;
+  if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
+  if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
+  if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
+  if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
+
+  for (auto &component : components) {
+    bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]);
+    bool component_has_sep = !component.empty() && is_separator(component[0]);
+    bool is_root_name = has_root_name(component);
+
+    if (path_has_sep) {
+      // Strip separators from beginning of component.
+      size_t loc = component.find_first_not_of(separators);
+      StringRef c = component.substr(loc);
+
+      // Append it.
+      path.append(c.begin(), c.end());
+      continue;
+    }
+
+    if (!component_has_sep && !(path.empty() || is_root_name)) {
+      // Add a separator.
+      path.push_back(preferred_separator);
+    }
+
+    path.append(component.begin(), component.end());
+  }
+}
+
+void append(SmallVectorImpl<char> &path,
+            const_iterator begin, const_iterator end) {
+  for (; begin != end; ++begin)
+    path::append(path, *begin);
+}
+
+StringRef parent_path(StringRef path) {
+  size_t end_pos = parent_path_end(path);
+  if (end_pos == StringRef::npos)
+    return StringRef();
+  else
+    return path.substr(0, end_pos);
+}
+
+void remove_filename(SmallVectorImpl<char> &path) {
+  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()));
+  if (end_pos != StringRef::npos)
+    path.set_size(end_pos);
+}
+
+void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
+  StringRef p(path.begin(), path.size());
+  SmallString<32> ext_storage;
+  StringRef ext = extension.toStringRef(ext_storage);
+
+  // Erase existing extension.
+  size_t pos = p.find_last_of('.');
+  if (pos != StringRef::npos && pos >= filename_pos(p))
+    path.set_size(pos);
+
+  // Append '.' if needed.
+  if (ext.size() > 0 && ext[0] != '.')
+    path.push_back('.');
+
+  // Append extension.
+  path.append(ext.begin(), ext.end());
+}
+
+void replace_path_prefix(SmallVectorImpl<char> &Path,
+                         const StringRef &OldPrefix,
+                         const StringRef &NewPrefix) {
+  if (OldPrefix.empty() && NewPrefix.empty())
+    return;
+
+  StringRef OrigPath(Path.begin(), Path.size());
+  if (!OrigPath.startswith(OldPrefix))
+    return;
+
+  // If prefixes have the same size we can simply copy the new one over.
+  if (OldPrefix.size() == NewPrefix.size()) {
+    std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
+    return;
+  }
+
+  StringRef RelPath = OrigPath.substr(OldPrefix.size());
+  SmallString<256> NewPath;
+  path::append(NewPath, NewPrefix);
+  path::append(NewPath, RelPath);
+  Path.swap(NewPath);
+}
+
+void native(const Twine &path, SmallVectorImpl<char> &result) {
+  assert((!path.isSingleStringRef() ||
+          path.getSingleStringRef().data() != result.data()) &&
+         "path and result are not allowed to overlap!");
+  // Clear result.
+  result.clear();
+  path.toVector(result);
+  native(result);
+}
+
+void native(SmallVectorImpl<char> &Path) {
+#ifdef LLVM_ON_WIN32
+  std::replace(Path.begin(), Path.end(), '/', '\\');
+#else
+  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
+    if (*PI == '\\') {
+      auto PN = PI + 1;
+      if (PN < PE && *PN == '\\')
+        ++PI; // increment once, the for loop will move over the escaped slash
+      else
+        *PI = '/';
+    }
+  }
+#endif
+}
+
+StringRef filename(StringRef path) {
+  return *rbegin(path);
+}
+
+StringRef stem(StringRef path) {
+  StringRef fname = filename(path);
+  size_t pos = fname.find_last_of('.');
+  if (pos == StringRef::npos)
+    return fname;
+  else
+    if ((fname.size() == 1 && fname == ".") ||
+        (fname.size() == 2 && fname == ".."))
+      return fname;
+    else
+      return fname.substr(0, pos);
+}
+
+StringRef extension(StringRef path) {
+  StringRef fname = filename(path);
+  size_t pos = fname.find_last_of('.');
+  if (pos == StringRef::npos)
+    return StringRef();
+  else
+    if ((fname.size() == 1 && fname == ".") ||
+        (fname.size() == 2 && fname == ".."))
+      return StringRef();
+    else
+      return fname.substr(pos);
+}
+
+bool is_separator(char value) {
+  switch(value) {
+#ifdef LLVM_ON_WIN32
+    case '\\': // fall through
+#endif
+    case '/': return true;
+    default: return false;
+  }
+}
+
+static const char preferred_separator_string[] = { preferred_separator, '\0' };
+
+StringRef get_separator() {
+  return preferred_separator_string;
+}
+
+bool has_root_name(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !root_name(p).empty();
+}
+
+bool has_root_directory(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !root_directory(p).empty();
+}
+
+bool has_root_path(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !root_path(p).empty();
+}
+
+bool has_relative_path(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !relative_path(p).empty();
+}
+
+bool has_filename(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !filename(p).empty();
+}
+
+bool has_parent_path(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !parent_path(p).empty();
+}
+
+bool has_stem(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !stem(p).empty();
+}
+
+bool has_extension(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  return !extension(p).empty();
+}
+
+bool is_absolute(const Twine &path) {
+  SmallString<128> path_storage;
+  StringRef p = path.toStringRef(path_storage);
+
+  bool rootDir = has_root_directory(p),
+#ifdef LLVM_ON_WIN32
+       rootName = has_root_name(p);
+#else
+       rootName = true;
+#endif
+
+  return rootDir && rootName;
+}
+
+bool is_relative(const Twine &path) { return !is_absolute(path); }
+
+StringRef remove_leading_dotslash(StringRef Path) {
+  // Remove leading "./" (or ".//" or "././" etc.)
+  while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1])) {
+    Path = Path.substr(2);
+    while (Path.size() > 0 && is_separator(Path[0]))
+      Path = Path.substr(1);
+  }
+  return Path;
+}
+
+static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot) {
+  SmallVector<StringRef, 16> components;
+
+  // Skip the root path, then look for traversal in the components.
+  StringRef rel = path::relative_path(path);
+  for (StringRef C : llvm::make_range(path::begin(rel), path::end(rel))) {
+    if (C == ".")
+      continue;
+    if (remove_dot_dot) {
+      if (C == "..") {
+        if (!components.empty())
+          components.pop_back();
+        continue;
+      }
+    }
+    components.push_back(C);
+  }
+
+  SmallString<256> buffer = path::root_path(path);
+  for (StringRef C : components)
+    path::append(buffer, C);
+  return buffer;
+}
+
+bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot) {
+  StringRef p(path.data(), path.size());
+
+  SmallString<256> result = remove_dots(p, remove_dot_dot);
+  if (result == path)
+    return false;
+
+  path.swap(result);
+  return true;
+}
+
+} // end namespace path
+
+namespace fs {
+
+std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
+  file_status Status;
+  std::error_code EC = status(Path, Status);
+  if (EC)
+    return EC;
+  Result = Status.getUniqueID();
+  return std::error_code();
+}
+
+std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
+                                 SmallVectorImpl<char> &ResultPath,
+                                 unsigned Mode) {
+  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
+}
+
+std::error_code createUniqueFile(const Twine &Model,
+                                 SmallVectorImpl<char> &ResultPath) {
+  int Dummy;
+  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
+}
+
+static std::error_code
+createTemporaryFile(const Twine &Model, int &ResultFD,
+                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
+  SmallString<128> Storage;
+  StringRef P = Model.toNullTerminatedStringRef(Storage);
+  assert(P.find_first_of(separators) == StringRef::npos &&
+         "Model must be a simple filename.");
+  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
+  return createUniqueEntity(P.begin(), ResultFD, ResultPath,
+                            true, owner_read | owner_write, Type);
+}
+
+static std::error_code
+createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
+                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
+  const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
+  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
+                             Type);
+}
+
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+                                    int &ResultFD,
+                                    SmallVectorImpl<char> &ResultPath) {
+  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
+}
+
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+                                    SmallVectorImpl<char> &ResultPath) {
+  int Dummy;
+  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
+}
+
+
+// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
+// for consistency. We should try using mkdtemp.
+std::error_code createUniqueDirectory(const Twine &Prefix,
+                                      SmallVectorImpl<char> &ResultPath) {
+  int Dummy;
+  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
+                            true, 0, FS_Dir);
+}
+
+static std::error_code make_absolute(const Twine &current_directory,
+                                     SmallVectorImpl<char> &path,
+                                     bool use_current_directory) {
+  StringRef p(path.data(), path.size());
+
+  bool rootDirectory = path::has_root_directory(p),
+#ifdef LLVM_ON_WIN32
+       rootName = path::has_root_name(p);
+#else
+       rootName = true;
+#endif
+
+  // Already absolute.
+  if (rootName && rootDirectory)
+    return std::error_code();
+
+  // All of the following conditions will need the current directory.
+  SmallString<128> current_dir;
+  if (use_current_directory)
+    current_directory.toVector(current_dir);
+  else if (std::error_code ec = current_path(current_dir))
+    return ec;
+
+  // Relative path. Prepend the current directory.
+  if (!rootName && !rootDirectory) {
+    // Append path to the current directory.
+    path::append(current_dir, p);
+    // Set path to the result.
+    path.swap(current_dir);
+    return std::error_code();
+  }
+
+  if (!rootName && rootDirectory) {
+    StringRef cdrn = path::root_name(current_dir);
+    SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
+    path::append(curDirRootName, p);
+    // Set path to the result.
+    path.swap(curDirRootName);
+    return std::error_code();
+  }
+
+  if (rootName && !rootDirectory) {
+    StringRef pRootName      = path::root_name(p);
+    StringRef bRootDirectory = path::root_directory(current_dir);
+    StringRef bRelativePath  = path::relative_path(current_dir);
+    StringRef pRelativePath  = path::relative_path(p);
+
+    SmallString<128> res;
+    path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
+    path.swap(res);
+    return std::error_code();
+  }
+
+  llvm_unreachable("All rootName and rootDirectory combinations should have "
+                   "occurred above!");
+}
+
+std::error_code make_absolute(const Twine &current_directory,
+                              SmallVectorImpl<char> &path) {
+  return make_absolute(current_directory, path, true);
+}
+
+std::error_code make_absolute(SmallVectorImpl<char> &path) {
+  return make_absolute(Twine(), path, false);
+}
+
+std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
+                                   perms Perms) {
+  SmallString<128> PathStorage;
+  StringRef P = Path.toStringRef(PathStorage);
+
+  // Be optimistic and try to create the directory
+  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
+  // If we succeeded, or had any error other than the parent not existing, just
+  // return it.
+  if (EC != errc::no_such_file_or_directory)
+    return EC;
+
+  // We failed because of a no_such_file_or_directory, try to create the
+  // parent.
+  StringRef Parent = path::parent_path(P);
+  if (Parent.empty())
+    return EC;
+
+  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
+      return EC;
+
+  return create_directory(P, IgnoreExisting, Perms);
+}
+
+std::error_code copy_file(const Twine &From, const Twine &To) {
+  int ReadFD, WriteFD;
+  if (std::error_code EC = openFileForRead(From, ReadFD))
+    return EC;
+  if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
+    close(ReadFD);
+    return EC;
+  }
+
+  const size_t BufSize = 4096;
+  char *Buf = new char[BufSize];
+  int BytesRead = 0, BytesWritten = 0;
+  for (;;) {
+    BytesRead = read(ReadFD, Buf, BufSize);
+    if (BytesRead <= 0)
+      break;
+    while (BytesRead) {
+      BytesWritten = write(WriteFD, Buf, BytesRead);
+      if (BytesWritten < 0)
+        break;
+      BytesRead -= BytesWritten;
+    }
+    if (BytesWritten < 0)
+      break;
+  }
+  close(ReadFD);
+  close(WriteFD);
+  delete[] Buf;
+
+  if (BytesRead < 0 || BytesWritten < 0)
+    return std::error_code(errno, std::generic_category());
+  return std::error_code();
+}
+
+bool exists(file_status status) {
+  return status_known(status) && status.type() != file_type::file_not_found;
+}
+
+bool status_known(file_status s) {
+  return s.type() != file_type::status_error;
+}
+
+bool is_directory(file_status status) {
+  return status.type() == file_type::directory_file;
+}
+
+std::error_code is_directory(const Twine &path, bool &result) {
+  file_status st;
+  if (std::error_code ec = status(path, st))
+    return ec;
+  result = is_directory(st);
+  return std::error_code();
+}
+
+bool is_regular_file(file_status status) {
+  return status.type() == file_type::regular_file;
+}
+
+std::error_code is_regular_file(const Twine &path, bool &result) {
+  file_status st;
+  if (std::error_code ec = status(path, st))
+    return ec;
+  result = is_regular_file(st);
+  return std::error_code();
+}
+
+bool is_other(file_status status) {
+  return exists(status) &&
+         !is_regular_file(status) &&
+         !is_directory(status);
+}
+
+std::error_code is_other(const Twine &Path, bool &Result) {
+  file_status FileStatus;
+  if (std::error_code EC = status(Path, FileStatus))
+    return EC;
+  Result = is_other(FileStatus);
+  return std::error_code();
+}
+
+void directory_entry::replace_filename(const Twine &filename, file_status st) {
+  SmallString<128> path = path::parent_path(Path);
+  path::append(path, filename);
+  Path = path.str();
+  Status = st;
+}
+
+/// @brief Identify the magic in magic.
+file_magic identify_magic(StringRef Magic) {
+  if (Magic.size() < 4)
+    return file_magic::unknown;
+  switch ((unsigned char)Magic[0]) {
+    case 0x00: {
+      // COFF bigobj or short import library file
+      if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff &&
+          Magic[3] == (char)0xff) {
+        size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic);
+        if (Magic.size() < MinSize)
+          return file_magic::coff_import_library;
+
+        int BigObjVersion = read16le(
+            Magic.data() + offsetof(COFF::BigObjHeader, Version));
+        if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion)
+          return file_magic::coff_import_library;
+
+        const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID);
+        if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0)
+          return file_magic::coff_import_library;
+        return file_magic::coff_object;
+      }
+      // Windows resource file
+      const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' };
+      if (Magic.size() >= sizeof(Expected) &&
+          memcmp(Magic.data(), Expected, sizeof(Expected)) == 0)
+        return file_magic::windows_resource;
+      // 0x0000 = COFF unknown machine type
+      if (Magic[1] == 0)
+        return file_magic::coff_object;
+      break;
+    }
+    case 0xDE:  // 0x0B17C0DE = BC wraper
+      if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 &&
+          Magic[3] == (char)0x0B)
+        return file_magic::bitcode;
+      break;
+    case 'B':
+      if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE)
+        return file_magic::bitcode;
+      break;
+    case '!':
+      if (Magic.size() >= 8)
+        if (memcmp(Magic.data(), "!<arch>\n", 8) == 0 ||
+            memcmp(Magic.data(), "!<thin>\n", 8) == 0)
+          return file_magic::archive;
+      break;
+
+    case '\177':
+      if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' &&
+          Magic[3] == 'F') {
+        bool Data2MSB = Magic[5] == 2;
+        unsigned high = Data2MSB ? 16 : 17;
+        unsigned low  = Data2MSB ? 17 : 16;
+        if (Magic[high] == 0)
+          switch (Magic[low]) {
+            default: return file_magic::elf;
+            case 1: return file_magic::elf_relocatable;
+            case 2: return file_magic::elf_executable;
+            case 3: return file_magic::elf_shared_object;
+            case 4: return file_magic::elf_core;
+          }
+        else
+          // It's still some type of ELF file.
+          return file_magic::elf;
+      }
+      break;
+
+    case 0xCA:
+      if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
+          (Magic[3] == char(0xBE) || Magic[3] == char(0xBF))) {
+        // This is complicated by an overlap with Java class files.
+        // See the Mach-O section in /usr/share/file/magic for details.
+        if (Magic.size() >= 8 && Magic[7] < 43)
+          return file_magic::macho_universal_binary;
+      }
+      break;
+
+      // The two magic numbers for mach-o are:
+      // 0xfeedface - 32-bit mach-o
+      // 0xfeedfacf - 64-bit mach-o
+    case 0xFE:
+    case 0xCE:
+    case 0xCF: {
+      uint16_t type = 0;
+      if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) &&
+          Magic[2] == char(0xFA) &&
+          (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) {
+        /* Native endian */
+        size_t MinSize;
+        if (Magic[3] == char(0xCE))
+          MinSize = sizeof(MachO::mach_header);
+        else
+          MinSize = sizeof(MachO::mach_header_64);
+        if (Magic.size() >= MinSize)
+          type = Magic[12] << 24 | Magic[13] << 12 | Magic[14] << 8 | Magic[15];
+      } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) &&
+                 Magic[1] == char(0xFA) && Magic[2] == char(0xED) &&
+                 Magic[3] == char(0xFE)) {
+        /* Reverse endian */
+        size_t MinSize;
+        if (Magic[0] == char(0xCE))
+          MinSize = sizeof(MachO::mach_header);
+        else
+          MinSize = sizeof(MachO::mach_header_64);
+        if (Magic.size() >= MinSize)
+          type = Magic[15] << 24 | Magic[14] << 12 |Magic[13] << 8 | Magic[12];
+      }
+      switch (type) {
+        default: break;
+        case 1: return file_magic::macho_object;
+        case 2: return file_magic::macho_executable;
+        case 3: return file_magic::macho_fixed_virtual_memory_shared_lib;
+        case 4: return file_magic::macho_core;
+        case 5: return file_magic::macho_preload_executable;
+        case 6: return file_magic::macho_dynamically_linked_shared_lib;
+        case 7: return file_magic::macho_dynamic_linker;
+        case 8: return file_magic::macho_bundle;
+        case 9: return file_magic::macho_dynamically_linked_shared_lib_stub;
+        case 10: return file_magic::macho_dsym_companion;
+        case 11: return file_magic::macho_kext_bundle;
+      }
+      break;
+    }
+    case 0xF0: // PowerPC Windows
+    case 0x83: // Alpha 32-bit
+    case 0x84: // Alpha 64-bit
+    case 0x66: // MPS R4000 Windows
+    case 0x50: // mc68K
+    case 0x4c: // 80386 Windows
+    case 0xc4: // ARMNT Windows
+      if (Magic[1] == 0x01)
+        return file_magic::coff_object;
+
+    case 0x90: // PA-RISC Windows
+    case 0x68: // mc68K Windows
+      if (Magic[1] == 0x02)
+        return file_magic::coff_object;
+      break;
+
+    case 'M': // Possible MS-DOS stub on Windows PE file
+      if (Magic[1] == 'Z') {
+        uint32_t off = read32le(Magic.data() + 0x3c);
+        // PE/COFF file, either EXE or DLL.
+        if (off < Magic.size() &&
+            memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0)
+          return file_magic::pecoff_executable;
+      }
+      break;
+
+    case 0x64: // x86-64 Windows.
+      if (Magic[1] == char(0x86))
+        return file_magic::coff_object;
+      break;
+
+    default:
+      break;
+  }
+  return file_magic::unknown;
+}
+
+std::error_code identify_magic(const Twine &Path, file_magic &Result) {
+  int FD;
+  if (std::error_code EC = openFileForRead(Path, FD))
+    return EC;
+
+  char Buffer[32];
+  int Length = read(FD, Buffer, sizeof(Buffer));
+  if (close(FD) != 0 || Length < 0)
+    return std::error_code(errno, std::generic_category());
+
+  Result = identify_magic(StringRef(Buffer, Length));
+  return std::error_code();
+}
+
+std::error_code directory_entry::status(file_status &result) const {
+  return fs::status(Path, result);
+}
+
+} // end namespace fs
+} // end namespace sys
+} // end namespace llvm
+
+// Include the truly platform-specific parts.
+#if defined(LLVM_ON_UNIX)
+#include "Unix/Path.inc"
+#endif
+#if defined(LLVM_ON_WIN32)
+#include "Windows/Path.inc"
+#endif
+
+namespace llvm {
+namespace sys {
+namespace path {
+
+bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
+                          const Twine &Path2, const Twine &Path3) {
+  if (getUserCacheDir(Result)) {
+    append(Result, Path1, Path2, Path3);
+    return true;
+  }
+  return false;
+}
+
+} // end namespace path
+} // end namsspace sys
+} // end namespace llvm
diff --git a/third_party/llvm-subzero/lib/Support/Process.cpp b/third_party/llvm-subzero/lib/Support/Process.cpp
new file mode 100644
index 0000000..290c30f
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Process.cpp
@@ -0,0 +1,89 @@
+//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the operating system Process concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
+
+using namespace llvm;
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//===          independent code.
+//===----------------------------------------------------------------------===//
+
+Optional<std::string> Process::FindInEnvPath(const std::string& EnvName,
+                                             const std::string& FileName)
+{
+  assert(!path::is_absolute(FileName));
+  Optional<std::string> FoundPath;
+  Optional<std::string> OptPath = Process::GetEnv(EnvName);
+  if (!OptPath.hasValue())
+    return FoundPath;
+
+  const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'};
+  SmallVector<StringRef, 8> Dirs;
+  SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr);
+
+  for (const auto &Dir : Dirs) {
+    if (Dir.empty())
+      continue;
+
+    SmallString<128> FilePath(Dir);
+    path::append(FilePath, FileName);
+    if (fs::exists(Twine(FilePath))) {
+      FoundPath = FilePath.str();
+      break;
+    }
+  }
+
+  return FoundPath;
+}
+
+
+#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
+
+#define ALLCOLORS(FGBG,BOLD) {\
+    COLOR(FGBG, "0", BOLD),\
+    COLOR(FGBG, "1", BOLD),\
+    COLOR(FGBG, "2", BOLD),\
+    COLOR(FGBG, "3", BOLD),\
+    COLOR(FGBG, "4", BOLD),\
+    COLOR(FGBG, "5", BOLD),\
+    COLOR(FGBG, "6", BOLD),\
+    COLOR(FGBG, "7", BOLD)\
+  }
+
+static const char colorcodes[2][2][8][10] = {
+ { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
+ { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
+};
+
+// This is set to true when Process::PreventCoreFiles() is called.
+static bool coreFilesPrevented = false;
+
+bool Process::AreCoreFilesPrevented() {
+  return coreFilesPrevented;
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Process.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Process.inc"
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/Program.cpp b/third_party/llvm-subzero/lib/Support/Program.cpp
new file mode 100644
index 0000000..34e336b
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Program.cpp
@@ -0,0 +1,69 @@
+//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the operating system Program concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Program.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include <system_error>
+using namespace llvm;
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//===          independent code.
+//===----------------------------------------------------------------------===//
+
+static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,
+                    const char **env, const StringRef **Redirects,
+                    unsigned memoryLimit, std::string *ErrMsg);
+
+int sys::ExecuteAndWait(StringRef Program, const char **args, const char **envp,
+                        const StringRef **redirects, unsigned secondsToWait,
+                        unsigned memoryLimit, std::string *ErrMsg,
+                        bool *ExecutionFailed) {
+  ProcessInfo PI;
+  if (Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg)) {
+    if (ExecutionFailed)
+      *ExecutionFailed = false;
+    ProcessInfo Result = Wait(
+        PI, secondsToWait, /*WaitUntilTerminates=*/secondsToWait == 0, ErrMsg);
+    return Result.ReturnCode;
+  }
+
+  if (ExecutionFailed)
+    *ExecutionFailed = true;
+
+  return -1;
+}
+
+ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **args,
+                               const char **envp, const StringRef **redirects,
+                               unsigned memoryLimit, std::string *ErrMsg,
+                               bool *ExecutionFailed) {
+  ProcessInfo PI;
+  if (ExecutionFailed)
+    *ExecutionFailed = false;
+  if (!Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg))
+    if (ExecutionFailed)
+      *ExecutionFailed = true;
+
+  return PI;
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Program.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Program.inc"
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/Signals.cpp b/third_party/llvm-subzero/lib/Support/Signals.cpp
new file mode 100644
index 0000000..e5e38f5
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Signals.cpp
@@ -0,0 +1,184 @@
+//===- Signals.cpp - Signal Handling support --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines some helpful functions for dealing with the possibility of
+// Unix signals occurring while your program is running.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//===          independent code.
+//===----------------------------------------------------------------------===//
+
+static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>>
+    CallBacksToRun;
+void sys::RunSignalHandlers() {
+  if (!CallBacksToRun.isConstructed())
+    return;
+  for (auto &I : *CallBacksToRun)
+    I.first(I.second);
+  CallBacksToRun->clear();
+}
+}
+
+using namespace llvm;
+
+static bool findModulesAndOffsets(void **StackTrace, int Depth,
+                                  const char **Modules, intptr_t *Offsets,
+                                  const char *MainExecutableName,
+                                  StringSaver &StrPool);
+
+/// Format a pointer value as hexadecimal. Zero pad it out so its always the
+/// same width.
+static FormattedNumber format_ptr(void *PC) {
+  // Each byte is two hex digits plus 2 for the 0x prefix.
+  unsigned PtrWidth = 2 + 2 * sizeof(void *);
+  return format_hex((uint64_t)PC, PtrWidth);
+}
+
+static bool printSymbolizedStackTrace(StringRef Argv0,
+                                      void **StackTrace, int Depth,
+                                      llvm::raw_ostream &OS)
+  LLVM_ATTRIBUTE_USED;
+
+/// Helper that launches llvm-symbolizer and symbolizes a backtrace.
+static bool printSymbolizedStackTrace(StringRef Argv0,
+                                      void **StackTrace, int Depth,
+                                      llvm::raw_ostream &OS) {
+  // Don't recursively invoke the llvm-symbolizer binary.
+  if (Argv0.find("llvm-symbolizer") != std::string::npos)
+    return false;
+
+  // FIXME: Subtract necessary number from StackTrace entries to turn return addresses
+  // into actual instruction addresses.
+  // Use llvm-symbolizer tool to symbolize the stack traces. First look for it
+  // alongside our binary, then in $PATH.
+  ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code();
+  if (!Argv0.empty()) {
+    StringRef Parent = llvm::sys::path::parent_path(Argv0);
+    if (!Parent.empty())
+      LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent);
+  }
+  if (!LLVMSymbolizerPathOrErr)
+    LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer");
+  if (!LLVMSymbolizerPathOrErr)
+    return false;
+  const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
+
+  // If we don't know argv0 or the address of main() at this point, try
+  // to guess it anyway (it's possible on some platforms).
+  std::string MainExecutableName =
+      Argv0.empty() ? sys::fs::getMainExecutable(nullptr, nullptr)
+                    : (std::string)Argv0;
+  BumpPtrAllocator Allocator;
+  StringSaver StrPool(Allocator);
+  std::vector<const char *> Modules(Depth, nullptr);
+  std::vector<intptr_t> Offsets(Depth, 0);
+  if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(),
+                             MainExecutableName.c_str(), StrPool))
+    return false;
+  int InputFD;
+  SmallString<32> InputFile, OutputFile;
+  sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile);
+  sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
+  FileRemover InputRemover(InputFile.c_str());
+  FileRemover OutputRemover(OutputFile.c_str());
+
+  {
+    raw_fd_ostream Input(InputFD, true);
+    for (int i = 0; i < Depth; i++) {
+      if (Modules[i])
+        Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
+    }
+  }
+
+  StringRef InputFileStr(InputFile);
+  StringRef OutputFileStr(OutputFile);
+  StringRef StderrFileStr;
+  const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr,
+                                  &StderrFileStr};
+  const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
+#ifdef LLVM_ON_WIN32
+                        // Pass --relative-address on Windows so that we don't
+                        // have to add ImageBase from PE file.
+                        // FIXME: Make this the default for llvm-symbolizer.
+                        "--relative-address",
+#endif
+                        "--demangle", nullptr};
+  int RunResult =
+      sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
+  if (RunResult != 0)
+    return false;
+
+  // This report format is based on the sanitizer stack trace printer.  See
+  // sanitizer_stacktrace_printer.cc in compiler-rt.
+  auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
+  if (!OutputBuf)
+    return false;
+  StringRef Output = OutputBuf.get()->getBuffer();
+  SmallVector<StringRef, 32> Lines;
+  Output.split(Lines, "\n");
+  auto CurLine = Lines.begin();
+  int frame_no = 0;
+  for (int i = 0; i < Depth; i++) {
+    if (!Modules[i]) {
+      OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '\n';
+      continue;
+    }
+    // Read pairs of lines (function name and file/line info) until we
+    // encounter empty line.
+    for (;;) {
+      if (CurLine == Lines.end())
+        return false;
+      StringRef FunctionName = *CurLine++;
+      if (FunctionName.empty())
+        break;
+      OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << ' ';
+      if (!FunctionName.startswith("??"))
+        OS << FunctionName << ' ';
+      if (CurLine == Lines.end())
+        return false;
+      StringRef FileLineInfo = *CurLine++;
+      if (!FileLineInfo.startswith("??"))
+        OS << FileLineInfo;
+      else
+        OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")";
+      OS << "\n";
+    }
+  }
+  return true;
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Signals.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Signals.inc"
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/SmallPtrSet.cpp b/third_party/llvm-subzero/lib/Support/SmallPtrSet.cpp
new file mode 100644
index 0000000..8fb12ba
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/SmallPtrSet.cpp
@@ -0,0 +1,296 @@
+//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SmallPtrSet class.  See SmallPtrSet.h for an
+// overview of the algorithm.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+
+using namespace llvm;
+
+void SmallPtrSetImplBase::shrink_and_clear() {
+  assert(!isSmall() && "Can't shrink a small set!");
+  free(CurArray);
+
+  // Reduce the number of buckets.
+  unsigned Size = size();
+  CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32;
+  NumNonEmpty = NumTombstones = 0;
+
+  // Install the new array.  Clear all the buckets to empty.
+  CurArray = (const void**)malloc(sizeof(void*) * CurArraySize);
+  assert(CurArray && "Failed to allocate memory?");
+  memset(CurArray, -1, CurArraySize*sizeof(void*));
+}
+
+std::pair<const void *const *, bool>
+SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
+  if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) {
+    // If more than 3/4 of the array is full, grow.
+    Grow(CurArraySize < 64 ? 128 : CurArraySize * 2);
+  } else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) {
+    // If fewer of 1/8 of the array is empty (meaning that many are filled with
+    // tombstones), rehash.
+    Grow(CurArraySize);
+  }
+
+  // Okay, we know we have space.  Find a hash bucket.
+  const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr));
+  if (*Bucket == Ptr)
+    return std::make_pair(Bucket, false); // Already inserted, good.
+
+  // Otherwise, insert it!
+  if (*Bucket == getTombstoneMarker())
+    --NumTombstones;
+  else
+    ++NumNonEmpty; // Track density.
+  *Bucket = Ptr;
+  return std::make_pair(Bucket, true);
+}
+
+bool SmallPtrSetImplBase::erase_imp(const void * Ptr) {
+  if (isSmall()) {
+    // Check to see if it is in the set.
+    for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty; APtr != E;
+         ++APtr)
+      if (*APtr == Ptr) {
+        // If it is in the set, replace this element.
+        *APtr = getTombstoneMarker();
+        ++NumTombstones;
+        return true;
+      }
+
+    return false;
+  }
+
+  // Okay, we know we have space.  Find a hash bucket.
+  void **Bucket = const_cast<void**>(FindBucketFor(Ptr));
+  if (*Bucket != Ptr) return false;  // Not in the set?
+
+  // Set this as a tombstone.
+  *Bucket = getTombstoneMarker();
+  ++NumTombstones;
+  return true;
+}
+
+const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
+  unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1);
+  unsigned ArraySize = CurArraySize;
+  unsigned ProbeAmt = 1;
+  const void *const *Array = CurArray;
+  const void *const *Tombstone = nullptr;
+  while (true) {
+    // If we found an empty bucket, the pointer doesn't exist in the set.
+    // Return a tombstone if we've seen one so far, or the empty bucket if
+    // not.
+    if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker()))
+      return Tombstone ? Tombstone : Array+Bucket;
+
+    // Found Ptr's bucket?
+    if (LLVM_LIKELY(Array[Bucket] == Ptr))
+      return Array+Bucket;
+
+    // If this is a tombstone, remember it.  If Ptr ends up not in the set, we
+    // prefer to return it than something that would require more probing.
+    if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
+      Tombstone = Array+Bucket;  // Remember the first tombstone found.
+
+    // It's a hash collision or a tombstone. Reprobe.
+    Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
+  }
+}
+
+/// Grow - Allocate a larger backing store for the buckets and move it over.
+///
+void SmallPtrSetImplBase::Grow(unsigned NewSize) {
+  const void **OldBuckets = CurArray;
+  const void **OldEnd = EndPointer();
+  bool WasSmall = isSmall();
+
+  // Install the new array.  Clear all the buckets to empty.
+  CurArray = (const void**)malloc(sizeof(void*) * NewSize);
+  assert(CurArray && "Failed to allocate memory?");
+  CurArraySize = NewSize;
+  memset(CurArray, -1, NewSize*sizeof(void*));
+
+  // Copy over all valid entries.
+  for (const void **BucketPtr = OldBuckets; BucketPtr != OldEnd; ++BucketPtr) {
+    // Copy over the element if it is valid.
+    const void *Elt = *BucketPtr;
+    if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
+      *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
+  }
+
+  if (!WasSmall)
+    free(OldBuckets);
+  NumNonEmpty -= NumTombstones;
+  NumTombstones = 0;
+}
+
+SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
+                                         const SmallPtrSetImplBase &that) {
+  SmallArray = SmallStorage;
+
+  // If we're becoming small, prepare to insert into our stack space
+  if (that.isSmall()) {
+    CurArray = SmallArray;
+  // Otherwise, allocate new heap space (unless we were the same size)
+  } else {
+    CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize);
+    assert(CurArray && "Failed to allocate memory?");
+  }
+
+  // Copy over the that array.
+  CopyHelper(that);
+}
+
+SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
+                                         unsigned SmallSize,
+                                         SmallPtrSetImplBase &&that) {
+  SmallArray = SmallStorage;
+  MoveHelper(SmallSize, std::move(that));
+}
+
+void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
+  assert(&RHS != this && "Self-copy should be handled by the caller.");
+
+  if (isSmall() && RHS.isSmall())
+    assert(CurArraySize == RHS.CurArraySize &&
+           "Cannot assign sets with different small sizes");
+
+  // If we're becoming small, prepare to insert into our stack space
+  if (RHS.isSmall()) {
+    if (!isSmall())
+      free(CurArray);
+    CurArray = SmallArray;
+  // Otherwise, allocate new heap space (unless we were the same size)
+  } else if (CurArraySize != RHS.CurArraySize) {
+    if (isSmall())
+      CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize);
+    else {
+      const void **T = (const void**)realloc(CurArray,
+                                             sizeof(void*) * RHS.CurArraySize);
+      if (!T)
+        free(CurArray);
+      CurArray = T;
+    }
+    assert(CurArray && "Failed to allocate memory?");
+  }
+
+  CopyHelper(RHS);
+}
+
+void SmallPtrSetImplBase::CopyHelper(const SmallPtrSetImplBase &RHS) {
+  // Copy over the new array size
+  CurArraySize = RHS.CurArraySize;
+
+  // Copy over the contents from the other set
+  std::copy(RHS.CurArray, RHS.EndPointer(), CurArray);
+
+  NumNonEmpty = RHS.NumNonEmpty;
+  NumTombstones = RHS.NumTombstones;
+}
+
+void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
+                                   SmallPtrSetImplBase &&RHS) {
+  if (!isSmall())
+    free(CurArray);
+  MoveHelper(SmallSize, std::move(RHS));
+}
+
+void SmallPtrSetImplBase::MoveHelper(unsigned SmallSize,
+                                     SmallPtrSetImplBase &&RHS) {
+  assert(&RHS != this && "Self-move should be handled by the caller.");
+
+  if (RHS.isSmall()) {
+    // Copy a small RHS rather than moving.
+    CurArray = SmallArray;
+    std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray);
+  } else {
+    CurArray = RHS.CurArray;
+    RHS.CurArray = RHS.SmallArray;
+  }
+
+  // Copy the rest of the trivial members.
+  CurArraySize = RHS.CurArraySize;
+  NumNonEmpty = RHS.NumNonEmpty;
+  NumTombstones = RHS.NumTombstones;
+
+  // Make the RHS small and empty.
+  RHS.CurArraySize = SmallSize;
+  assert(RHS.CurArray == RHS.SmallArray);
+  RHS.NumNonEmpty = 0;
+  RHS.NumTombstones = 0;
+}
+
+void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
+  if (this == &RHS) return;
+
+  // We can only avoid copying elements if neither set is small.
+  if (!this->isSmall() && !RHS.isSmall()) {
+    std::swap(this->CurArray, RHS.CurArray);
+    std::swap(this->CurArraySize, RHS.CurArraySize);
+    std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
+    std::swap(this->NumTombstones, RHS.NumTombstones);
+    return;
+  }
+
+  // FIXME: From here on we assume that both sets have the same small size.
+
+  // If only RHS is small, copy the small elements into LHS and move the pointer
+  // from LHS to RHS.
+  if (!this->isSmall() && RHS.isSmall()) {
+    assert(RHS.CurArray == RHS.SmallArray);
+    std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, this->SmallArray);
+    std::swap(RHS.CurArraySize, this->CurArraySize);
+    std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
+    std::swap(this->NumTombstones, RHS.NumTombstones);
+    RHS.CurArray = this->CurArray;
+    this->CurArray = this->SmallArray;
+    return;
+  }
+
+  // If only LHS is small, copy the small elements into RHS and move the pointer
+  // from RHS to LHS.
+  if (this->isSmall() && !RHS.isSmall()) {
+    assert(this->CurArray == this->SmallArray);
+    std::copy(this->CurArray, this->CurArray + this->NumNonEmpty,
+              RHS.SmallArray);
+    std::swap(RHS.CurArraySize, this->CurArraySize);
+    std::swap(RHS.NumNonEmpty, this->NumNonEmpty);
+    std::swap(RHS.NumTombstones, this->NumTombstones);
+    this->CurArray = RHS.CurArray;
+    RHS.CurArray = RHS.SmallArray;
+    return;
+  }
+
+  // Both a small, just swap the small elements.
+  assert(this->isSmall() && RHS.isSmall());
+  unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty);
+  std::swap_ranges(this->SmallArray, this->SmallArray + MinNonEmpty,
+                   RHS.SmallArray);
+  if (this->NumNonEmpty > MinNonEmpty) {
+    std::copy(this->SmallArray + MinNonEmpty,
+              this->SmallArray + this->NumNonEmpty,
+              RHS.SmallArray + MinNonEmpty);
+  } else {
+    std::copy(RHS.SmallArray + MinNonEmpty, RHS.SmallArray + RHS.NumNonEmpty,
+              this->SmallArray + MinNonEmpty);
+  }
+  assert(this->CurArraySize == RHS.CurArraySize);
+  std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
+  std::swap(this->NumTombstones, RHS.NumTombstones);
+}
diff --git a/third_party/llvm-subzero/lib/Support/SmallVector.cpp b/third_party/llvm-subzero/lib/Support/SmallVector.cpp
new file mode 100644
index 0000000..b931505
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/SmallVector.cpp
@@ -0,0 +1,41 @@
+//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SmallVector class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+using namespace llvm;
+
+/// grow_pod - This is an implementation of the grow() method which only works
+/// on POD-like datatypes and is out of line to reduce code duplication.
+void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSizeInBytes,
+                               size_t TSize) {
+  size_t CurSizeBytes = size_in_bytes();
+  size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow.
+  if (NewCapacityInBytes < MinSizeInBytes)
+    NewCapacityInBytes = MinSizeInBytes;
+
+  void *NewElts;
+  if (BeginX == FirstEl) {
+    NewElts = malloc(NewCapacityInBytes);
+
+    // Copy the elements over.  No need to run dtors on PODs.
+    memcpy(NewElts, this->BeginX, CurSizeBytes);
+  } else {
+    // If this wasn't grown from the inline copy, grow the allocated space.
+    NewElts = realloc(this->BeginX, NewCapacityInBytes);
+  }
+  assert(NewElts && "Out of memory");
+
+  this->EndX = (char*)NewElts+CurSizeBytes;
+  this->BeginX = NewElts;
+  this->CapacityX = (char*)this->BeginX + NewCapacityInBytes;
+}
diff --git a/third_party/llvm-subzero/lib/Support/StringExtras.cpp b/third_party/llvm-subzero/lib/Support/StringExtras.cpp
new file mode 100644
index 0000000..3e2420f
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/StringExtras.cpp
@@ -0,0 +1,58 @@
+//===-- StringExtras.cpp - Implement the StringExtras header --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the StringExtras.h header
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace llvm;
+
+/// StrInStrNoCase - Portable version of strcasestr.  Locates the first
+/// occurrence of string 's1' in string 's2', ignoring case.  Returns
+/// the offset of s2 in s1 or npos if s2 cannot be found.
+StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) {
+  size_t N = s2.size(), M = s1.size();
+  if (N > M)
+    return StringRef::npos;
+  for (size_t i = 0, e = M - N + 1; i != e; ++i)
+    if (s1.substr(i, N).equals_lower(s2))
+      return i;
+  return StringRef::npos;
+}
+
+/// getToken - This function extracts one token from source, ignoring any
+/// leading characters that appear in the Delimiters string, and ending the
+/// token at any of the characters that appear in the Delimiters string.  If
+/// there are no tokens in the source string, an empty string is returned.
+/// The function returns a pair containing the extracted token and the
+/// remaining tail string.
+std::pair<StringRef, StringRef> llvm::getToken(StringRef Source,
+                                               StringRef Delimiters) {
+  // Figure out where the token starts.
+  StringRef::size_type Start = Source.find_first_not_of(Delimiters);
+
+  // Find the next occurrence of the delimiter.
+  StringRef::size_type End = Source.find_first_of(Delimiters, Start);
+
+  return std::make_pair(Source.slice(Start, End), Source.substr(End));
+}
+
+/// SplitString - Split up the specified string according to the specified
+/// delimiters, appending the result fragments to the output list.
+void llvm::SplitString(StringRef Source,
+                       SmallVectorImpl<StringRef> &OutFragments,
+                       StringRef Delimiters) {
+  std::pair<StringRef, StringRef> S = getToken(Source, Delimiters);
+  while (!S.first.empty()) {
+    OutFragments.push_back(S.first);
+    S = getToken(S.second, Delimiters);
+  }
+}
diff --git a/third_party/llvm-subzero/lib/Support/StringMap.cpp b/third_party/llvm-subzero/lib/Support/StringMap.cpp
new file mode 100644
index 0000000..d231596
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/StringMap.cpp
@@ -0,0 +1,257 @@
+//===--- StringMap.cpp - String Hash table map implementation -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the StringMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+
+using namespace llvm;
+
+/// Returns the number of buckets to allocate to ensure that the DenseMap can
+/// accommodate \p NumEntries without need to grow().
+static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
+  // Ensure that "NumEntries * 4 < NumBuckets * 3"
+  if (NumEntries == 0)
+    return 0;
+  // +1 is required because of the strict equality.
+  // For example if NumEntries is 48, we need to return 401.
+  return NextPowerOf2(NumEntries * 4 / 3 + 1);
+}
+
+StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
+  ItemSize = itemSize;
+  
+  // If a size is specified, initialize the table with that many buckets.
+  if (InitSize) {
+    // The table will grow when the number of entries reach 3/4 of the number of
+    // buckets. To guarantee that "InitSize" number of entries can be inserted
+    // in the table without growing, we allocate just what is needed here.
+    init(getMinBucketToReserveForEntries(InitSize));
+    return;
+  }
+  
+  // Otherwise, initialize it with zero buckets to avoid the allocation.
+  TheTable = nullptr;
+  NumBuckets = 0;
+  NumItems = 0;
+  NumTombstones = 0;
+}
+
+void StringMapImpl::init(unsigned InitSize) {
+  assert((InitSize & (InitSize-1)) == 0 &&
+         "Init Size must be a power of 2 or zero!");
+  NumBuckets = InitSize ? InitSize : 16;
+  NumItems = 0;
+  NumTombstones = 0;
+  
+  TheTable = (StringMapEntryBase **)calloc(NumBuckets+1,
+                                           sizeof(StringMapEntryBase **) +
+                                           sizeof(unsigned));
+
+  // Allocate one extra bucket, set it to look filled so the iterators stop at
+  // end.
+  TheTable[NumBuckets] = (StringMapEntryBase*)2;
+}
+
+/// LookupBucketFor - Look up the bucket that the specified string should end
+/// up in.  If it already exists as a key in the map, the Item pointer for the
+/// specified bucket will be non-null.  Otherwise, it will be null.  In either
+/// case, the FullHashValue field of the bucket will be set to the hash value
+/// of the string.
+unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
+  unsigned HTSize = NumBuckets;
+  if (HTSize == 0) {  // Hash table unallocated so far?
+    init(16);
+    HTSize = NumBuckets;
+  }
+  unsigned FullHashValue = HashString(Name);
+  unsigned BucketNo = FullHashValue & (HTSize-1);
+  unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
+
+  unsigned ProbeAmt = 1;
+  int FirstTombstone = -1;
+  while (true) {
+    StringMapEntryBase *BucketItem = TheTable[BucketNo];
+    // If we found an empty bucket, this key isn't in the table yet, return it.
+    if (LLVM_LIKELY(!BucketItem)) {
+      // If we found a tombstone, we want to reuse the tombstone instead of an
+      // empty bucket.  This reduces probing.
+      if (FirstTombstone != -1) {
+        HashTable[FirstTombstone] = FullHashValue;
+        return FirstTombstone;
+      }
+      
+      HashTable[BucketNo] = FullHashValue;
+      return BucketNo;
+    }
+    
+    if (BucketItem == getTombstoneVal()) {
+      // Skip over tombstones.  However, remember the first one we see.
+      if (FirstTombstone == -1) FirstTombstone = BucketNo;
+    } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
+      // If the full hash value matches, check deeply for a match.  The common
+      // case here is that we are only looking at the buckets (for item info
+      // being non-null and for the full hash value) not at the items.  This
+      // is important for cache locality.
+      
+      // Do the comparison like this because Name isn't necessarily
+      // null-terminated!
+      char *ItemStr = (char*)BucketItem+ItemSize;
+      if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) {
+        // We found a match!
+        return BucketNo;
+      }
+    }
+    
+    // Okay, we didn't find the item.  Probe to the next bucket.
+    BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
+    
+    // Use quadratic probing, it has fewer clumping artifacts than linear
+    // probing and has good cache behavior in the common case.
+    ++ProbeAmt;
+  }
+}
+
+/// FindKey - Look up the bucket that contains the specified key. If it exists
+/// in the map, return the bucket number of the key.  Otherwise return -1.
+/// This does not modify the map.
+int StringMapImpl::FindKey(StringRef Key) const {
+  unsigned HTSize = NumBuckets;
+  if (HTSize == 0) return -1;  // Really empty table?
+  unsigned FullHashValue = HashString(Key);
+  unsigned BucketNo = FullHashValue & (HTSize-1);
+  unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
+
+  unsigned ProbeAmt = 1;
+  while (true) {
+    StringMapEntryBase *BucketItem = TheTable[BucketNo];
+    // If we found an empty bucket, this key isn't in the table yet, return.
+    if (LLVM_LIKELY(!BucketItem))
+      return -1;
+    
+    if (BucketItem == getTombstoneVal()) {
+      // Ignore tombstones.
+    } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
+      // If the full hash value matches, check deeply for a match.  The common
+      // case here is that we are only looking at the buckets (for item info
+      // being non-null and for the full hash value) not at the items.  This
+      // is important for cache locality.
+      
+      // Do the comparison like this because NameStart isn't necessarily
+      // null-terminated!
+      char *ItemStr = (char*)BucketItem+ItemSize;
+      if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) {
+        // We found a match!
+        return BucketNo;
+      }
+    }
+    
+    // Okay, we didn't find the item.  Probe to the next bucket.
+    BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
+    
+    // Use quadratic probing, it has fewer clumping artifacts than linear
+    // probing and has good cache behavior in the common case.
+    ++ProbeAmt;
+  }
+}
+
+/// RemoveKey - Remove the specified StringMapEntry from the table, but do not
+/// delete it.  This aborts if the value isn't in the table.
+void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
+  const char *VStr = (char*)V + ItemSize;
+  StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength()));
+  (void)V2;
+  assert(V == V2 && "Didn't find key?");
+}
+
+/// RemoveKey - Remove the StringMapEntry for the specified key from the
+/// table, returning it.  If the key is not in the table, this returns null.
+StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) {
+  int Bucket = FindKey(Key);
+  if (Bucket == -1) return nullptr;
+  
+  StringMapEntryBase *Result = TheTable[Bucket];
+  TheTable[Bucket] = getTombstoneVal();
+  --NumItems;
+  ++NumTombstones;
+  assert(NumItems + NumTombstones <= NumBuckets);
+
+  return Result;
+}
+
+/// RehashTable - Grow the table, redistributing values into the buckets with
+/// the appropriate mod-of-hashtable-size.
+unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
+  unsigned NewSize;
+  unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
+
+  // If the hash table is now more than 3/4 full, or if fewer than 1/8 of
+  // the buckets are empty (meaning that many are filled with tombstones),
+  // grow/rehash the table.
+  if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
+    NewSize = NumBuckets*2;
+  } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
+                           NumBuckets / 8)) {
+    NewSize = NumBuckets;
+  } else {
+    return BucketNo;
+  }
+
+  unsigned NewBucketNo = BucketNo;
+  // Allocate one extra bucket which will always be non-empty.  This allows the
+  // iterators to stop at end.
+  StringMapEntryBase **NewTableArray =
+    (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) +
+                                             sizeof(unsigned));
+  unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
+  NewTableArray[NewSize] = (StringMapEntryBase*)2;
+
+  // Rehash all the items into their new buckets.  Luckily :) we already have
+  // the hash values available, so we don't have to rehash any strings.
+  for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+    StringMapEntryBase *Bucket = TheTable[I];
+    if (Bucket && Bucket != getTombstoneVal()) {
+      // Fast case, bucket available.
+      unsigned FullHash = HashTable[I];
+      unsigned NewBucket = FullHash & (NewSize-1);
+      if (!NewTableArray[NewBucket]) {
+        NewTableArray[FullHash & (NewSize-1)] = Bucket;
+        NewHashArray[FullHash & (NewSize-1)] = FullHash;
+        if (I == BucketNo)
+          NewBucketNo = NewBucket;
+        continue;
+      }
+      
+      // Otherwise probe for a spot.
+      unsigned ProbeSize = 1;
+      do {
+        NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
+      } while (NewTableArray[NewBucket]);
+      
+      // Finally found a slot.  Fill it in.
+      NewTableArray[NewBucket] = Bucket;
+      NewHashArray[NewBucket] = FullHash;
+      if (I == BucketNo)
+        NewBucketNo = NewBucket;
+    }
+  }
+  
+  free(TheTable);
+  
+  TheTable = NewTableArray;
+  NumBuckets = NewSize;
+  NumTombstones = 0;
+  return NewBucketNo;
+}
diff --git a/third_party/llvm-subzero/lib/Support/StringRef.cpp b/third_party/llvm-subzero/lib/Support/StringRef.cpp
new file mode 100644
index 0000000..8a9da5e
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/StringRef.cpp
@@ -0,0 +1,524 @@
+//===-- StringRef.cpp - Lightweight String References ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/edit_distance.h"
+#include <bitset>
+
+using namespace llvm;
+
+// MSVC emits references to this into the translation units which reference it.
+#ifndef _MSC_VER
+const size_t StringRef::npos;
+#endif
+
+static char ascii_tolower(char x) {
+  if (x >= 'A' && x <= 'Z')
+    return x - 'A' + 'a';
+  return x;
+}
+
+static char ascii_toupper(char x) {
+  if (x >= 'a' && x <= 'z')
+    return x - 'a' + 'A';
+  return x;
+}
+
+static bool ascii_isdigit(char x) {
+  return x >= '0' && x <= '9';
+}
+
+// strncasecmp() is not available on non-POSIX systems, so define an
+// alternative function here.
+static int ascii_strncasecmp(const char *LHS, const char *RHS, size_t Length) {
+  for (size_t I = 0; I < Length; ++I) {
+    unsigned char LHC = ascii_tolower(LHS[I]);
+    unsigned char RHC = ascii_tolower(RHS[I]);
+    if (LHC != RHC)
+      return LHC < RHC ? -1 : 1;
+  }
+  return 0;
+}
+
+/// compare_lower - Compare strings, ignoring case.
+int StringRef::compare_lower(StringRef RHS) const {
+  if (int Res = ascii_strncasecmp(Data, RHS.Data, std::min(Length, RHS.Length)))
+    return Res;
+  if (Length == RHS.Length)
+    return 0;
+  return Length < RHS.Length ? -1 : 1;
+}
+
+/// Check if this string starts with the given \p Prefix, ignoring case.
+bool StringRef::startswith_lower(StringRef Prefix) const {
+  return Length >= Prefix.Length &&
+      ascii_strncasecmp(Data, Prefix.Data, Prefix.Length) == 0;
+}
+
+/// Check if this string ends with the given \p Suffix, ignoring case.
+bool StringRef::endswith_lower(StringRef Suffix) const {
+  return Length >= Suffix.Length &&
+      ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
+}
+
+/// compare_numeric - Compare strings, handle embedded numbers.
+int StringRef::compare_numeric(StringRef RHS) const {
+  for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) {
+    // Check for sequences of digits.
+    if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) {
+      // The longer sequence of numbers is considered larger.
+      // This doesn't really handle prefixed zeros well.
+      size_t J;
+      for (J = I + 1; J != E + 1; ++J) {
+        bool ld = J < Length && ascii_isdigit(Data[J]);
+        bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]);
+        if (ld != rd)
+          return rd ? -1 : 1;
+        if (!rd)
+          break;
+      }
+      // The two number sequences have the same length (J-I), just memcmp them.
+      if (int Res = compareMemory(Data + I, RHS.Data + I, J - I))
+        return Res < 0 ? -1 : 1;
+      // Identical number sequences, continue search after the numbers.
+      I = J - 1;
+      continue;
+    }
+    if (Data[I] != RHS.Data[I])
+      return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1;
+  }
+  if (Length == RHS.Length)
+    return 0;
+  return Length < RHS.Length ? -1 : 1;
+}
+
+// Compute the edit distance between the two given strings.
+unsigned StringRef::edit_distance(llvm::StringRef Other,
+                                  bool AllowReplacements,
+                                  unsigned MaxEditDistance) const {
+  return llvm::ComputeEditDistance(
+      makeArrayRef(data(), size()),
+      makeArrayRef(Other.data(), Other.size()),
+      AllowReplacements, MaxEditDistance);
+}
+
+//===----------------------------------------------------------------------===//
+// String Operations
+//===----------------------------------------------------------------------===//
+
+std::string StringRef::lower() const {
+  std::string Result(size(), char());
+  for (size_type i = 0, e = size(); i != e; ++i) {
+    Result[i] = ascii_tolower(Data[i]);
+  }
+  return Result;
+}
+
+std::string StringRef::upper() const {
+  std::string Result(size(), char());
+  for (size_type i = 0, e = size(); i != e; ++i) {
+    Result[i] = ascii_toupper(Data[i]);
+  }
+  return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// String Searching
+//===----------------------------------------------------------------------===//
+
+
+/// find - Search for the first string \arg Str in the string.
+///
+/// \return - The index of the first occurrence of \arg Str, or npos if not
+/// found.
+size_t StringRef::find(StringRef Str, size_t From) const {
+  if (From > Length)
+    return npos;
+
+  const char *Needle = Str.data();
+  size_t N = Str.size();
+  if (N == 0)
+    return From;
+
+  size_t Size = Length - From;
+  if (Size < N)
+    return npos;
+
+  const char *Start = Data + From;
+  const char *Stop = Start + (Size - N + 1);
+
+  // For short haystacks or unsupported needles fall back to the naive algorithm
+  if (Size < 16 || N > 255) {
+    do {
+      if (std::memcmp(Start, Needle, N) == 0)
+        return Start - Data;
+      ++Start;
+    } while (Start < Stop);
+    return npos;
+  }
+
+  // Build the bad char heuristic table, with uint8_t to reduce cache thrashing.
+  uint8_t BadCharSkip[256];
+  std::memset(BadCharSkip, N, 256);
+  for (unsigned i = 0; i != N-1; ++i)
+    BadCharSkip[(uint8_t)Str[i]] = N-1-i;
+
+  do {
+    if (std::memcmp(Start, Needle, N) == 0)
+      return Start - Data;
+
+    // Otherwise skip the appropriate number of bytes.
+    Start += BadCharSkip[(uint8_t)Start[N-1]];
+  } while (Start < Stop);
+
+  return npos;
+}
+
+/// rfind - Search for the last string \arg Str in the string.
+///
+/// \return - The index of the last occurrence of \arg Str, or npos if not
+/// found.
+size_t StringRef::rfind(StringRef Str) const {
+  size_t N = Str.size();
+  if (N > Length)
+    return npos;
+  for (size_t i = Length - N + 1, e = 0; i != e;) {
+    --i;
+    if (substr(i, N).equals(Str))
+      return i;
+  }
+  return npos;
+}
+
+/// find_first_of - Find the first character in the string that is in \arg
+/// Chars, or npos if not found.
+///
+/// Note: O(size() + Chars.size())
+StringRef::size_type StringRef::find_first_of(StringRef Chars,
+                                              size_t From) const {
+  std::bitset<1 << CHAR_BIT> CharBits;
+  for (size_type i = 0; i != Chars.size(); ++i)
+    CharBits.set((unsigned char)Chars[i]);
+
+  for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
+    if (CharBits.test((unsigned char)Data[i]))
+      return i;
+  return npos;
+}
+
+/// find_first_not_of - Find the first character in the string that is not
+/// \arg C or npos if not found.
+StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const {
+  for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
+    if (Data[i] != C)
+      return i;
+  return npos;
+}
+
+/// find_first_not_of - Find the first character in the string that is not
+/// in the string \arg Chars, or npos if not found.
+///
+/// Note: O(size() + Chars.size())
+StringRef::size_type StringRef::find_first_not_of(StringRef Chars,
+                                                  size_t From) const {
+  std::bitset<1 << CHAR_BIT> CharBits;
+  for (size_type i = 0; i != Chars.size(); ++i)
+    CharBits.set((unsigned char)Chars[i]);
+
+  for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
+    if (!CharBits.test((unsigned char)Data[i]))
+      return i;
+  return npos;
+}
+
+/// find_last_of - Find the last character in the string that is in \arg C,
+/// or npos if not found.
+///
+/// Note: O(size() + Chars.size())
+StringRef::size_type StringRef::find_last_of(StringRef Chars,
+                                             size_t From) const {
+  std::bitset<1 << CHAR_BIT> CharBits;
+  for (size_type i = 0; i != Chars.size(); ++i)
+    CharBits.set((unsigned char)Chars[i]);
+
+  for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)
+    if (CharBits.test((unsigned char)Data[i]))
+      return i;
+  return npos;
+}
+
+/// find_last_not_of - Find the last character in the string that is not
+/// \arg C, or npos if not found.
+StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const {
+  for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)
+    if (Data[i] != C)
+      return i;
+  return npos;
+}
+
+/// find_last_not_of - Find the last character in the string that is not in
+/// \arg Chars, or npos if not found.
+///
+/// Note: O(size() + Chars.size())
+StringRef::size_type StringRef::find_last_not_of(StringRef Chars,
+                                                 size_t From) const {
+  std::bitset<1 << CHAR_BIT> CharBits;
+  for (size_type i = 0, e = Chars.size(); i != e; ++i)
+    CharBits.set((unsigned char)Chars[i]);
+
+  for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)
+    if (!CharBits.test((unsigned char)Data[i]))
+      return i;
+  return npos;
+}
+
+void StringRef::split(SmallVectorImpl<StringRef> &A,
+                      StringRef Separator, int MaxSplit,
+                      bool KeepEmpty) const {
+  StringRef S = *this;
+
+  // Count down from MaxSplit. When MaxSplit is -1, this will just split
+  // "forever". This doesn't support splitting more than 2^31 times
+  // intentionally; if we ever want that we can make MaxSplit a 64-bit integer
+  // but that seems unlikely to be useful.
+  while (MaxSplit-- != 0) {
+    size_t Idx = S.find(Separator);
+    if (Idx == npos)
+      break;
+
+    // Push this split.
+    if (KeepEmpty || Idx > 0)
+      A.push_back(S.slice(0, Idx));
+
+    // Jump forward.
+    S = S.slice(Idx + Separator.size(), npos);
+  }
+
+  // Push the tail.
+  if (KeepEmpty || !S.empty())
+    A.push_back(S);
+}
+
+void StringRef::split(SmallVectorImpl<StringRef> &A, char Separator,
+                      int MaxSplit, bool KeepEmpty) const {
+  StringRef S = *this;
+
+  // Count down from MaxSplit. When MaxSplit is -1, this will just split
+  // "forever". This doesn't support splitting more than 2^31 times
+  // intentionally; if we ever want that we can make MaxSplit a 64-bit integer
+  // but that seems unlikely to be useful.
+  while (MaxSplit-- != 0) {
+    size_t Idx = S.find(Separator);
+    if (Idx == npos)
+      break;
+
+    // Push this split.
+    if (KeepEmpty || Idx > 0)
+      A.push_back(S.slice(0, Idx));
+
+    // Jump forward.
+    S = S.slice(Idx + 1, npos);
+  }
+
+  // Push the tail.
+  if (KeepEmpty || !S.empty())
+    A.push_back(S);
+}
+
+//===----------------------------------------------------------------------===//
+// Helpful Algorithms
+//===----------------------------------------------------------------------===//
+
+/// count - Return the number of non-overlapped occurrences of \arg Str in
+/// the string.
+size_t StringRef::count(StringRef Str) const {
+  size_t Count = 0;
+  size_t N = Str.size();
+  if (N > Length)
+    return 0;
+  for (size_t i = 0, e = Length - N + 1; i != e; ++i)
+    if (substr(i, N).equals(Str))
+      ++Count;
+  return Count;
+}
+
+static unsigned GetAutoSenseRadix(StringRef &Str) {
+  if (Str.startswith("0x") || Str.startswith("0X")) {
+    Str = Str.substr(2);
+    return 16;
+  }
+  
+  if (Str.startswith("0b") || Str.startswith("0B")) {
+    Str = Str.substr(2);
+    return 2;
+  }
+
+  if (Str.startswith("0o")) {
+    Str = Str.substr(2);
+    return 8;
+  }
+
+  if (Str.startswith("0"))
+    return 8;
+  
+  return 10;
+}
+
+
+/// GetAsUnsignedInteger - Workhorse method that converts a integer character
+/// sequence of radix up to 36 to an unsigned long long value.
+bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix,
+                                unsigned long long &Result) {
+  // Autosense radix if not specified.
+  if (Radix == 0)
+    Radix = GetAutoSenseRadix(Str);
+
+  // Empty strings (after the radix autosense) are invalid.
+  if (Str.empty()) return true;
+
+  // Parse all the bytes of the string given this radix.  Watch for overflow.
+  Result = 0;
+  while (!Str.empty()) {
+    unsigned CharVal;
+    if (Str[0] >= '0' && Str[0] <= '9')
+      CharVal = Str[0]-'0';
+    else if (Str[0] >= 'a' && Str[0] <= 'z')
+      CharVal = Str[0]-'a'+10;
+    else if (Str[0] >= 'A' && Str[0] <= 'Z')
+      CharVal = Str[0]-'A'+10;
+    else
+      return true;
+
+    // If the parsed value is larger than the integer radix, the string is
+    // invalid.
+    if (CharVal >= Radix)
+      return true;
+
+    // Add in this character.
+    unsigned long long PrevResult = Result;
+    Result = Result*Radix+CharVal;
+
+    // Check for overflow by shifting back and seeing if bits were lost.
+    if (Result/Radix < PrevResult)
+      return true;
+
+    Str = Str.substr(1);
+  }
+
+  return false;
+}
+
+bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix,
+                              long long &Result) {
+  unsigned long long ULLVal;
+
+  // Handle positive strings first.
+  if (Str.empty() || Str.front() != '-') {
+    if (getAsUnsignedInteger(Str, Radix, ULLVal) ||
+        // Check for value so large it overflows a signed value.
+        (long long)ULLVal < 0)
+      return true;
+    Result = ULLVal;
+    return false;
+  }
+
+  // Get the positive part of the value.
+  if (getAsUnsignedInteger(Str.substr(1), Radix, ULLVal) ||
+      // Reject values so large they'd overflow as negative signed, but allow
+      // "-0".  This negates the unsigned so that the negative isn't undefined
+      // on signed overflow.
+      (long long)-ULLVal > 0)
+    return true;
+
+  Result = -ULLVal;
+  return false;
+}
+
+bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
+  StringRef Str = *this;
+
+  // Autosense radix if not specified.
+  if (Radix == 0)
+    Radix = GetAutoSenseRadix(Str);
+
+  assert(Radix > 1 && Radix <= 36);
+
+  // Empty strings (after the radix autosense) are invalid.
+  if (Str.empty()) return true;
+
+  // Skip leading zeroes.  This can be a significant improvement if
+  // it means we don't need > 64 bits.
+  while (!Str.empty() && Str.front() == '0')
+    Str = Str.substr(1);
+
+  // If it was nothing but zeroes....
+  if (Str.empty()) {
+    Result = APInt(64, 0);
+    return false;
+  }
+
+  // (Over-)estimate the required number of bits.
+  unsigned Log2Radix = 0;
+  while ((1U << Log2Radix) < Radix) Log2Radix++;
+  bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix);
+
+  unsigned BitWidth = Log2Radix * Str.size();
+  if (BitWidth < Result.getBitWidth())
+    BitWidth = Result.getBitWidth(); // don't shrink the result
+  else if (BitWidth > Result.getBitWidth())
+    Result = Result.zext(BitWidth);
+
+  APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix
+  if (!IsPowerOf2Radix) {
+    // These must have the same bit-width as Result.
+    RadixAP = APInt(BitWidth, Radix);
+    CharAP = APInt(BitWidth, 0);
+  }
+
+  // Parse all the bytes of the string given this radix.
+  Result = 0;
+  while (!Str.empty()) {
+    unsigned CharVal;
+    if (Str[0] >= '0' && Str[0] <= '9')
+      CharVal = Str[0]-'0';
+    else if (Str[0] >= 'a' && Str[0] <= 'z')
+      CharVal = Str[0]-'a'+10;
+    else if (Str[0] >= 'A' && Str[0] <= 'Z')
+      CharVal = Str[0]-'A'+10;
+    else
+      return true;
+
+    // If the parsed value is larger than the integer radix, the string is
+    // invalid.
+    if (CharVal >= Radix)
+      return true;
+
+    // Add in this character.
+    if (IsPowerOf2Radix) {
+      Result <<= Log2Radix;
+      Result |= CharVal;
+    } else {
+      Result *= RadixAP;
+      CharAP = CharVal;
+      Result += CharAP;
+    }
+
+    Str = Str.substr(1);
+  }
+
+  return false;
+}
+
+
+// Implementation of StringRef hashing.
+hash_code llvm::hash_value(StringRef S) {
+  return hash_combine_range(S.begin(), S.end());
+}
diff --git a/third_party/llvm-subzero/lib/Support/StringSaver.cpp b/third_party/llvm-subzero/lib/Support/StringSaver.cpp
new file mode 100644
index 0000000..bbc1fd2
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/StringSaver.cpp
@@ -0,0 +1,19 @@
+//===-- StringSaver.cpp ---------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/StringSaver.h"
+
+using namespace llvm;
+
+const char *StringSaver::save(StringRef S) {
+  char *P = Alloc.Allocate<char>(S.size() + 1);
+  memcpy(P, S.data(), S.size());
+  P[S.size()] = '\0';
+  return P;
+}
diff --git a/third_party/llvm-subzero/lib/Support/TargetParser.cpp b/third_party/llvm-subzero/lib/Support/TargetParser.cpp
new file mode 100644
index 0000000..8b00b34
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/TargetParser.cpp
@@ -0,0 +1,834 @@
+//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise hardware features such as
+// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include <cctype>
+
+using namespace llvm;
+using namespace ARM;
+using namespace AArch64;
+
+namespace {
+
+// List of canonical FPU names (use getFPUSynonym) and which architectural
+// features they correspond to (use getFPUFeatures).
+// FIXME: TableGen this.
+// The entries must appear in the order listed in ARM::FPUKind for correct indexing
+static const struct {
+  const char *NameCStr;
+  size_t NameLength;
+  ARM::FPUKind ID;
+  ARM::FPUVersion FPUVersion;
+  ARM::NeonSupportLevel NeonSupport;
+  ARM::FPURestriction Restriction;
+
+  StringRef getName() const { return StringRef(NameCStr, NameLength); }
+} FPUNames[] = {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
+  { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
+#include "llvm/Support/ARMTargetParser.def"
+};
+
+// List of canonical arch names (use getArchSynonym).
+// This table also provides the build attribute fields for CPU arch
+// and Arch ID, according to the Addenda to the ARM ABI, chapters
+// 2.4 and 2.3.5.2 respectively.
+// FIXME: SubArch values were simplified to fit into the expectations
+// of the triples and are not conforming with their official names.
+// Check to see if the expectation should be changed.
+// FIXME: TableGen this.
+template <typename T> struct ArchNames {
+  const char *NameCStr;
+  size_t NameLength;
+  const char *CPUAttrCStr;
+  size_t CPUAttrLength;
+  const char *SubArchCStr;
+  size_t SubArchLength;
+  unsigned DefaultFPU;
+  unsigned ArchBaseExtensions;
+  T ID;
+  ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
+
+  StringRef getName() const { return StringRef(NameCStr, NameLength); }
+
+  // CPU class in build attributes.
+  StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
+
+  // Sub-Arch name.
+  StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
+};
+ArchNames<ARM::ArchKind> ARCHNames[] = {
+#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
+  {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
+   sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR},
+#include "llvm/Support/ARMTargetParser.def"
+};
+
+ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = {
+ #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \
+   {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH,       \
+    sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
+ #include "llvm/Support/AArch64TargetParser.def"
+ };
+
+
+// List of Arch Extension names.
+// FIXME: TableGen this.
+static const struct {
+  const char *NameCStr;
+  size_t NameLength;
+  unsigned ID;
+  const char *Feature;
+  const char *NegFeature;
+
+  StringRef getName() const { return StringRef(NameCStr, NameLength); }
+} ARCHExtNames[] = {
+#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
+  { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
+#include "llvm/Support/ARMTargetParser.def"
+},AArch64ARCHExtNames[] = {
+#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
+  { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
+#include "llvm/Support/AArch64TargetParser.def"
+};
+
+// List of HWDiv names (use getHWDivSynonym) and which architectural
+// features they correspond to (use getHWDivFeatures).
+// FIXME: TableGen this.
+static const struct {
+  const char *NameCStr;
+  size_t NameLength;
+  unsigned ID;
+
+  StringRef getName() const { return StringRef(NameCStr, NameLength); }
+} HWDivNames[] = {
+#define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
+#include "llvm/Support/ARMTargetParser.def"
+};
+
+// List of CPU names and their arches.
+// The same CPU can have multiple arches and can be default on multiple arches.
+// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
+// When this becomes table-generated, we'd probably need two tables.
+// FIXME: TableGen this.
+template <typename T> struct CpuNames {
+  const char *NameCStr;
+  size_t NameLength;
+  T ArchID;
+  bool Default; // is $Name the default CPU for $ArchID ?
+  unsigned DefaultExtensions;
+
+  StringRef getName() const { return StringRef(NameCStr, NameLength); }
+};
+CpuNames<ARM::ArchKind> CPUNames[] = {
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+  { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
+#include "llvm/Support/ARMTargetParser.def"
+};
+
+CpuNames<AArch64::ArchKind> AArch64CPUNames[] = {
+ #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+   { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
+ #include "llvm/Support/AArch64TargetParser.def"
+ };
+
+} // namespace
+
+// ======================================================= //
+// Information by ID
+// ======================================================= //
+
+StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
+  if (FPUKind >= ARM::FK_LAST)
+    return StringRef();
+  return FPUNames[FPUKind].getName();
+}
+
+unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
+  if (FPUKind >= ARM::FK_LAST)
+    return 0;
+  return FPUNames[FPUKind].FPUVersion;
+}
+
+unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
+  if (FPUKind >= ARM::FK_LAST)
+    return 0;
+  return FPUNames[FPUKind].NeonSupport;
+}
+
+unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
+  if (FPUKind >= ARM::FK_LAST)
+    return 0;
+  return FPUNames[FPUKind].Restriction;
+}
+
+unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
+  if (CPU == "generic")
+    return ARCHNames[ArchKind].DefaultFPU;
+
+  return StringSwitch<unsigned>(CPU)
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+    .Case(NAME, DEFAULT_FPU)
+#include "llvm/Support/ARMTargetParser.def"
+    .Default(ARM::FK_INVALID);
+}
+
+unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
+  if (CPU == "generic")
+    return ARCHNames[ArchKind].ArchBaseExtensions;
+
+  return StringSwitch<unsigned>(CPU)
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+    .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
+#include "llvm/Support/ARMTargetParser.def"
+    .Default(ARM::AEK_INVALID);
+}
+
+bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
+                                 std::vector<const char *> &Features) {
+
+  if (HWDivKind == ARM::AEK_INVALID)
+    return false;
+
+  if (HWDivKind & ARM::AEK_HWDIVARM)
+    Features.push_back("+hwdiv-arm");
+  else
+    Features.push_back("-hwdiv-arm");
+
+  if (HWDivKind & ARM::AEK_HWDIV)
+    Features.push_back("+hwdiv");
+  else
+    Features.push_back("-hwdiv");
+
+  return true;
+}
+
+bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
+                                     std::vector<const char *> &Features) {
+
+  if (Extensions == ARM::AEK_INVALID)
+    return false;
+
+  if (Extensions & ARM::AEK_CRC)
+    Features.push_back("+crc");
+  else
+    Features.push_back("-crc");
+
+  if (Extensions & ARM::AEK_DSP)
+    Features.push_back("+dsp");
+  else
+    Features.push_back("-dsp");
+
+  return getHWDivFeatures(Extensions, Features);
+}
+
+bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
+                               std::vector<const char *> &Features) {
+
+  if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
+    return false;
+
+  // fp-only-sp and d16 subtarget features are independent of each other, so we
+  // must enable/disable both.
+  switch (FPUNames[FPUKind].Restriction) {
+  case ARM::FR_SP_D16:
+    Features.push_back("+fp-only-sp");
+    Features.push_back("+d16");
+    break;
+  case ARM::FR_D16:
+    Features.push_back("-fp-only-sp");
+    Features.push_back("+d16");
+    break;
+  case ARM::FR_None:
+    Features.push_back("-fp-only-sp");
+    Features.push_back("-d16");
+    break;
+  }
+
+  // FPU version subtarget features are inclusive of lower-numbered ones, so
+  // enable the one corresponding to this version and disable all that are
+  // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
+  // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
+  switch (FPUNames[FPUKind].FPUVersion) {
+  case ARM::FV_VFPV5:
+    Features.push_back("+fp-armv8");
+    break;
+  case ARM::FV_VFPV4:
+    Features.push_back("+vfp4");
+    Features.push_back("-fp-armv8");
+    break;
+  case ARM::FV_VFPV3_FP16:
+    Features.push_back("+vfp3");
+    Features.push_back("+fp16");
+    Features.push_back("-vfp4");
+    Features.push_back("-fp-armv8");
+    break;
+  case ARM::FV_VFPV3:
+    Features.push_back("+vfp3");
+    Features.push_back("-fp16");
+    Features.push_back("-vfp4");
+    Features.push_back("-fp-armv8");
+    break;
+  case ARM::FV_VFPV2:
+    Features.push_back("+vfp2");
+    Features.push_back("-vfp3");
+    Features.push_back("-fp16");
+    Features.push_back("-vfp4");
+    Features.push_back("-fp-armv8");
+    break;
+  case ARM::FV_NONE:
+    Features.push_back("-vfp2");
+    Features.push_back("-vfp3");
+    Features.push_back("-fp16");
+    Features.push_back("-vfp4");
+    Features.push_back("-fp-armv8");
+    break;
+  }
+
+  // crypto includes neon, so we handle this similarly to FPU version.
+  switch (FPUNames[FPUKind].NeonSupport) {
+  case ARM::NS_Crypto:
+    Features.push_back("+neon");
+    Features.push_back("+crypto");
+    break;
+  case ARM::NS_Neon:
+    Features.push_back("+neon");
+    Features.push_back("-crypto");
+    break;
+  case ARM::NS_None:
+    Features.push_back("-neon");
+    Features.push_back("-crypto");
+    break;
+  }
+
+  return true;
+}
+
+StringRef llvm::ARM::getArchName(unsigned ArchKind) {
+  if (ArchKind >= ARM::AK_LAST)
+    return StringRef();
+  return ARCHNames[ArchKind].getName();
+}
+
+StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
+  if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
+    return StringRef();
+  return ARCHNames[ArchKind].getCPUAttr();
+}
+
+StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
+  if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST)
+    return StringRef();
+  return ARCHNames[ArchKind].getSubArch();
+}
+
+unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
+  if (ArchKind >= ARM::AK_LAST)
+    return ARMBuildAttrs::CPUArch::Pre_v4;
+  return ARCHNames[ArchKind].ArchAttr;
+}
+
+StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
+  for (const auto AE : ARCHExtNames) {
+    if (ArchExtKind == AE.ID)
+      return AE.getName();
+  }
+  return StringRef();
+}
+
+const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
+  if (ArchExt.startswith("no")) {
+    StringRef ArchExtBase(ArchExt.substr(2));
+    for (const auto AE : ARCHExtNames) {
+      if (AE.NegFeature && ArchExtBase == AE.getName())
+        return AE.NegFeature;
+    }
+  }
+  for (const auto AE : ARCHExtNames) {
+    if (AE.Feature && ArchExt == AE.getName())
+      return AE.Feature;
+  }
+
+  return nullptr;
+}
+
+StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
+  for (const auto D : HWDivNames) {
+    if (HWDivKind == D.ID)
+      return D.getName();
+  }
+  return StringRef();
+}
+
+StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
+  unsigned AK = parseArch(Arch);
+  if (AK == ARM::AK_INVALID)
+    return StringRef();
+
+  // Look for multiple AKs to find the default for pair AK+Name.
+  for (const auto CPU : CPUNames) {
+    if (CPU.ArchID == AK && CPU.Default)
+      return CPU.getName();
+  }
+
+  // If we can't find a default then target the architecture instead
+  return "generic";
+}
+
+StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
+  return ARM::getFPUName(FPUKind);
+}
+
+unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) {
+  return ARM::getFPUVersion(FPUKind);
+}
+
+unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
+  return ARM::getFPUNeonSupportLevel( FPUKind);
+}
+
+unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) {
+  return ARM::getFPURestriction(FPUKind);
+}
+
+unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
+  if (CPU == "generic")
+    return AArch64ARCHNames[ArchKind].DefaultFPU;
+
+  return StringSwitch<unsigned>(CPU)
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+    .Case(NAME, DEFAULT_FPU)
+#include "llvm/Support/AArch64TargetParser.def"
+    .Default(ARM::FK_INVALID);
+}
+
+unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
+  if (CPU == "generic")
+    return AArch64ARCHNames[ArchKind].ArchBaseExtensions;
+
+  return StringSwitch<unsigned>(CPU)
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+    .Case(NAME, DEFAULT_EXT)
+#include "llvm/Support/AArch64TargetParser.def"
+    .Default(AArch64::AEK_INVALID);
+}
+
+bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
+                                     std::vector<const char *> &Features) {
+
+  if (Extensions == AArch64::AEK_INVALID)
+    return false;
+
+  if (Extensions & AArch64::AEK_FP)
+    Features.push_back("+fp-armv8");
+  if (Extensions & AArch64::AEK_SIMD)
+    Features.push_back("+neon");
+  if (Extensions & AArch64::AEK_CRC)
+    Features.push_back("+crc");
+  if (Extensions & AArch64::AEK_CRYPTO)
+    Features.push_back("+crypto");
+  if (Extensions & AArch64::AEK_FP16)
+    Features.push_back("+fullfp16");
+  if (Extensions & AArch64::AEK_PROFILE)
+    Features.push_back("+spe");
+  if (Extensions & AArch64::AEK_RAS)
+    Features.push_back("+ras");
+
+  return true;
+}
+
+bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
+                               std::vector<const char *> &Features) {
+  return ARM::getFPUFeatures(FPUKind, Features);
+}
+
+bool llvm::AArch64::getArchFeatures(unsigned ArchKind,
+                                     std::vector<const char *> &Features) {
+  if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A))
+    Features.push_back("+v8.1a");
+  if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A))
+    Features.push_back("+v8.2a");
+
+  return ArchKind > static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) &&
+         ArchKind < static_cast<unsigned>(AArch64::ArchKind::AK_LAST);
+}
+
+StringRef llvm::AArch64::getArchName(unsigned ArchKind) {
+  if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
+    return StringRef();
+  return AArch64ARCHNames[ArchKind].getName();
+}
+
+StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) {
+  if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
+      ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
+    return StringRef();
+  return AArch64ARCHNames[ArchKind].getCPUAttr();
+}
+
+StringRef llvm::AArch64::getSubArch(unsigned ArchKind) {
+  if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) ||
+      ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
+    return StringRef();
+  return AArch64ARCHNames[ArchKind].getSubArch();
+}
+
+unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) {
+  if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST))
+    return ARMBuildAttrs::CPUArch::v8_A;
+  return AArch64ARCHNames[ArchKind].ArchAttr;
+}
+
+StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) {
+  for (const auto &AE : AArch64ARCHExtNames)
+    if (ArchExtKind == AE.ID)
+      return AE.getName();
+  return StringRef();
+}
+
+const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
+  if (ArchExt.startswith("no")) {
+    StringRef ArchExtBase(ArchExt.substr(2));
+    for (const auto &AE : AArch64ARCHExtNames) {
+      if (AE.NegFeature && ArchExtBase == AE.getName())
+        return AE.NegFeature;
+    }
+  }
+
+  for (const auto &AE : AArch64ARCHExtNames)
+    if (AE.Feature && ArchExt == AE.getName())
+      return AE.Feature;
+  return nullptr;
+}
+
+StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
+  unsigned AK = parseArch(Arch);
+  if (AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
+    return StringRef();
+
+  // Look for multiple AKs to find the default for pair AK+Name.
+  for (const auto &CPU : AArch64CPUNames)
+    if (static_cast<unsigned>(CPU.ArchID) == AK && CPU.Default)
+      return CPU.getName();
+
+  // If we can't find a default then target the architecture instead
+  return "generic";
+}
+
+unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
+  if (Arch[0] == 'v' && std::isdigit(Arch[1]))
+    return (Arch[1] - 48);
+  return 0;
+}
+
+// ======================================================= //
+// Parsers
+// ======================================================= //
+
+static StringRef getHWDivSynonym(StringRef HWDiv) {
+  return StringSwitch<StringRef>(HWDiv)
+      .Case("thumb,arm", "arm,thumb")
+      .Default(HWDiv);
+}
+
+static StringRef getFPUSynonym(StringRef FPU) {
+  return StringSwitch<StringRef>(FPU)
+      .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
+      .Case("vfp2", "vfpv2")
+      .Case("vfp3", "vfpv3")
+      .Case("vfp4", "vfpv4")
+      .Case("vfp3-d16", "vfpv3-d16")
+      .Case("vfp4-d16", "vfpv4-d16")
+      .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
+      .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
+      .Case("fp5-sp-d16", "fpv5-sp-d16")
+      .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
+      // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
+      .Case("neon-vfpv3", "neon")
+      .Default(FPU);
+}
+
+static StringRef getArchSynonym(StringRef Arch) {
+  return StringSwitch<StringRef>(Arch)
+      .Case("v5", "v5t")
+      .Case("v5e", "v5te")
+      .Case("v6j", "v6")
+      .Case("v6hl", "v6k")
+      .Cases("v6m", "v6sm", "v6s-m", "v6-m")
+      .Cases("v6z", "v6zk", "v6kz")
+      .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
+      .Case("v7r", "v7-r")
+      .Case("v7m", "v7-m")
+      .Case("v7em", "v7e-m")
+      .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
+      .Case("v8.1a", "v8.1-a")
+      .Case("v8.2a", "v8.2-a")
+      .Case("v8m.base", "v8-m.base")
+      .Case("v8m.main", "v8-m.main")
+      .Default(Arch);
+}
+
+// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
+// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
+// "v.+", if the latter, return unmodified string, minus 'eb'.
+// If invalid, return empty string.
+StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
+  size_t offset = StringRef::npos;
+  StringRef A = Arch;
+  StringRef Error = "";
+
+  // Begins with "arm" / "thumb", move past it.
+  if (A.startswith("arm64"))
+    offset = 5;
+  else if (A.startswith("arm"))
+    offset = 3;
+  else if (A.startswith("thumb"))
+    offset = 5;
+  else if (A.startswith("aarch64")) {
+    offset = 7;
+    // AArch64 uses "_be", not "eb" suffix.
+    if (A.find("eb") != StringRef::npos)
+      return Error;
+    if (A.substr(offset, 3) == "_be")
+      offset += 3;
+  }
+
+  // Ex. "armebv7", move past the "eb".
+  if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
+    offset += 2;
+  // Or, if it ends with eb ("armv7eb"), chop it off.
+  else if (A.endswith("eb"))
+    A = A.substr(0, A.size() - 2);
+  // Trim the head
+  if (offset != StringRef::npos)
+    A = A.substr(offset);
+
+  // Empty string means offset reached the end, which means it's valid.
+  if (A.empty())
+    return Arch;
+
+  // Only match non-marketing names
+  if (offset != StringRef::npos) {
+    // Must start with 'vN'.
+    if (A[0] != 'v' || !std::isdigit(A[1]))
+      return Error;
+    // Can't have an extra 'eb'.
+    if (A.find("eb") != StringRef::npos)
+      return Error;
+  }
+
+  // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
+  return A;
+}
+
+unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
+  StringRef Syn = getHWDivSynonym(HWDiv);
+  for (const auto D : HWDivNames) {
+    if (Syn == D.getName())
+      return D.ID;
+  }
+  return ARM::AEK_INVALID;
+}
+
+unsigned llvm::ARM::parseFPU(StringRef FPU) {
+  StringRef Syn = getFPUSynonym(FPU);
+  for (const auto F : FPUNames) {
+    if (Syn == F.getName())
+      return F.ID;
+  }
+  return ARM::FK_INVALID;
+}
+
+// Allows partial match, ex. "v7a" matches "armv7a".
+unsigned llvm::ARM::parseArch(StringRef Arch) {
+  Arch = getCanonicalArchName(Arch);
+  StringRef Syn = getArchSynonym(Arch);
+  for (const auto A : ARCHNames) {
+    if (A.getName().endswith(Syn))
+      return A.ID;
+  }
+  return ARM::AK_INVALID;
+}
+
+unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
+  for (const auto A : ARCHExtNames) {
+    if (ArchExt == A.getName())
+      return A.ID;
+  }
+  return ARM::AEK_INVALID;
+}
+
+unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
+  for (const auto C : CPUNames) {
+    if (CPU == C.getName())
+      return C.ArchID;
+  }
+  return ARM::AK_INVALID;
+}
+
+// ARM, Thumb, AArch64
+unsigned llvm::ARM::parseArchISA(StringRef Arch) {
+  return StringSwitch<unsigned>(Arch)
+      .StartsWith("aarch64", ARM::IK_AARCH64)
+      .StartsWith("arm64", ARM::IK_AARCH64)
+      .StartsWith("thumb", ARM::IK_THUMB)
+      .StartsWith("arm", ARM::IK_ARM)
+      .Default(ARM::IK_INVALID);
+}
+
+// Little/Big endian
+unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
+  if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
+      Arch.startswith("aarch64_be"))
+    return ARM::EK_BIG;
+
+  if (Arch.startswith("arm") || Arch.startswith("thumb")) {
+    if (Arch.endswith("eb"))
+      return ARM::EK_BIG;
+    else
+      return ARM::EK_LITTLE;
+  }
+
+  if (Arch.startswith("aarch64"))
+    return ARM::EK_LITTLE;
+
+  return ARM::EK_INVALID;
+}
+
+// Profile A/R/M
+unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
+  Arch = getCanonicalArchName(Arch);
+  switch (parseArch(Arch)) {
+  case ARM::AK_ARMV6M:
+  case ARM::AK_ARMV7M:
+  case ARM::AK_ARMV7EM:
+  case ARM::AK_ARMV8MMainline:
+  case ARM::AK_ARMV8MBaseline:
+    return ARM::PK_M;
+  case ARM::AK_ARMV7R:
+    return ARM::PK_R;
+  case ARM::AK_ARMV7A:
+  case ARM::AK_ARMV7K:
+  case ARM::AK_ARMV8A:
+  case ARM::AK_ARMV8_1A:
+  case ARM::AK_ARMV8_2A:
+    return ARM::PK_A;
+  }
+  return ARM::PK_INVALID;
+}
+
+// Version number (ex. v7 = 7).
+unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
+  Arch = getCanonicalArchName(Arch);
+  switch (parseArch(Arch)) {
+  case ARM::AK_ARMV2:
+  case ARM::AK_ARMV2A:
+    return 2;
+  case ARM::AK_ARMV3:
+  case ARM::AK_ARMV3M:
+    return 3;
+  case ARM::AK_ARMV4:
+  case ARM::AK_ARMV4T:
+    return 4;
+  case ARM::AK_ARMV5T:
+  case ARM::AK_ARMV5TE:
+  case ARM::AK_IWMMXT:
+  case ARM::AK_IWMMXT2:
+  case ARM::AK_XSCALE:
+  case ARM::AK_ARMV5TEJ:
+    return 5;
+  case ARM::AK_ARMV6:
+  case ARM::AK_ARMV6K:
+  case ARM::AK_ARMV6T2:
+  case ARM::AK_ARMV6KZ:
+  case ARM::AK_ARMV6M:
+    return 6;
+  case ARM::AK_ARMV7A:
+  case ARM::AK_ARMV7R:
+  case ARM::AK_ARMV7M:
+  case ARM::AK_ARMV7S:
+  case ARM::AK_ARMV7EM:
+  case ARM::AK_ARMV7K:
+    return 7;
+  case ARM::AK_ARMV8A:
+  case ARM::AK_ARMV8_1A:
+  case ARM::AK_ARMV8_2A:
+  case ARM::AK_ARMV8MBaseline:
+  case ARM::AK_ARMV8MMainline:
+    return 8;
+  }
+  return 0;
+}
+
+StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
+  return ARM::getCanonicalArchName(Arch);
+}
+
+unsigned llvm::AArch64::parseFPU(StringRef FPU) {
+  return ARM::parseFPU(FPU);
+}
+
+// Allows partial match, ex. "v8a" matches "armv8a".
+unsigned llvm::AArch64::parseArch(StringRef Arch) {
+  Arch = getCanonicalArchName(Arch);
+  if (checkArchVersion(Arch) < 8)
+    return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
+
+  StringRef Syn = getArchSynonym(Arch);
+  for (const auto A : AArch64ARCHNames) {
+    if (A.getName().endswith(Syn))
+      return static_cast<unsigned>(A.ID);
+  }
+  return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
+}
+
+unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) {
+  for (const auto A : AArch64ARCHExtNames) {
+    if (ArchExt == A.getName())
+      return A.ID;
+  }
+  return AArch64::AEK_INVALID;
+}
+
+unsigned llvm::AArch64::parseCPUArch(StringRef CPU) {
+  for (const auto C : AArch64CPUNames) {
+    if (CPU == C.getName())
+      return static_cast<unsigned>(C.ArchID);
+  }
+  return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID);
+}
+
+// ARM, Thumb, AArch64
+unsigned llvm::AArch64::parseArchISA(StringRef Arch) {
+  return ARM::parseArchISA(Arch);
+}
+
+// Little/Big endian
+unsigned llvm::AArch64::parseArchEndian(StringRef Arch) {
+  return ARM::parseArchEndian(Arch);
+}
+
+// Profile A/R/M
+unsigned llvm::AArch64::parseArchProfile(StringRef Arch) {
+  return ARM::parseArchProfile(Arch);
+}
+
+// Version number (ex. v8 = 8).
+unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
+  return ARM::parseArchVersion(Arch);
+}
diff --git a/third_party/llvm-subzero/lib/Support/Threading.cpp b/third_party/llvm-subzero/lib/Support/Threading.cpp
new file mode 100644
index 0000000..e8f5622
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Threading.cpp
@@ -0,0 +1,118 @@
+//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper functions for running LLVM in a multi-threaded
+// environment.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Threading.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Atomic.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/thread.h"
+#include <cassert>
+
+using namespace llvm;
+
+bool llvm::llvm_is_multithreaded() {
+#if LLVM_ENABLE_THREADS != 0
+  return true;
+#else
+  return false;
+#endif
+}
+
+#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
+#include <pthread.h>
+
+struct ThreadInfo {
+  void (*UserFn)(void *);
+  void *UserData;
+};
+static void *ExecuteOnThread_Dispatch(void *Arg) {
+  ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
+  TI->UserFn(TI->UserData);
+  return nullptr;
+}
+
+void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
+                                  unsigned RequestedStackSize) {
+  ThreadInfo Info = { Fn, UserData };
+  pthread_attr_t Attr;
+  pthread_t Thread;
+
+  // Construct the attributes object.
+  if (::pthread_attr_init(&Attr) != 0)
+    return;
+
+  // Set the requested stack size, if given.
+  if (RequestedStackSize != 0) {
+    if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
+      goto error;
+  }
+
+  // Construct and execute the thread.
+  if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
+    goto error;
+
+  // Wait for the thread and clean up.
+  ::pthread_join(Thread, nullptr);
+
+ error:
+  ::pthread_attr_destroy(&Attr);
+}
+#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
+#include "Windows/WindowsSupport.h"
+#include <process.h>
+
+// Windows will at times define MemoryFence.
+#ifdef MemoryFence
+#undef MemoryFence
+#endif
+
+struct ThreadInfo {
+  void (*func)(void*);
+  void *param;
+};
+
+static unsigned __stdcall ThreadCallback(void *param) {
+  struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
+  info->func(info->param);
+
+  return 0;
+}
+
+void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
+                                  unsigned RequestedStackSize) {
+  struct ThreadInfo param = { Fn, UserData };
+
+  HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
+                                            RequestedStackSize, ThreadCallback,
+                                            &param, 0, NULL);
+
+  if (hThread) {
+    // We actually don't care whether the wait succeeds or fails, in
+    // the same way we don't care whether the pthread_join call succeeds
+    // or fails.  There's not much we could do if this were to fail. But
+    // on success, this call will wait until the thread finishes executing
+    // before returning.
+    (void)::WaitForSingleObject(hThread, INFINITE);
+    ::CloseHandle(hThread);
+  }
+}
+#else
+// Support for non-Win32, non-pthread implementation.
+void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
+                                  unsigned RequestedStackSize) {
+  (void) RequestedStackSize;
+  Fn(UserData);
+}
+
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/TimeValue.cpp b/third_party/llvm-subzero/lib/Support/TimeValue.cpp
new file mode 100644
index 0000000..94a4c01
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/TimeValue.cpp
@@ -0,0 +1,56 @@
+//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the operating system TimeValue concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/TimeValue.h"
+#include "llvm/Config/config.h"
+
+namespace llvm {
+
+using namespace sys;
+
+const TimeValue::SecondsType
+  TimeValue::PosixZeroTimeSeconds = -946684800;
+const TimeValue::SecondsType
+  TimeValue::Win32ZeroTimeSeconds = -12591158400ULL;
+
+void TimeValue::normalize() {
+  if ( nanos_ >= NANOSECONDS_PER_SECOND ) {
+    do {
+      seconds_++;
+      nanos_ -= NANOSECONDS_PER_SECOND;
+    } while ( nanos_ >= NANOSECONDS_PER_SECOND );
+  } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) {
+    do {
+      seconds_--;
+      nanos_ += NANOSECONDS_PER_SECOND;
+    } while (nanos_ <= -NANOSECONDS_PER_SECOND);
+  }
+
+  if (seconds_ >= 1 && nanos_ < 0) {
+    seconds_--;
+    nanos_ += NANOSECONDS_PER_SECOND;
+  } else if (seconds_ < 0 && nanos_ > 0) {
+    seconds_++;
+    nanos_ -= NANOSECONDS_PER_SECOND;
+  }
+}
+
+} // namespace llvm
+
+/// Include the platform-specific portion of TimeValue class
+#ifdef LLVM_ON_UNIX
+#include "Unix/TimeValue.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/TimeValue.inc"
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/Timer.cpp b/third_party/llvm-subzero/lib/Support/Timer.cpp
new file mode 100644
index 0000000..49bd39e
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Timer.cpp
@@ -0,0 +1,375 @@
+//===-- Timer.cpp - Interval Timing Support -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interval Timing implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Timer.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
+// of constructor/destructor ordering being unspecified by C++.  Basically the
+// problem is that a Statistic object gets destroyed, which ends up calling
+// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
+// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
+// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
+// this by creating the string the first time it is needed and never destroying
+// it.
+static ManagedStatic<std::string> LibSupportInfoOutputFilename;
+static std::string &getLibSupportInfoOutputFilename() {
+  return *LibSupportInfoOutputFilename;
+}
+
+static ManagedStatic<sys::SmartMutex<true> > TimerLock;
+
+namespace {
+  static cl::opt<bool>
+  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
+                                      "tracking (this may be slow)"),
+             cl::Hidden);
+
+  static cl::opt<std::string, true>
+  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
+                     cl::desc("File to append -stats and -timer output to"),
+                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
+}
+
+// Return a file stream to print our output on.
+std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() {
+  const std::string &OutputFilename = getLibSupportInfoOutputFilename();
+  if (OutputFilename.empty())
+    return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
+  if (OutputFilename == "-")
+    return llvm::make_unique<raw_fd_ostream>(1, false); // stdout.
+
+  // Append mode is used because the info output file is opened and closed
+  // each time -stats or -time-passes wants to print output to it. To
+  // compensate for this, the test-suite Makefiles have code to delete the
+  // info output file before running commands which write to it.
+  std::error_code EC;
+  auto Result = llvm::make_unique<raw_fd_ostream>(
+      OutputFilename, EC, sys::fs::F_Append | sys::fs::F_Text);
+  if (!EC)
+    return Result;
+
+  errs() << "Error opening info-output-file '"
+    << OutputFilename << " for appending!\n";
+  return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
+}
+
+
+static TimerGroup *DefaultTimerGroup = nullptr;
+static TimerGroup *getDefaultTimerGroup() {
+  TimerGroup *tmp = DefaultTimerGroup;
+  sys::MemoryFence();
+  if (tmp) return tmp;
+
+  sys::SmartScopedLock<true> Lock(*TimerLock);
+  tmp = DefaultTimerGroup;
+  if (!tmp) {
+    tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
+    sys::MemoryFence();
+    DefaultTimerGroup = tmp;
+  }
+
+  return tmp;
+}
+
+//===----------------------------------------------------------------------===//
+// Timer Implementation
+//===----------------------------------------------------------------------===//
+
+void Timer::init(StringRef N) {
+  init(N, *getDefaultTimerGroup());
+}
+
+void Timer::init(StringRef N, TimerGroup &tg) {
+  assert(!TG && "Timer already initialized");
+  Name.assign(N.begin(), N.end());
+  Running = Triggered = false;
+  TG = &tg;
+  TG->addTimer(*this);
+}
+
+Timer::~Timer() {
+  if (!TG) return;  // Never initialized, or already cleared.
+  TG->removeTimer(*this);
+}
+
+static inline size_t getMemUsage() {
+  if (!TrackSpace) return 0;
+  return sys::Process::GetMallocUsage();
+}
+
+TimeRecord TimeRecord::getCurrentTime(bool Start) {
+  TimeRecord Result;
+  sys::TimeValue now(0,0), user(0,0), sys(0,0);
+
+  if (Start) {
+    Result.MemUsed = getMemUsage();
+    sys::Process::GetTimeUsage(now, user, sys);
+  } else {
+    sys::Process::GetTimeUsage(now, user, sys);
+    Result.MemUsed = getMemUsage();
+  }
+
+  Result.WallTime   =  now.seconds() +  now.microseconds() / 1000000.0;
+  Result.UserTime   = user.seconds() + user.microseconds() / 1000000.0;
+  Result.SystemTime =  sys.seconds() +  sys.microseconds() / 1000000.0;
+  return Result;
+}
+
+void Timer::startTimer() {
+  assert(!Running && "Cannot start a running timer");
+  Running = Triggered = true;
+  StartTime = TimeRecord::getCurrentTime(true);
+}
+
+void Timer::stopTimer() {
+  assert(Running && "Cannot stop a paused timer");
+  Running = false;
+  Time += TimeRecord::getCurrentTime(false);
+  Time -= StartTime;
+}
+
+void Timer::clear() {
+  Running = Triggered = false;
+  Time = StartTime = TimeRecord();
+}
+
+static void printVal(double Val, double Total, raw_ostream &OS) {
+  if (Total < 1e-7)   // Avoid dividing by zero.
+    OS << "        -----     ";
+  else
+    OS << format("  %7.4f (%5.1f%%)", Val, Val*100/Total);
+}
+
+void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
+  if (Total.getUserTime())
+    printVal(getUserTime(), Total.getUserTime(), OS);
+  if (Total.getSystemTime())
+    printVal(getSystemTime(), Total.getSystemTime(), OS);
+  if (Total.getProcessTime())
+    printVal(getProcessTime(), Total.getProcessTime(), OS);
+  printVal(getWallTime(), Total.getWallTime(), OS);
+
+  OS << "  ";
+
+  if (Total.getMemUsed())
+    OS << format("%9" PRId64 "  ", (int64_t)getMemUsed());
+}
+
+
+//===----------------------------------------------------------------------===//
+//   NamedRegionTimer Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+typedef StringMap<Timer> Name2TimerMap;
+
+class Name2PairMap {
+  StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map;
+public:
+  ~Name2PairMap() {
+    for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator
+         I = Map.begin(), E = Map.end(); I != E; ++I)
+      delete I->second.first;
+  }
+
+  Timer &get(StringRef Name, StringRef GroupName) {
+    sys::SmartScopedLock<true> L(*TimerLock);
+
+    std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName];
+
+    if (!GroupEntry.first)
+      GroupEntry.first = new TimerGroup(GroupName);
+
+    Timer &T = GroupEntry.second[Name];
+    if (!T.isInitialized())
+      T.init(Name, *GroupEntry.first);
+    return T;
+  }
+};
+
+}
+
+static ManagedStatic<Name2TimerMap> NamedTimers;
+static ManagedStatic<Name2PairMap> NamedGroupedTimers;
+
+static Timer &getNamedRegionTimer(StringRef Name) {
+  sys::SmartScopedLock<true> L(*TimerLock);
+
+  Timer &T = (*NamedTimers)[Name];
+  if (!T.isInitialized())
+    T.init(Name);
+  return T;
+}
+
+NamedRegionTimer::NamedRegionTimer(StringRef Name,
+                                   bool Enabled)
+  : TimeRegion(!Enabled ? nullptr : &getNamedRegionTimer(Name)) {}
+
+NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName,
+                                   bool Enabled)
+  : TimeRegion(!Enabled ? nullptr : &NamedGroupedTimers->get(Name, GroupName)){}
+
+//===----------------------------------------------------------------------===//
+//   TimerGroup Implementation
+//===----------------------------------------------------------------------===//
+
+/// TimerGroupList - This is the global list of TimerGroups, maintained by the
+/// TimerGroup ctor/dtor and is protected by the TimerLock lock.
+static TimerGroup *TimerGroupList = nullptr;
+
+TimerGroup::TimerGroup(StringRef name)
+  : Name(name.begin(), name.end()), FirstTimer(nullptr) {
+
+  // Add the group to TimerGroupList.
+  sys::SmartScopedLock<true> L(*TimerLock);
+  if (TimerGroupList)
+    TimerGroupList->Prev = &Next;
+  Next = TimerGroupList;
+  Prev = &TimerGroupList;
+  TimerGroupList = this;
+}
+
+TimerGroup::~TimerGroup() {
+  // If the timer group is destroyed before the timers it owns, accumulate and
+  // print the timing data.
+  while (FirstTimer)
+    removeTimer(*FirstTimer);
+
+  // Remove the group from the TimerGroupList.
+  sys::SmartScopedLock<true> L(*TimerLock);
+  *Prev = Next;
+  if (Next)
+    Next->Prev = Prev;
+}
+
+
+void TimerGroup::removeTimer(Timer &T) {
+  sys::SmartScopedLock<true> L(*TimerLock);
+
+  // If the timer was started, move its data to TimersToPrint.
+  if (T.hasTriggered())
+    TimersToPrint.emplace_back(T.Time, T.Name);
+
+  T.TG = nullptr;
+
+  // Unlink the timer from our list.
+  *T.Prev = T.Next;
+  if (T.Next)
+    T.Next->Prev = T.Prev;
+
+  // Print the report when all timers in this group are destroyed if some of
+  // them were started.
+  if (FirstTimer || TimersToPrint.empty())
+    return;
+
+  std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
+  PrintQueuedTimers(*OutStream);
+}
+
+void TimerGroup::addTimer(Timer &T) {
+  sys::SmartScopedLock<true> L(*TimerLock);
+
+  // Add the timer to our list.
+  if (FirstTimer)
+    FirstTimer->Prev = &T.Next;
+  T.Next = FirstTimer;
+  T.Prev = &FirstTimer;
+  FirstTimer = &T;
+}
+
+void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
+  // Sort the timers in descending order by amount of time taken.
+  std::sort(TimersToPrint.begin(), TimersToPrint.end());
+
+  TimeRecord Total;
+  for (auto &RecordNamePair : TimersToPrint)
+    Total += RecordNamePair.first;
+
+  // Print out timing header.
+  OS << "===" << std::string(73, '-') << "===\n";
+  // Figure out how many spaces to indent TimerGroup name.
+  unsigned Padding = (80-Name.length())/2;
+  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
+  OS.indent(Padding) << Name << '\n';
+  OS << "===" << std::string(73, '-') << "===\n";
+
+  // If this is not an collection of ungrouped times, print the total time.
+  // Ungrouped timers don't really make sense to add up.  We still print the
+  // TOTAL line to make the percentages make sense.
+  if (this != DefaultTimerGroup)
+    OS << format("  Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
+                 Total.getProcessTime(), Total.getWallTime());
+  OS << '\n';
+
+  if (Total.getUserTime())
+    OS << "   ---User Time---";
+  if (Total.getSystemTime())
+    OS << "   --System Time--";
+  if (Total.getProcessTime())
+    OS << "   --User+System--";
+  OS << "   ---Wall Time---";
+  if (Total.getMemUsed())
+    OS << "  ---Mem---";
+  OS << "  --- Name ---\n";
+
+  // Loop through all of the timing data, printing it out.
+  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
+    const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
+    Entry.first.print(Total, OS);
+    OS << Entry.second << '\n';
+  }
+
+  Total.print(Total, OS);
+  OS << "Total\n\n";
+  OS.flush();
+
+  TimersToPrint.clear();
+}
+
+/// print - Print any started timers in this group and zero them.
+void TimerGroup::print(raw_ostream &OS) {
+  sys::SmartScopedLock<true> L(*TimerLock);
+
+  // See if any of our timers were started, if so add them to TimersToPrint and
+  // reset them.
+  for (Timer *T = FirstTimer; T; T = T->Next) {
+    if (!T->hasTriggered()) continue;
+    TimersToPrint.emplace_back(T->Time, T->Name);
+    
+    // Clear out the time.
+    T->clear();
+  }
+
+  // If any timers were started, print the group.
+  if (!TimersToPrint.empty())
+    PrintQueuedTimers(OS);
+}
+
+/// printAll - This static method prints all timers and clears them all out.
+void TimerGroup::printAll(raw_ostream &OS) {
+  sys::SmartScopedLock<true> L(*TimerLock);
+
+  for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
+    TG->print(OS);
+}
diff --git a/third_party/llvm-subzero/lib/Support/Triple.cpp b/third_party/llvm-subzero/lib/Support/Triple.cpp
new file mode 100644
index 0000000..2bac2a3
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Triple.cpp
@@ -0,0 +1,1489 @@
+//===--- Triple.cpp - Target triple helper class --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/Host.h"
+#include <cstring>
+using namespace llvm;
+
+const char *Triple::getArchTypeName(ArchType Kind) {
+  switch (Kind) {
+  case UnknownArch:    return "unknown";
+
+  case aarch64:        return "aarch64";
+  case aarch64_be:     return "aarch64_be";
+  case arm:            return "arm";
+  case armeb:          return "armeb";
+  case avr:            return "avr";
+  case bpfel:          return "bpfel";
+  case bpfeb:          return "bpfeb";
+  case hexagon:        return "hexagon";
+  case mips:           return "mips";
+  case mipsel:         return "mipsel";
+  case mips64:         return "mips64";
+  case mips64el:       return "mips64el";
+  case msp430:         return "msp430";
+  case ppc64:          return "powerpc64";
+  case ppc64le:        return "powerpc64le";
+  case ppc:            return "powerpc";
+  case r600:           return "r600";
+  case amdgcn:         return "amdgcn";
+  case sparc:          return "sparc";
+  case sparcv9:        return "sparcv9";
+  case sparcel:        return "sparcel";
+  case systemz:        return "s390x";
+  case tce:            return "tce";
+  case thumb:          return "thumb";
+  case thumbeb:        return "thumbeb";
+  case x86:            return "i386";
+  case x86_64:         return "x86_64";
+  case xcore:          return "xcore";
+  case nvptx:          return "nvptx";
+  case nvptx64:        return "nvptx64";
+  case le32:           return "le32";
+  case le64:           return "le64";
+  case amdil:          return "amdil";
+  case amdil64:        return "amdil64";
+  case hsail:          return "hsail";
+  case hsail64:        return "hsail64";
+  case spir:           return "spir";
+  case spir64:         return "spir64";
+  case kalimba:        return "kalimba";
+  case lanai:          return "lanai";
+  case shave:          return "shave";
+  case wasm32:         return "wasm32";
+  case wasm64:         return "wasm64";
+  case renderscript32: return "renderscript32";
+  case renderscript64: return "renderscript64";
+  }
+
+  llvm_unreachable("Invalid ArchType!");
+}
+
+const char *Triple::getArchTypePrefix(ArchType Kind) {
+  switch (Kind) {
+  default:
+    return nullptr;
+
+  case aarch64:
+  case aarch64_be:  return "aarch64";
+
+  case arm:
+  case armeb:
+  case thumb:
+  case thumbeb:     return "arm";
+
+  case avr:         return "avr";
+
+  case ppc64:
+  case ppc64le:
+  case ppc:         return "ppc";
+
+  case mips:
+  case mipsel:
+  case mips64:
+  case mips64el:    return "mips";
+
+  case hexagon:     return "hexagon";
+
+  case amdgcn:      return "amdgcn";
+  case r600:        return "r600";
+
+  case bpfel:
+  case bpfeb:       return "bpf";
+
+  case sparcv9:
+  case sparcel:
+  case sparc:       return "sparc";
+
+  case systemz:     return "s390";
+
+  case x86:
+  case x86_64:      return "x86";
+
+  case xcore:       return "xcore";
+
+  // NVPTX intrinsics are namespaced under nvvm.
+  case nvptx:       return "nvvm";
+  case nvptx64:     return "nvvm";
+
+  case le32:        return "le32";
+  case le64:        return "le64";
+
+  case amdil:
+  case amdil64:     return "amdil";
+
+  case hsail:
+  case hsail64:     return "hsail";
+
+  case spir:
+  case spir64:      return "spir";
+  case kalimba:     return "kalimba";
+  case lanai:       return "lanai";
+  case shave:       return "shave";
+  case wasm32:
+  case wasm64:      return "wasm";
+  }
+}
+
+const char *Triple::getVendorTypeName(VendorType Kind) {
+  switch (Kind) {
+  case UnknownVendor: return "unknown";
+
+  case Apple: return "apple";
+  case PC: return "pc";
+  case SCEI: return "scei";
+  case BGP: return "bgp";
+  case BGQ: return "bgq";
+  case Freescale: return "fsl";
+  case IBM: return "ibm";
+  case ImaginationTechnologies: return "img";
+  case MipsTechnologies: return "mti";
+  case NVIDIA: return "nvidia";
+  case CSR: return "csr";
+  case Myriad: return "myriad";
+  case AMD: return "amd";
+  case Mesa: return "mesa";
+  }
+
+  llvm_unreachable("Invalid VendorType!");
+}
+
+const char *Triple::getOSTypeName(OSType Kind) {
+  switch (Kind) {
+  case UnknownOS: return "unknown";
+
+  case CloudABI: return "cloudabi";
+  case Darwin: return "darwin";
+  case DragonFly: return "dragonfly";
+  case FreeBSD: return "freebsd";
+  case IOS: return "ios";
+  case KFreeBSD: return "kfreebsd";
+  case Linux: return "linux";
+  case Lv2: return "lv2";
+  case MacOSX: return "macosx";
+  case NetBSD: return "netbsd";
+  case OpenBSD: return "openbsd";
+  case Solaris: return "solaris";
+  case Win32: return "windows";
+  case Haiku: return "haiku";
+  case Minix: return "minix";
+  case RTEMS: return "rtems";
+  case NaCl: return "nacl";
+  case CNK: return "cnk";
+  case Bitrig: return "bitrig";
+  case AIX: return "aix";
+  case CUDA: return "cuda";
+  case NVCL: return "nvcl";
+  case AMDHSA: return "amdhsa";
+  case PS4: return "ps4";
+  case ELFIAMCU: return "elfiamcu";
+  case TvOS: return "tvos";
+  case WatchOS: return "watchos";
+  case Mesa3D: return "mesa3d";
+  }
+
+  llvm_unreachable("Invalid OSType");
+}
+
+const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) {
+  switch (Kind) {
+  case UnknownEnvironment: return "unknown";
+  case GNU: return "gnu";
+  case GNUABI64: return "gnuabi64";
+  case GNUEABIHF: return "gnueabihf";
+  case GNUEABI: return "gnueabi";
+  case GNUX32: return "gnux32";
+  case CODE16: return "code16";
+  case EABI: return "eabi";
+  case EABIHF: return "eabihf";
+  case Android: return "android";
+  case Musl: return "musl";
+  case MuslEABI: return "musleabi";
+  case MuslEABIHF: return "musleabihf";
+  case MSVC: return "msvc";
+  case Itanium: return "itanium";
+  case Cygnus: return "cygnus";
+  case AMDOpenCL: return "amdopencl";
+  case CoreCLR: return "coreclr";
+  }
+
+  llvm_unreachable("Invalid EnvironmentType!");
+}
+
+static Triple::ArchType parseBPFArch(StringRef ArchName) {
+  if (ArchName.equals("bpf")) {
+    if (sys::IsLittleEndianHost)
+      return Triple::bpfel;
+    else
+      return Triple::bpfeb;
+  } else if (ArchName.equals("bpf_be") || ArchName.equals("bpfeb")) {
+    return Triple::bpfeb;
+  } else if (ArchName.equals("bpf_le") || ArchName.equals("bpfel")) {
+    return Triple::bpfel;
+  } else {
+    return Triple::UnknownArch;
+  }
+}
+
+Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
+  Triple::ArchType BPFArch(parseBPFArch(Name));
+  return StringSwitch<Triple::ArchType>(Name)
+    .Case("aarch64", aarch64)
+    .Case("aarch64_be", aarch64_be)
+    .Case("arm64", aarch64) // "arm64" is an alias for "aarch64"
+    .Case("arm", arm)
+    .Case("armeb", armeb)
+    .Case("avr", avr)
+    .StartsWith("bpf", BPFArch)
+    .Case("mips", mips)
+    .Case("mipsel", mipsel)
+    .Case("mips64", mips64)
+    .Case("mips64el", mips64el)
+    .Case("msp430", msp430)
+    .Case("ppc64", ppc64)
+    .Case("ppc32", ppc)
+    .Case("ppc", ppc)
+    .Case("ppc64le", ppc64le)
+    .Case("r600", r600)
+    .Case("amdgcn", amdgcn)
+    .Case("hexagon", hexagon)
+    .Case("sparc", sparc)
+    .Case("sparcel", sparcel)
+    .Case("sparcv9", sparcv9)
+    .Case("systemz", systemz)
+    .Case("tce", tce)
+    .Case("thumb", thumb)
+    .Case("thumbeb", thumbeb)
+    .Case("x86", x86)
+    .Case("x86-64", x86_64)
+    .Case("xcore", xcore)
+    .Case("nvptx", nvptx)
+    .Case("nvptx64", nvptx64)
+    .Case("le32", le32)
+    .Case("le64", le64)
+    .Case("amdil", amdil)
+    .Case("amdil64", amdil64)
+    .Case("hsail", hsail)
+    .Case("hsail64", hsail64)
+    .Case("spir", spir)
+    .Case("spir64", spir64)
+    .Case("kalimba", kalimba)
+    .Case("lanai", lanai)
+    .Case("shave", shave)
+    .Case("wasm32", wasm32)
+    .Case("wasm64", wasm64)
+    .Case("renderscript32", renderscript32)
+    .Case("renderscript64", renderscript64)
+    .Default(UnknownArch);
+}
+
+static Triple::ArchType parseARMArch(StringRef ArchName) {
+  unsigned ISA = ARM::parseArchISA(ArchName);
+  unsigned ENDIAN = ARM::parseArchEndian(ArchName);
+
+  Triple::ArchType arch = Triple::UnknownArch;
+  switch (ENDIAN) {
+  case ARM::EK_LITTLE: {
+    switch (ISA) {
+    case ARM::IK_ARM:
+      arch = Triple::arm;
+      break;
+    case ARM::IK_THUMB:
+      arch = Triple::thumb;
+      break;
+    case ARM::IK_AARCH64:
+      arch = Triple::aarch64;
+      break;
+    }
+    break;
+  }
+  case ARM::EK_BIG: {
+    switch (ISA) {
+    case ARM::IK_ARM:
+      arch = Triple::armeb;
+      break;
+    case ARM::IK_THUMB:
+      arch = Triple::thumbeb;
+      break;
+    case ARM::IK_AARCH64:
+      arch = Triple::aarch64_be;
+      break;
+    }
+    break;
+  }
+  }
+
+  ArchName = ARM::getCanonicalArchName(ArchName);
+  if (ArchName.empty())
+    return Triple::UnknownArch;
+
+  // Thumb only exists in v4+
+  if (ISA == ARM::IK_THUMB &&
+      (ArchName.startswith("v2") || ArchName.startswith("v3")))
+    return Triple::UnknownArch;
+
+  // Thumb only for v6m
+  unsigned Profile = ARM::parseArchProfile(ArchName);
+  unsigned Version = ARM::parseArchVersion(ArchName);
+  if (Profile == ARM::PK_M && Version == 6) {
+    if (ENDIAN == ARM::EK_BIG)
+      return Triple::thumbeb;
+    else
+      return Triple::thumb;
+  }
+
+  return arch;
+}
+
+static Triple::ArchType parseArch(StringRef ArchName) {
+  auto AT = StringSwitch<Triple::ArchType>(ArchName)
+    .Cases("i386", "i486", "i586", "i686", Triple::x86)
+    // FIXME: Do we need to support these?
+    .Cases("i786", "i886", "i986", Triple::x86)
+    .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64)
+    .Cases("powerpc", "ppc32", Triple::ppc)
+    .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64)
+    .Cases("powerpc64le", "ppc64le", Triple::ppc64le)
+    .Case("xscale", Triple::arm)
+    .Case("xscaleeb", Triple::armeb)
+    .Case("aarch64", Triple::aarch64)
+    .Case("aarch64_be", Triple::aarch64_be)
+    .Case("arm64", Triple::aarch64)
+    .Case("arm", Triple::arm)
+    .Case("armeb", Triple::armeb)
+    .Case("thumb", Triple::thumb)
+    .Case("thumbeb", Triple::thumbeb)
+    .Case("avr", Triple::avr)
+    .Case("msp430", Triple::msp430)
+    .Cases("mips", "mipseb", "mipsallegrex", Triple::mips)
+    .Cases("mipsel", "mipsallegrexel", Triple::mipsel)
+    .Cases("mips64", "mips64eb", Triple::mips64)
+    .Case("mips64el", Triple::mips64el)
+    .Case("r600", Triple::r600)
+    .Case("amdgcn", Triple::amdgcn)
+    .Case("hexagon", Triple::hexagon)
+    .Cases("s390x", "systemz", Triple::systemz)
+    .Case("sparc", Triple::sparc)
+    .Case("sparcel", Triple::sparcel)
+    .Cases("sparcv9", "sparc64", Triple::sparcv9)
+    .Case("tce", Triple::tce)
+    .Case("xcore", Triple::xcore)
+    .Case("nvptx", Triple::nvptx)
+    .Case("nvptx64", Triple::nvptx64)
+    .Case("le32", Triple::le32)
+    .Case("le64", Triple::le64)
+    .Case("amdil", Triple::amdil)
+    .Case("amdil64", Triple::amdil64)
+    .Case("hsail", Triple::hsail)
+    .Case("hsail64", Triple::hsail64)
+    .Case("spir", Triple::spir)
+    .Case("spir64", Triple::spir64)
+    .StartsWith("kalimba", Triple::kalimba)
+    .Case("lanai", Triple::lanai)
+    .Case("shave", Triple::shave)
+    .Case("wasm32", Triple::wasm32)
+    .Case("wasm64", Triple::wasm64)
+    .Case("renderscript32", Triple::renderscript32)
+    .Case("renderscript64", Triple::renderscript64)
+    .Default(Triple::UnknownArch);
+
+  // Some architectures require special parsing logic just to compute the
+  // ArchType result.
+  if (AT == Triple::UnknownArch) {
+    if (ArchName.startswith("arm") || ArchName.startswith("thumb") ||
+        ArchName.startswith("aarch64"))
+      return parseARMArch(ArchName);
+    if (ArchName.startswith("bpf"))
+      return parseBPFArch(ArchName);
+  }
+
+  return AT;
+}
+
+static Triple::VendorType parseVendor(StringRef VendorName) {
+  return StringSwitch<Triple::VendorType>(VendorName)
+    .Case("apple", Triple::Apple)
+    .Case("pc", Triple::PC)
+    .Case("scei", Triple::SCEI)
+    .Case("bgp", Triple::BGP)
+    .Case("bgq", Triple::BGQ)
+    .Case("fsl", Triple::Freescale)
+    .Case("ibm", Triple::IBM)
+    .Case("img", Triple::ImaginationTechnologies)
+    .Case("mti", Triple::MipsTechnologies)
+    .Case("nvidia", Triple::NVIDIA)
+    .Case("csr", Triple::CSR)
+    .Case("myriad", Triple::Myriad)
+    .Case("amd", Triple::AMD)
+    .Case("mesa", Triple::Mesa)
+    .Default(Triple::UnknownVendor);
+}
+
+static Triple::OSType parseOS(StringRef OSName) {
+  return StringSwitch<Triple::OSType>(OSName)
+    .StartsWith("cloudabi", Triple::CloudABI)
+    .StartsWith("darwin", Triple::Darwin)
+    .StartsWith("dragonfly", Triple::DragonFly)
+    .StartsWith("freebsd", Triple::FreeBSD)
+    .StartsWith("ios", Triple::IOS)
+    .StartsWith("kfreebsd", Triple::KFreeBSD)
+    .StartsWith("linux", Triple::Linux)
+    .StartsWith("lv2", Triple::Lv2)
+    .StartsWith("macosx", Triple::MacOSX)
+    .StartsWith("netbsd", Triple::NetBSD)
+    .StartsWith("openbsd", Triple::OpenBSD)
+    .StartsWith("solaris", Triple::Solaris)
+    .StartsWith("win32", Triple::Win32)
+    .StartsWith("windows", Triple::Win32)
+    .StartsWith("haiku", Triple::Haiku)
+    .StartsWith("minix", Triple::Minix)
+    .StartsWith("rtems", Triple::RTEMS)
+    .StartsWith("nacl", Triple::NaCl)
+    .StartsWith("cnk", Triple::CNK)
+    .StartsWith("bitrig", Triple::Bitrig)
+    .StartsWith("aix", Triple::AIX)
+    .StartsWith("cuda", Triple::CUDA)
+    .StartsWith("nvcl", Triple::NVCL)
+    .StartsWith("amdhsa", Triple::AMDHSA)
+    .StartsWith("ps4", Triple::PS4)
+    .StartsWith("elfiamcu", Triple::ELFIAMCU)
+    .StartsWith("tvos", Triple::TvOS)
+    .StartsWith("watchos", Triple::WatchOS)
+    .StartsWith("mesa3d", Triple::Mesa3D)
+    .Default(Triple::UnknownOS);
+}
+
+static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
+  return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
+    .StartsWith("eabihf", Triple::EABIHF)
+    .StartsWith("eabi", Triple::EABI)
+    .StartsWith("gnuabi64", Triple::GNUABI64)
+    .StartsWith("gnueabihf", Triple::GNUEABIHF)
+    .StartsWith("gnueabi", Triple::GNUEABI)
+    .StartsWith("gnux32", Triple::GNUX32)
+    .StartsWith("code16", Triple::CODE16)
+    .StartsWith("gnu", Triple::GNU)
+    .StartsWith("android", Triple::Android)
+    .StartsWith("musleabihf", Triple::MuslEABIHF)
+    .StartsWith("musleabi", Triple::MuslEABI)
+    .StartsWith("musl", Triple::Musl)
+    .StartsWith("msvc", Triple::MSVC)
+    .StartsWith("itanium", Triple::Itanium)
+    .StartsWith("cygnus", Triple::Cygnus)
+    .StartsWith("amdopencl", Triple::AMDOpenCL)
+    .StartsWith("coreclr", Triple::CoreCLR)
+    .Default(Triple::UnknownEnvironment);
+}
+
+static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) {
+  return StringSwitch<Triple::ObjectFormatType>(EnvironmentName)
+    .EndsWith("coff", Triple::COFF)
+    .EndsWith("elf", Triple::ELF)
+    .EndsWith("macho", Triple::MachO)
+    .Default(Triple::UnknownObjectFormat);
+}
+
+static Triple::SubArchType parseSubArch(StringRef SubArchName) {
+  StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
+
+  // For now, this is the small part. Early return.
+  if (ARMSubArch.empty())
+    return StringSwitch<Triple::SubArchType>(SubArchName)
+      .EndsWith("kalimba3", Triple::KalimbaSubArch_v3)
+      .EndsWith("kalimba4", Triple::KalimbaSubArch_v4)
+      .EndsWith("kalimba5", Triple::KalimbaSubArch_v5)
+      .Default(Triple::NoSubArch);
+
+  // ARM sub arch.
+  switch(ARM::parseArch(ARMSubArch)) {
+  case ARM::AK_ARMV4:
+    return Triple::NoSubArch;
+  case ARM::AK_ARMV4T:
+    return Triple::ARMSubArch_v4t;
+  case ARM::AK_ARMV5T:
+    return Triple::ARMSubArch_v5;
+  case ARM::AK_ARMV5TE:
+  case ARM::AK_IWMMXT:
+  case ARM::AK_IWMMXT2:
+  case ARM::AK_XSCALE:
+  case ARM::AK_ARMV5TEJ:
+    return Triple::ARMSubArch_v5te;
+  case ARM::AK_ARMV6:
+    return Triple::ARMSubArch_v6;
+  case ARM::AK_ARMV6K:
+  case ARM::AK_ARMV6KZ:
+    return Triple::ARMSubArch_v6k;
+  case ARM::AK_ARMV6T2:
+    return Triple::ARMSubArch_v6t2;
+  case ARM::AK_ARMV6M:
+    return Triple::ARMSubArch_v6m;
+  case ARM::AK_ARMV7A:
+  case ARM::AK_ARMV7R:
+    return Triple::ARMSubArch_v7;
+  case ARM::AK_ARMV7K:
+    return Triple::ARMSubArch_v7k;
+  case ARM::AK_ARMV7M:
+    return Triple::ARMSubArch_v7m;
+  case ARM::AK_ARMV7S:
+    return Triple::ARMSubArch_v7s;
+  case ARM::AK_ARMV7EM:
+    return Triple::ARMSubArch_v7em;
+  case ARM::AK_ARMV8A:
+    return Triple::ARMSubArch_v8;
+  case ARM::AK_ARMV8_1A:
+    return Triple::ARMSubArch_v8_1a;
+  case ARM::AK_ARMV8_2A:
+    return Triple::ARMSubArch_v8_2a;
+  case ARM::AK_ARMV8MBaseline:
+    return Triple::ARMSubArch_v8m_baseline;
+  case ARM::AK_ARMV8MMainline:
+    return Triple::ARMSubArch_v8m_mainline;
+  default:
+    return Triple::NoSubArch;
+  }
+}
+
+static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) {
+  switch (Kind) {
+  case Triple::UnknownObjectFormat: return "";
+  case Triple::COFF: return "coff";
+  case Triple::ELF: return "elf";
+  case Triple::MachO: return "macho";
+  }
+  llvm_unreachable("unknown object format type");
+}
+
+static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
+  switch (T.getArch()) {
+  case Triple::UnknownArch:
+  case Triple::aarch64:
+  case Triple::arm:
+  case Triple::thumb:
+  case Triple::x86:
+  case Triple::x86_64:
+    if (T.isOSDarwin())
+      return Triple::MachO;
+    else if (T.isOSWindows())
+      return Triple::COFF;
+    return Triple::ELF;
+
+  case Triple::aarch64_be:
+  case Triple::amdgcn:
+  case Triple::amdil:
+  case Triple::amdil64:
+  case Triple::armeb:
+  case Triple::avr:
+  case Triple::bpfeb:
+  case Triple::bpfel:
+  case Triple::hexagon:
+  case Triple::lanai:
+  case Triple::hsail:
+  case Triple::hsail64:
+  case Triple::kalimba:
+  case Triple::le32:
+  case Triple::le64:
+  case Triple::mips:
+  case Triple::mips64:
+  case Triple::mips64el:
+  case Triple::mipsel:
+  case Triple::msp430:
+  case Triple::nvptx:
+  case Triple::nvptx64:
+  case Triple::ppc64le:
+  case Triple::r600:
+  case Triple::renderscript32:
+  case Triple::renderscript64:
+  case Triple::shave:
+  case Triple::sparc:
+  case Triple::sparcel:
+  case Triple::sparcv9:
+  case Triple::spir:
+  case Triple::spir64:
+  case Triple::systemz:
+  case Triple::tce:
+  case Triple::thumbeb:
+  case Triple::wasm32:
+  case Triple::wasm64:
+  case Triple::xcore:
+    return Triple::ELF;
+
+  case Triple::ppc:
+  case Triple::ppc64:
+    if (T.isOSDarwin())
+      return Triple::MachO;
+    return Triple::ELF;
+  }
+  llvm_unreachable("unknown architecture");
+}
+
+/// \brief Construct a triple from the string representation provided.
+///
+/// This stores the string representation and parses the various pieces into
+/// enum members.
+Triple::Triple(const Twine &Str)
+    : Data(Str.str()), Arch(UnknownArch), SubArch(NoSubArch),
+      Vendor(UnknownVendor), OS(UnknownOS), Environment(UnknownEnvironment),
+      ObjectFormat(UnknownObjectFormat) {
+  // Do minimal parsing by hand here.
+  SmallVector<StringRef, 4> Components;
+  StringRef(Data).split(Components, '-', /*MaxSplit*/ 3);
+  if (Components.size() > 0) {
+    Arch = parseArch(Components[0]);
+    SubArch = parseSubArch(Components[0]);
+    if (Components.size() > 1) {
+      Vendor = parseVendor(Components[1]);
+      if (Components.size() > 2) {
+        OS = parseOS(Components[2]);
+        if (Components.size() > 3) {
+          Environment = parseEnvironment(Components[3]);
+          ObjectFormat = parseFormat(Components[3]);
+        }
+      }
+    }
+  }
+  if (ObjectFormat == UnknownObjectFormat)
+    ObjectFormat = getDefaultFormat(*this);
+}
+
+/// \brief Construct a triple from string representations of the architecture,
+/// vendor, and OS.
+///
+/// This joins each argument into a canonical string representation and parses
+/// them into enum members. It leaves the environment unknown and omits it from
+/// the string representation.
+Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr)
+    : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()),
+      Arch(parseArch(ArchStr.str())),
+      SubArch(parseSubArch(ArchStr.str())),
+      Vendor(parseVendor(VendorStr.str())),
+      OS(parseOS(OSStr.str())),
+      Environment(), ObjectFormat(Triple::UnknownObjectFormat) {
+  ObjectFormat = getDefaultFormat(*this);
+}
+
+/// \brief Construct a triple from string representations of the architecture,
+/// vendor, OS, and environment.
+///
+/// This joins each argument into a canonical string representation and parses
+/// them into enum members.
+Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
+               const Twine &EnvironmentStr)
+    : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') +
+            EnvironmentStr).str()),
+      Arch(parseArch(ArchStr.str())),
+      SubArch(parseSubArch(ArchStr.str())),
+      Vendor(parseVendor(VendorStr.str())),
+      OS(parseOS(OSStr.str())),
+      Environment(parseEnvironment(EnvironmentStr.str())),
+      ObjectFormat(parseFormat(EnvironmentStr.str())) {
+  if (ObjectFormat == Triple::UnknownObjectFormat)
+    ObjectFormat = getDefaultFormat(*this);
+}
+
+std::string Triple::normalize(StringRef Str) {
+  bool IsMinGW32 = false;
+  bool IsCygwin = false;
+
+  // Parse into components.
+  SmallVector<StringRef, 4> Components;
+  Str.split(Components, '-');
+
+  // If the first component corresponds to a known architecture, preferentially
+  // use it for the architecture.  If the second component corresponds to a
+  // known vendor, preferentially use it for the vendor, etc.  This avoids silly
+  // component movement when a component parses as (eg) both a valid arch and a
+  // valid os.
+  ArchType Arch = UnknownArch;
+  if (Components.size() > 0)
+    Arch = parseArch(Components[0]);
+  VendorType Vendor = UnknownVendor;
+  if (Components.size() > 1)
+    Vendor = parseVendor(Components[1]);
+  OSType OS = UnknownOS;
+  if (Components.size() > 2) {
+    OS = parseOS(Components[2]);
+    IsCygwin = Components[2].startswith("cygwin");
+    IsMinGW32 = Components[2].startswith("mingw");
+  }
+  EnvironmentType Environment = UnknownEnvironment;
+  if (Components.size() > 3)
+    Environment = parseEnvironment(Components[3]);
+  ObjectFormatType ObjectFormat = UnknownObjectFormat;
+  if (Components.size() > 4)
+    ObjectFormat = parseFormat(Components[4]);
+
+  // Note which components are already in their final position.  These will not
+  // be moved.
+  bool Found[4];
+  Found[0] = Arch != UnknownArch;
+  Found[1] = Vendor != UnknownVendor;
+  Found[2] = OS != UnknownOS;
+  Found[3] = Environment != UnknownEnvironment;
+
+  // If they are not there already, permute the components into their canonical
+  // positions by seeing if they parse as a valid architecture, and if so moving
+  // the component to the architecture position etc.
+  for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) {
+    if (Found[Pos])
+      continue; // Already in the canonical position.
+
+    for (unsigned Idx = 0; Idx != Components.size(); ++Idx) {
+      // Do not reparse any components that already matched.
+      if (Idx < array_lengthof(Found) && Found[Idx])
+        continue;
+
+      // Does this component parse as valid for the target position?
+      bool Valid = false;
+      StringRef Comp = Components[Idx];
+      switch (Pos) {
+      default: llvm_unreachable("unexpected component type!");
+      case 0:
+        Arch = parseArch(Comp);
+        Valid = Arch != UnknownArch;
+        break;
+      case 1:
+        Vendor = parseVendor(Comp);
+        Valid = Vendor != UnknownVendor;
+        break;
+      case 2:
+        OS = parseOS(Comp);
+        IsCygwin = Comp.startswith("cygwin");
+        IsMinGW32 = Comp.startswith("mingw");
+        Valid = OS != UnknownOS || IsCygwin || IsMinGW32;
+        break;
+      case 3:
+        Environment = parseEnvironment(Comp);
+        Valid = Environment != UnknownEnvironment;
+        if (!Valid) {
+          ObjectFormat = parseFormat(Comp);
+          Valid = ObjectFormat != UnknownObjectFormat;
+        }
+        break;
+      }
+      if (!Valid)
+        continue; // Nope, try the next component.
+
+      // Move the component to the target position, pushing any non-fixed
+      // components that are in the way to the right.  This tends to give
+      // good results in the common cases of a forgotten vendor component
+      // or a wrongly positioned environment.
+      if (Pos < Idx) {
+        // Insert left, pushing the existing components to the right.  For
+        // example, a-b-i386 -> i386-a-b when moving i386 to the front.
+        StringRef CurrentComponent(""); // The empty component.
+        // Replace the component we are moving with an empty component.
+        std::swap(CurrentComponent, Components[Idx]);
+        // Insert the component being moved at Pos, displacing any existing
+        // components to the right.
+        for (unsigned i = Pos; !CurrentComponent.empty(); ++i) {
+          // Skip over any fixed components.
+          while (i < array_lengthof(Found) && Found[i])
+            ++i;
+          // Place the component at the new position, getting the component
+          // that was at this position - it will be moved right.
+          std::swap(CurrentComponent, Components[i]);
+        }
+      } else if (Pos > Idx) {
+        // Push right by inserting empty components until the component at Idx
+        // reaches the target position Pos.  For example, pc-a -> -pc-a when
+        // moving pc to the second position.
+        do {
+          // Insert one empty component at Idx.
+          StringRef CurrentComponent(""); // The empty component.
+          for (unsigned i = Idx; i < Components.size();) {
+            // Place the component at the new position, getting the component
+            // that was at this position - it will be moved right.
+            std::swap(CurrentComponent, Components[i]);
+            // If it was placed on top of an empty component then we are done.
+            if (CurrentComponent.empty())
+              break;
+            // Advance to the next component, skipping any fixed components.
+            while (++i < array_lengthof(Found) && Found[i])
+              ;
+          }
+          // The last component was pushed off the end - append it.
+          if (!CurrentComponent.empty())
+            Components.push_back(CurrentComponent);
+
+          // Advance Idx to the component's new position.
+          while (++Idx < array_lengthof(Found) && Found[Idx])
+            ;
+        } while (Idx < Pos); // Add more until the final position is reached.
+      }
+      assert(Pos < Components.size() && Components[Pos] == Comp &&
+             "Component moved wrong!");
+      Found[Pos] = true;
+      break;
+    }
+  }
+
+  // Special case logic goes here.  At this point Arch, Vendor and OS have the
+  // correct values for the computed components.
+  std::string NormalizedEnvironment;
+  if (Environment == Triple::Android && Components[3].startswith("androideabi")) {
+    StringRef AndroidVersion = Components[3].drop_front(strlen("androideabi"));
+    if (AndroidVersion.empty()) {
+      Components[3] = "android";
+    } else {
+      NormalizedEnvironment = Twine("android", AndroidVersion).str();
+      Components[3] = NormalizedEnvironment;
+    }
+  }
+
+  if (OS == Triple::Win32) {
+    Components.resize(4);
+    Components[2] = "windows";
+    if (Environment == UnknownEnvironment) {
+      if (ObjectFormat == UnknownObjectFormat || ObjectFormat == Triple::COFF)
+        Components[3] = "msvc";
+      else
+        Components[3] = getObjectFormatTypeName(ObjectFormat);
+    }
+  } else if (IsMinGW32) {
+    Components.resize(4);
+    Components[2] = "windows";
+    Components[3] = "gnu";
+  } else if (IsCygwin) {
+    Components.resize(4);
+    Components[2] = "windows";
+    Components[3] = "cygnus";
+  }
+  if (IsMinGW32 || IsCygwin ||
+      (OS == Triple::Win32 && Environment != UnknownEnvironment)) {
+    if (ObjectFormat != UnknownObjectFormat && ObjectFormat != Triple::COFF) {
+      Components.resize(5);
+      Components[4] = getObjectFormatTypeName(ObjectFormat);
+    }
+  }
+
+  // Stick the corrected components back together to form the normalized string.
+  std::string Normalized;
+  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
+    if (i) Normalized += '-';
+    Normalized += Components[i];
+  }
+  return Normalized;
+}
+
+StringRef Triple::getArchName() const {
+  return StringRef(Data).split('-').first;           // Isolate first component
+}
+
+StringRef Triple::getVendorName() const {
+  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
+  return Tmp.split('-').first;                       // Isolate second component
+}
+
+StringRef Triple::getOSName() const {
+  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
+  Tmp = Tmp.split('-').second;                       // Strip second component
+  return Tmp.split('-').first;                       // Isolate third component
+}
+
+StringRef Triple::getEnvironmentName() const {
+  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
+  Tmp = Tmp.split('-').second;                       // Strip second component
+  return Tmp.split('-').second;                      // Strip third component
+}
+
+StringRef Triple::getOSAndEnvironmentName() const {
+  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
+  return Tmp.split('-').second;                      // Strip second component
+}
+
+static unsigned EatNumber(StringRef &Str) {
+  assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
+  unsigned Result = 0;
+
+  do {
+    // Consume the leading digit.
+    Result = Result*10 + (Str[0] - '0');
+
+    // Eat the digit.
+    Str = Str.substr(1);
+  } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9');
+
+  return Result;
+}
+
+static void parseVersionFromName(StringRef Name, unsigned &Major,
+                                 unsigned &Minor, unsigned &Micro) {
+  // Any unset version defaults to 0.
+  Major = Minor = Micro = 0;
+
+  // Parse up to three components.
+  unsigned *Components[3] = {&Major, &Minor, &Micro};
+  for (unsigned i = 0; i != 3; ++i) {
+    if (Name.empty() || Name[0] < '0' || Name[0] > '9')
+      break;
+
+    // Consume the leading number.
+    *Components[i] = EatNumber(Name);
+
+    // Consume the separator, if present.
+    if (Name.startswith("."))
+      Name = Name.substr(1);
+  }
+}
+
+void Triple::getEnvironmentVersion(unsigned &Major, unsigned &Minor,
+                                   unsigned &Micro) const {
+  StringRef EnvironmentName = getEnvironmentName();
+  StringRef EnvironmentTypeName = getEnvironmentTypeName(getEnvironment());
+  if (EnvironmentName.startswith(EnvironmentTypeName))
+    EnvironmentName = EnvironmentName.substr(EnvironmentTypeName.size());
+
+  parseVersionFromName(EnvironmentName, Major, Minor, Micro);
+}
+
+void Triple::getOSVersion(unsigned &Major, unsigned &Minor,
+                          unsigned &Micro) const {
+  StringRef OSName = getOSName();
+  // Assume that the OS portion of the triple starts with the canonical name.
+  StringRef OSTypeName = getOSTypeName(getOS());
+  if (OSName.startswith(OSTypeName))
+    OSName = OSName.substr(OSTypeName.size());
+
+  parseVersionFromName(OSName, Major, Minor, Micro);
+}
+
+bool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor,
+                              unsigned &Micro) const {
+  getOSVersion(Major, Minor, Micro);
+
+  switch (getOS()) {
+  default: llvm_unreachable("unexpected OS for Darwin triple");
+  case Darwin:
+    // Default to darwin8, i.e., MacOSX 10.4.
+    if (Major == 0)
+      Major = 8;
+    // Darwin version numbers are skewed from OS X versions.
+    if (Major < 4)
+      return false;
+    Micro = 0;
+    Minor = Major - 4;
+    Major = 10;
+    break;
+  case MacOSX:
+    // Default to 10.4.
+    if (Major == 0) {
+      Major = 10;
+      Minor = 4;
+    }
+    if (Major != 10)
+      return false;
+    break;
+  case IOS:
+  case TvOS:
+  case WatchOS:
+    // Ignore the version from the triple.  This is only handled because the
+    // the clang driver combines OS X and IOS support into a common Darwin
+    // toolchain that wants to know the OS X version number even when targeting
+    // IOS.
+    Major = 10;
+    Minor = 4;
+    Micro = 0;
+    break;
+  }
+  return true;
+}
+
+void Triple::getiOSVersion(unsigned &Major, unsigned &Minor,
+                           unsigned &Micro) const {
+  switch (getOS()) {
+  default: llvm_unreachable("unexpected OS for Darwin triple");
+  case Darwin:
+  case MacOSX:
+    // Ignore the version from the triple.  This is only handled because the
+    // the clang driver combines OS X and IOS support into a common Darwin
+    // toolchain that wants to know the iOS version number even when targeting
+    // OS X.
+    Major = 5;
+    Minor = 0;
+    Micro = 0;
+    break;
+  case IOS:
+  case TvOS:
+    getOSVersion(Major, Minor, Micro);
+    // Default to 5.0 (or 7.0 for arm64).
+    if (Major == 0)
+      Major = (getArch() == aarch64) ? 7 : 5;
+    break;
+  case WatchOS:
+    llvm_unreachable("conflicting triple info");
+  }
+}
+
+void Triple::getWatchOSVersion(unsigned &Major, unsigned &Minor,
+                               unsigned &Micro) const {
+  switch (getOS()) {
+  default: llvm_unreachable("unexpected OS for Darwin triple");
+  case Darwin:
+  case MacOSX:
+    // Ignore the version from the triple.  This is only handled because the
+    // the clang driver combines OS X and IOS support into a common Darwin
+    // toolchain that wants to know the iOS version number even when targeting
+    // OS X.
+    Major = 2;
+    Minor = 0;
+    Micro = 0;
+    break;
+  case WatchOS:
+    getOSVersion(Major, Minor, Micro);
+    if (Major == 0)
+      Major = 2;
+    break;
+  case IOS:
+    llvm_unreachable("conflicting triple info");
+  }
+}
+
+void Triple::setTriple(const Twine &Str) {
+  *this = Triple(Str);
+}
+
+void Triple::setArch(ArchType Kind) {
+  setArchName(getArchTypeName(Kind));
+}
+
+void Triple::setVendor(VendorType Kind) {
+  setVendorName(getVendorTypeName(Kind));
+}
+
+void Triple::setOS(OSType Kind) {
+  setOSName(getOSTypeName(Kind));
+}
+
+void Triple::setEnvironment(EnvironmentType Kind) {
+  if (ObjectFormat == getDefaultFormat(*this))
+    return setEnvironmentName(getEnvironmentTypeName(Kind));
+
+  setEnvironmentName((getEnvironmentTypeName(Kind) + Twine("-") +
+                      getObjectFormatTypeName(ObjectFormat)).str());
+}
+
+void Triple::setObjectFormat(ObjectFormatType Kind) {
+  if (Environment == UnknownEnvironment)
+    return setEnvironmentName(getObjectFormatTypeName(Kind));
+
+  setEnvironmentName((getEnvironmentTypeName(Environment) + Twine("-") +
+                      getObjectFormatTypeName(Kind)).str());
+}
+
+void Triple::setArchName(StringRef Str) {
+  // Work around a miscompilation bug for Twines in gcc 4.0.3.
+  SmallString<64> Triple;
+  Triple += Str;
+  Triple += "-";
+  Triple += getVendorName();
+  Triple += "-";
+  Triple += getOSAndEnvironmentName();
+  setTriple(Triple);
+}
+
+void Triple::setVendorName(StringRef Str) {
+  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
+}
+
+void Triple::setOSName(StringRef Str) {
+  if (hasEnvironment())
+    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
+              "-" + getEnvironmentName());
+  else
+    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
+}
+
+void Triple::setEnvironmentName(StringRef Str) {
+  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
+            "-" + Str);
+}
+
+void Triple::setOSAndEnvironmentName(StringRef Str) {
+  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
+}
+
+static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
+  switch (Arch) {
+  case llvm::Triple::UnknownArch:
+    return 0;
+
+  case llvm::Triple::avr:
+  case llvm::Triple::msp430:
+    return 16;
+
+  case llvm::Triple::arm:
+  case llvm::Triple::armeb:
+  case llvm::Triple::hexagon:
+  case llvm::Triple::le32:
+  case llvm::Triple::mips:
+  case llvm::Triple::mipsel:
+  case llvm::Triple::nvptx:
+  case llvm::Triple::ppc:
+  case llvm::Triple::r600:
+  case llvm::Triple::sparc:
+  case llvm::Triple::sparcel:
+  case llvm::Triple::tce:
+  case llvm::Triple::thumb:
+  case llvm::Triple::thumbeb:
+  case llvm::Triple::x86:
+  case llvm::Triple::xcore:
+  case llvm::Triple::amdil:
+  case llvm::Triple::hsail:
+  case llvm::Triple::spir:
+  case llvm::Triple::kalimba:
+  case llvm::Triple::lanai:
+  case llvm::Triple::shave:
+  case llvm::Triple::wasm32:
+  case llvm::Triple::renderscript32:
+    return 32;
+
+  case llvm::Triple::aarch64:
+  case llvm::Triple::aarch64_be:
+  case llvm::Triple::amdgcn:
+  case llvm::Triple::bpfel:
+  case llvm::Triple::bpfeb:
+  case llvm::Triple::le64:
+  case llvm::Triple::mips64:
+  case llvm::Triple::mips64el:
+  case llvm::Triple::nvptx64:
+  case llvm::Triple::ppc64:
+  case llvm::Triple::ppc64le:
+  case llvm::Triple::sparcv9:
+  case llvm::Triple::systemz:
+  case llvm::Triple::x86_64:
+  case llvm::Triple::amdil64:
+  case llvm::Triple::hsail64:
+  case llvm::Triple::spir64:
+  case llvm::Triple::wasm64:
+  case llvm::Triple::renderscript64:
+    return 64;
+  }
+  llvm_unreachable("Invalid architecture value");
+}
+
+bool Triple::isArch64Bit() const {
+  return getArchPointerBitWidth(getArch()) == 64;
+}
+
+bool Triple::isArch32Bit() const {
+  return getArchPointerBitWidth(getArch()) == 32;
+}
+
+bool Triple::isArch16Bit() const {
+  return getArchPointerBitWidth(getArch()) == 16;
+}
+
+Triple Triple::get32BitArchVariant() const {
+  Triple T(*this);
+  switch (getArch()) {
+  case Triple::UnknownArch:
+  case Triple::amdgcn:
+  case Triple::avr:
+  case Triple::bpfel:
+  case Triple::bpfeb:
+  case Triple::msp430:
+  case Triple::systemz:
+  case Triple::ppc64le:
+    T.setArch(UnknownArch);
+    break;
+
+  case Triple::amdil:
+  case Triple::hsail:
+  case Triple::spir:
+  case Triple::arm:
+  case Triple::armeb:
+  case Triple::hexagon:
+  case Triple::kalimba:
+  case Triple::le32:
+  case Triple::mips:
+  case Triple::mipsel:
+  case Triple::nvptx:
+  case Triple::ppc:
+  case Triple::r600:
+  case Triple::sparc:
+  case Triple::sparcel:
+  case Triple::tce:
+  case Triple::thumb:
+  case Triple::thumbeb:
+  case Triple::x86:
+  case Triple::xcore:
+  case Triple::lanai:
+  case Triple::shave:
+  case Triple::wasm32:
+  case Triple::renderscript32:
+    // Already 32-bit.
+    break;
+
+  case Triple::aarch64:        T.setArch(Triple::arm);     break;
+  case Triple::aarch64_be:     T.setArch(Triple::armeb);   break;
+  case Triple::le64:           T.setArch(Triple::le32);    break;
+  case Triple::mips64:         T.setArch(Triple::mips);    break;
+  case Triple::mips64el:       T.setArch(Triple::mipsel);  break;
+  case Triple::nvptx64:        T.setArch(Triple::nvptx);   break;
+  case Triple::ppc64:          T.setArch(Triple::ppc);     break;
+  case Triple::sparcv9:        T.setArch(Triple::sparc);   break;
+  case Triple::x86_64:         T.setArch(Triple::x86);     break;
+  case Triple::amdil64:        T.setArch(Triple::amdil);   break;
+  case Triple::hsail64:        T.setArch(Triple::hsail);   break;
+  case Triple::spir64:         T.setArch(Triple::spir);    break;
+  case Triple::wasm64:         T.setArch(Triple::wasm32);  break;
+  case Triple::renderscript64: T.setArch(Triple::renderscript32); break;
+  }
+  return T;
+}
+
+Triple Triple::get64BitArchVariant() const {
+  Triple T(*this);
+  switch (getArch()) {
+  case Triple::UnknownArch:
+  case Triple::avr:
+  case Triple::hexagon:
+  case Triple::kalimba:
+  case Triple::lanai:
+  case Triple::msp430:
+  case Triple::r600:
+  case Triple::tce:
+  case Triple::xcore:
+  case Triple::sparcel:
+  case Triple::shave:
+    T.setArch(UnknownArch);
+    break;
+
+  case Triple::aarch64:
+  case Triple::aarch64_be:
+  case Triple::bpfel:
+  case Triple::bpfeb:
+  case Triple::le64:
+  case Triple::amdil64:
+  case Triple::amdgcn:
+  case Triple::hsail64:
+  case Triple::spir64:
+  case Triple::mips64:
+  case Triple::mips64el:
+  case Triple::nvptx64:
+  case Triple::ppc64:
+  case Triple::ppc64le:
+  case Triple::sparcv9:
+  case Triple::systemz:
+  case Triple::x86_64:
+  case Triple::wasm64:
+  case Triple::renderscript64:
+    // Already 64-bit.
+    break;
+
+  case Triple::arm:             T.setArch(Triple::aarch64);    break;
+  case Triple::armeb:           T.setArch(Triple::aarch64_be); break;
+  case Triple::le32:            T.setArch(Triple::le64);       break;
+  case Triple::mips:            T.setArch(Triple::mips64);     break;
+  case Triple::mipsel:          T.setArch(Triple::mips64el);   break;
+  case Triple::nvptx:           T.setArch(Triple::nvptx64);    break;
+  case Triple::ppc:             T.setArch(Triple::ppc64);      break;
+  case Triple::sparc:           T.setArch(Triple::sparcv9);    break;
+  case Triple::x86:             T.setArch(Triple::x86_64);     break;
+  case Triple::amdil:           T.setArch(Triple::amdil64);    break;
+  case Triple::hsail:           T.setArch(Triple::hsail64);    break;
+  case Triple::spir:            T.setArch(Triple::spir64);     break;
+  case Triple::thumb:           T.setArch(Triple::aarch64);    break;
+  case Triple::thumbeb:         T.setArch(Triple::aarch64_be); break;
+  case Triple::wasm32:          T.setArch(Triple::wasm64);     break;
+  case Triple::renderscript32:  T.setArch(Triple::renderscript64);     break;
+  }
+  return T;
+}
+
+Triple Triple::getBigEndianArchVariant() const {
+  Triple T(*this);
+  // Already big endian.
+  if (!isLittleEndian())
+    return T;
+  switch (getArch()) {
+  case Triple::UnknownArch:
+  case Triple::amdgcn:
+  case Triple::amdil64:
+  case Triple::amdil:
+  case Triple::avr:
+  case Triple::hexagon:
+  case Triple::hsail64:
+  case Triple::hsail:
+  case Triple::kalimba:
+  case Triple::le32:
+  case Triple::le64:
+  case Triple::msp430:
+  case Triple::nvptx64:
+  case Triple::nvptx:
+  case Triple::r600:
+  case Triple::shave:
+  case Triple::spir64:
+  case Triple::spir:
+  case Triple::wasm32:
+  case Triple::wasm64:
+  case Triple::x86:
+  case Triple::x86_64:
+  case Triple::xcore:
+  case Triple::renderscript32:
+  case Triple::renderscript64:
+
+  // ARM is intentionally unsupported here, changing the architecture would
+  // drop any arch suffixes.
+  case Triple::arm:
+  case Triple::thumb:
+    T.setArch(UnknownArch);
+    break;
+
+  case Triple::aarch64: T.setArch(Triple::aarch64_be); break;
+  case Triple::bpfel:   T.setArch(Triple::bpfeb);      break;
+  case Triple::mips64el:T.setArch(Triple::mips64);     break;
+  case Triple::mipsel:  T.setArch(Triple::mips);       break;
+  case Triple::ppc64le: T.setArch(Triple::ppc64);      break;
+  case Triple::sparcel: T.setArch(Triple::sparc);      break;
+  default:
+    llvm_unreachable("getBigEndianArchVariant: unknown triple.");
+  }
+  return T;
+}
+
+Triple Triple::getLittleEndianArchVariant() const {
+  Triple T(*this);
+  if (isLittleEndian())
+    return T;
+
+  switch (getArch()) {
+  case Triple::UnknownArch:
+  case Triple::lanai:
+  case Triple::ppc:
+  case Triple::sparcv9:
+  case Triple::systemz:
+  case Triple::tce:
+
+  // ARM is intentionally unsupported here, changing the architecture would
+  // drop any arch suffixes.
+  case Triple::armeb:
+  case Triple::thumbeb:
+    T.setArch(UnknownArch);
+    break;
+
+  case Triple::aarch64_be: T.setArch(Triple::aarch64);  break;
+  case Triple::bpfeb:      T.setArch(Triple::bpfel);    break;
+  case Triple::mips64:     T.setArch(Triple::mips64el); break;
+  case Triple::mips:       T.setArch(Triple::mipsel);   break;
+  case Triple::ppc64:      T.setArch(Triple::ppc64le);  break;
+  case Triple::sparc:      T.setArch(Triple::sparcel);  break;
+  default:
+    llvm_unreachable("getLittleEndianArchVariant: unknown triple.");
+  }
+  return T;
+}
+
+bool Triple::isLittleEndian() const {
+  switch (getArch()) {
+  case Triple::aarch64:
+  case Triple::amdgcn:
+  case Triple::amdil64:
+  case Triple::amdil:
+  case Triple::arm:
+  case Triple::avr:
+  case Triple::bpfel:
+  case Triple::hexagon:
+  case Triple::hsail64:
+  case Triple::hsail:
+  case Triple::kalimba:
+  case Triple::le32:
+  case Triple::le64:
+  case Triple::mips64el:
+  case Triple::mipsel:
+  case Triple::msp430:
+  case Triple::nvptx64:
+  case Triple::nvptx:
+  case Triple::ppc64le:
+  case Triple::r600:
+  case Triple::shave:
+  case Triple::sparcel:
+  case Triple::spir64:
+  case Triple::spir:
+  case Triple::thumb:
+  case Triple::wasm32:
+  case Triple::wasm64:
+  case Triple::x86:
+  case Triple::x86_64:
+  case Triple::xcore:
+  case Triple::renderscript32:
+  case Triple::renderscript64:
+    return true;
+  default:
+    return false;
+  }
+}
+
+StringRef Triple::getARMCPUForArch(StringRef MArch) const {
+  if (MArch.empty())
+    MArch = getArchName();
+  MArch = ARM::getCanonicalArchName(MArch);
+
+  // Some defaults are forced.
+  switch (getOS()) {
+  case llvm::Triple::FreeBSD:
+  case llvm::Triple::NetBSD:
+    if (!MArch.empty() && MArch == "v6")
+      return "arm1176jzf-s";
+    break;
+  case llvm::Triple::Win32:
+    // FIXME: this is invalid for WindowsCE
+    return "cortex-a9";
+  case llvm::Triple::MacOSX:
+  case llvm::Triple::IOS:
+  case llvm::Triple::WatchOS:
+  case llvm::Triple::TvOS:
+    if (MArch == "v7k")
+      return "cortex-a7";
+    break;
+  default:
+    break;
+  }
+
+  if (MArch.empty())
+    return StringRef();
+
+  StringRef CPU = ARM::getDefaultCPU(MArch);
+  if (!CPU.empty())
+    return CPU;
+
+  // If no specific architecture version is requested, return the minimum CPU
+  // required by the OS and environment.
+  switch (getOS()) {
+  case llvm::Triple::NetBSD:
+    switch (getEnvironment()) {
+    case llvm::Triple::GNUEABIHF:
+    case llvm::Triple::GNUEABI:
+    case llvm::Triple::EABIHF:
+    case llvm::Triple::EABI:
+      return "arm926ej-s";
+    default:
+      return "strongarm";
+    }
+  case llvm::Triple::NaCl:
+    return "cortex-a8";
+  default:
+    switch (getEnvironment()) {
+    case llvm::Triple::EABIHF:
+    case llvm::Triple::GNUEABIHF:
+    case llvm::Triple::MuslEABIHF:
+      return "arm1176jzf-s";
+    default:
+      return "arm7tdmi";
+    }
+  }
+
+  llvm_unreachable("invalid arch name");
+}
diff --git a/third_party/llvm-subzero/lib/Support/Twine.cpp b/third_party/llvm-subzero/lib/Support/Twine.cpp
new file mode 100644
index 0000000..5e989fb
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Twine.cpp
@@ -0,0 +1,170 @@
+//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+std::string Twine::str() const {
+  // If we're storing only a std::string, just return it.
+  if (LHSKind == StdStringKind && RHSKind == EmptyKind)
+    return *LHS.stdString;
+
+  // Otherwise, flatten and copy the contents first.
+  SmallString<256> Vec;
+  return toStringRef(Vec).str();
+}
+
+void Twine::toVector(SmallVectorImpl<char> &Out) const {
+  raw_svector_ostream OS(Out);
+  print(OS);
+}
+
+StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
+  if (isUnary()) {
+    switch (getLHSKind()) {
+    case CStringKind:
+      // Already null terminated, yay!
+      return StringRef(LHS.cString);
+    case StdStringKind: {
+      const std::string *str = LHS.stdString;
+      return StringRef(str->c_str(), str->size());
+    }
+    default:
+      break;
+    }
+  }
+  toVector(Out);
+  Out.push_back(0);
+  Out.pop_back();
+  return StringRef(Out.data(), Out.size());
+}
+
+void Twine::printOneChild(raw_ostream &OS, Child Ptr,
+                          NodeKind Kind) const {
+  switch (Kind) {
+  case Twine::NullKind: break;
+  case Twine::EmptyKind: break;
+  case Twine::TwineKind:
+    Ptr.twine->print(OS);
+    break;
+  case Twine::CStringKind:
+    OS << Ptr.cString;
+    break;
+  case Twine::StdStringKind:
+    OS << *Ptr.stdString;
+    break;
+  case Twine::StringRefKind:
+    OS << *Ptr.stringRef;
+    break;
+  case Twine::SmallStringKind:
+    OS << *Ptr.smallString;
+    break;
+  case Twine::CharKind:
+    OS << Ptr.character;
+    break;
+  case Twine::DecUIKind:
+    OS << Ptr.decUI;
+    break;
+  case Twine::DecIKind:
+    OS << Ptr.decI;
+    break;
+  case Twine::DecULKind:
+    OS << *Ptr.decUL;
+    break;
+  case Twine::DecLKind:
+    OS << *Ptr.decL;
+    break;
+  case Twine::DecULLKind:
+    OS << *Ptr.decULL;
+    break;
+  case Twine::DecLLKind:
+    OS << *Ptr.decLL;
+    break;
+  case Twine::UHexKind:
+    OS.write_hex(*Ptr.uHex);
+    break;
+  }
+}
+
+void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
+                              NodeKind Kind) const {
+  switch (Kind) {
+  case Twine::NullKind:
+    OS << "null"; break;
+  case Twine::EmptyKind:
+    OS << "empty"; break;
+  case Twine::TwineKind:
+    OS << "rope:";
+    Ptr.twine->printRepr(OS);
+    break;
+  case Twine::CStringKind:
+    OS << "cstring:\""
+       << Ptr.cString << "\"";
+    break;
+  case Twine::StdStringKind:
+    OS << "std::string:\""
+       << Ptr.stdString << "\"";
+    break;
+  case Twine::StringRefKind:
+    OS << "stringref:\""
+       << Ptr.stringRef << "\"";
+    break;
+  case Twine::SmallStringKind:
+    OS << "smallstring:\"" << *Ptr.smallString << "\"";
+    break;
+  case Twine::CharKind:
+    OS << "char:\"" << Ptr.character << "\"";
+    break;
+  case Twine::DecUIKind:
+    OS << "decUI:\"" << Ptr.decUI << "\"";
+    break;
+  case Twine::DecIKind:
+    OS << "decI:\"" << Ptr.decI << "\"";
+    break;
+  case Twine::DecULKind:
+    OS << "decUL:\"" << *Ptr.decUL << "\"";
+    break;
+  case Twine::DecLKind:
+    OS << "decL:\"" << *Ptr.decL << "\"";
+    break;
+  case Twine::DecULLKind:
+    OS << "decULL:\"" << *Ptr.decULL << "\"";
+    break;
+  case Twine::DecLLKind:
+    OS << "decLL:\"" << *Ptr.decLL << "\"";
+    break;
+  case Twine::UHexKind:
+    OS << "uhex:\"" << Ptr.uHex << "\"";
+    break;
+  }
+}
+
+void Twine::print(raw_ostream &OS) const {
+  printOneChild(OS, LHS, getLHSKind());
+  printOneChild(OS, RHS, getRHSKind());
+}
+
+void Twine::printRepr(raw_ostream &OS) const {
+  OS << "(Twine ";
+  printOneChildRepr(OS, LHS, getLHSKind());
+  OS << " ";
+  printOneChildRepr(OS, RHS, getRHSKind());
+  OS << ")";
+}
+
+LLVM_DUMP_METHOD void Twine::dump() const {
+  print(dbgs());
+}
+
+void Twine::dumpRepr() const {
+  printRepr(dbgs());
+}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Host.inc b/third_party/llvm-subzero/lib/Support/Windows/Host.inc
new file mode 100644
index 0000000..fe89fe0
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/Host.inc
@@ -0,0 +1,22 @@
+//===- llvm/Support/Win32/Host.inc ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 Host support.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WindowsSupport.h"
+#include <cstdio>
+#include <string>
+
+using namespace llvm;
+
+std::string sys::getDefaultTargetTriple() {
+  return Triple::normalize(LLVM_DEFAULT_TARGET_TRIPLE);
+}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Mutex.inc b/third_party/llvm-subzero/lib/Support/Windows/Mutex.inc
new file mode 100644
index 0000000..ab79d07
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/Mutex.inc
@@ -0,0 +1,58 @@
+//===- llvm/Support/Win32/Mutex.inc - Win32 Mutex Implementation -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 specific (non-pthread) Mutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//===          is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "WindowsSupport.h"
+#include "llvm/Support/Mutex.h"
+
+namespace llvm {
+using namespace sys;
+
+MutexImpl::MutexImpl(bool /*recursive*/)
+{
+  data_ = new CRITICAL_SECTION;
+  InitializeCriticalSection((LPCRITICAL_SECTION)data_);
+}
+
+MutexImpl::~MutexImpl()
+{
+  DeleteCriticalSection((LPCRITICAL_SECTION)data_);
+  delete (LPCRITICAL_SECTION)data_;
+  data_ = 0;
+}
+
+bool
+MutexImpl::acquire()
+{
+  EnterCriticalSection((LPCRITICAL_SECTION)data_);
+  return true;
+}
+
+bool
+MutexImpl::release()
+{
+  LeaveCriticalSection((LPCRITICAL_SECTION)data_);
+  return true;
+}
+
+bool
+MutexImpl::tryacquire()
+{
+  return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
+}
+
+}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Path.inc b/third_party/llvm-subzero/lib/Support/Windows/Path.inc
new file mode 100644
index 0000000..fab6aec
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/Path.inc
@@ -0,0 +1,989 @@
+//===- llvm/Support/Windows/Path.inc - Windows Path Impl --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Windows specific implementation of the Path API.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Windows code that
+//===          is guaranteed to work on *all* Windows variants.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/WindowsError.h"
+#include <fcntl.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// These two headers must be included last, and make sure shlobj is required
+// after Windows.h to make sure it picks up our definition of _WIN32_WINNT
+#include "WindowsSupport.h"
+#include <shlobj.h>
+
+#undef max
+
+// MinGW doesn't define this.
+#ifndef _ERRNO_T_DEFINED
+#define _ERRNO_T_DEFINED
+typedef int errno_t;
+#endif
+
+#ifdef _MSC_VER
+# pragma comment(lib, "advapi32.lib")  // This provides CryptAcquireContextW.
+# pragma comment(lib, "ole32.lib")     // This provides CoTaskMemFree
+#endif
+
+using namespace llvm;
+
+using llvm::sys::windows::UTF8ToUTF16;
+using llvm::sys::windows::UTF16ToUTF8;
+using llvm::sys::path::widenPath;
+
+static bool is_separator(const wchar_t value) {
+  switch (value) {
+  case L'\\':
+  case L'/':
+    return true;
+  default:
+    return false;
+  }
+}
+
+namespace llvm {
+namespace sys  {
+namespace path {
+
+// Convert a UTF-8 path to UTF-16.  Also, if the absolute equivalent of the
+// path is longer than CreateDirectory can tolerate, make it absolute and
+// prefixed by '\\?\'.
+std::error_code widenPath(const Twine &Path8,
+                          SmallVectorImpl<wchar_t> &Path16) {
+  const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename.
+
+  // Several operations would convert Path8 to SmallString; more efficient to
+  // do it once up front.
+  SmallString<128> Path8Str;
+  Path8.toVector(Path8Str);
+
+  // If we made this path absolute, how much longer would it get?
+  size_t CurPathLen;
+  if (llvm::sys::path::is_absolute(Twine(Path8Str)))
+    CurPathLen = 0; // No contribution from current_path needed.
+  else {
+    CurPathLen = ::GetCurrentDirectoryW(0, NULL);
+    if (CurPathLen == 0)
+      return mapWindowsError(::GetLastError());
+  }
+
+  // Would the absolute path be longer than our limit?
+  if ((Path8Str.size() + CurPathLen) >= MaxDirLen &&
+      !Path8Str.startswith("\\\\?\\")) {
+    SmallString<2*MAX_PATH> FullPath("\\\\?\\");
+    if (CurPathLen) {
+      SmallString<80> CurPath;
+      if (std::error_code EC = llvm::sys::fs::current_path(CurPath))
+        return EC;
+      FullPath.append(CurPath);
+    }
+    // Traverse the requested path, canonicalizing . and .. as we go (because
+    // the \\?\ prefix is documented to treat them as real components).
+    // The iterators don't report separators and append() always attaches
+    // preferred_separator so we don't need to call native() on the result.
+    for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str),
+                                         E = llvm::sys::path::end(Path8Str);
+                                         I != E; ++I) {
+      if (I->size() == 1 && *I == ".")
+        continue;
+      if (I->size() == 2 && *I == "..")
+        llvm::sys::path::remove_filename(FullPath);
+      else
+        llvm::sys::path::append(FullPath, *I);
+    }
+    return UTF8ToUTF16(FullPath, Path16);
+  }
+
+  // Just use the caller's original path.
+  return UTF8ToUTF16(Path8Str, Path16);
+}
+} // end namespace path
+
+namespace fs {
+
+std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
+  SmallVector<wchar_t, MAX_PATH> PathName;
+  DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.capacity());
+
+  // A zero return value indicates a failure other than insufficient space.
+  if (Size == 0)
+    return "";
+
+  // Insufficient space is determined by a return value equal to the size of
+  // the buffer passed in.
+  if (Size == PathName.capacity())
+    return "";
+
+  // On success, GetModuleFileNameW returns the number of characters written to
+  // the buffer not including the NULL terminator.
+  PathName.set_size(Size);
+
+  // Convert the result from UTF-16 to UTF-8.
+  SmallVector<char, MAX_PATH> PathNameUTF8;
+  if (UTF16ToUTF8(PathName.data(), PathName.size(), PathNameUTF8))
+    return "";
+
+  return std::string(PathNameUTF8.data());
+}
+
+UniqueID file_status::getUniqueID() const {
+  // The file is uniquely identified by the volume serial number along
+  // with the 64-bit file identifier.
+  uint64_t FileID = (static_cast<uint64_t>(FileIndexHigh) << 32ULL) |
+                    static_cast<uint64_t>(FileIndexLow);
+
+  return UniqueID(VolumeSerialNumber, FileID);
+}
+
+ErrorOr<space_info> disk_space(const Twine &Path) {
+  ULARGE_INTEGER Avail, Total, Free;
+  if (!::GetDiskFreeSpaceExA(Path.str().c_str(), &Avail, &Total, &Free))
+    return mapWindowsError(::GetLastError());
+  space_info SpaceInfo;
+  SpaceInfo.capacity =
+      (static_cast<uint64_t>(Total.HighPart) << 32) + Total.LowPart;
+  SpaceInfo.free = (static_cast<uint64_t>(Free.HighPart) << 32) + Free.LowPart;
+  SpaceInfo.available =
+      (static_cast<uint64_t>(Avail.HighPart) << 32) + Avail.LowPart;
+  return SpaceInfo;
+}
+
+TimeValue file_status::getLastAccessedTime() const {
+  ULARGE_INTEGER UI;
+  UI.LowPart = LastAccessedTimeLow;
+  UI.HighPart = LastAccessedTimeHigh;
+
+  TimeValue Ret;
+  Ret.fromWin32Time(UI.QuadPart);
+  return Ret;
+}
+
+TimeValue file_status::getLastModificationTime() const {
+  ULARGE_INTEGER UI;
+  UI.LowPart = LastWriteTimeLow;
+  UI.HighPart = LastWriteTimeHigh;
+
+  TimeValue Ret;
+  Ret.fromWin32Time(UI.QuadPart);
+  return Ret;
+}
+
+std::error_code current_path(SmallVectorImpl<char> &result) {
+  SmallVector<wchar_t, MAX_PATH> cur_path;
+  DWORD len = MAX_PATH;
+
+  do {
+    cur_path.reserve(len);
+    len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data());
+
+    // A zero return value indicates a failure other than insufficient space.
+    if (len == 0)
+      return mapWindowsError(::GetLastError());
+
+    // If there's insufficient space, the len returned is larger than the len
+    // given.
+  } while (len > cur_path.capacity());
+
+  // On success, GetCurrentDirectoryW returns the number of characters not
+  // including the null-terminator.
+  cur_path.set_size(len);
+  return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result);
+}
+
+std::error_code create_directory(const Twine &path, bool IgnoreExisting,
+                                 perms Perms) {
+  SmallVector<wchar_t, 128> path_utf16;
+
+  if (std::error_code ec = widenPath(path, path_utf16))
+    return ec;
+
+  if (!::CreateDirectoryW(path_utf16.begin(), NULL)) {
+    DWORD LastError = ::GetLastError();
+    if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting)
+      return mapWindowsError(LastError);
+  }
+
+  return std::error_code();
+}
+
+// We can't use symbolic links for windows.
+std::error_code create_link(const Twine &to, const Twine &from) {
+  // Convert to utf-16.
+  SmallVector<wchar_t, 128> wide_from;
+  SmallVector<wchar_t, 128> wide_to;
+  if (std::error_code ec = widenPath(from, wide_from))
+    return ec;
+  if (std::error_code ec = widenPath(to, wide_to))
+    return ec;
+
+  if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL))
+    return mapWindowsError(::GetLastError());
+
+  return std::error_code();
+}
+
+std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
+  SmallVector<wchar_t, 128> path_utf16;
+
+  file_status ST;
+  if (std::error_code EC = status(path, ST)) {
+    if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
+      return EC;
+    return std::error_code();
+  }
+
+  if (std::error_code ec = widenPath(path, path_utf16))
+    return ec;
+
+  if (ST.type() == file_type::directory_file) {
+    if (!::RemoveDirectoryW(c_str(path_utf16))) {
+      std::error_code EC = mapWindowsError(::GetLastError());
+      if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
+        return EC;
+    }
+    return std::error_code();
+  }
+  if (!::DeleteFileW(c_str(path_utf16))) {
+    std::error_code EC = mapWindowsError(::GetLastError());
+    if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
+      return EC;
+  }
+  return std::error_code();
+}
+
+std::error_code rename(const Twine &from, const Twine &to) {
+  // Convert to utf-16.
+  SmallVector<wchar_t, 128> wide_from;
+  SmallVector<wchar_t, 128> wide_to;
+  if (std::error_code ec = widenPath(from, wide_from))
+    return ec;
+  if (std::error_code ec = widenPath(to, wide_to))
+    return ec;
+
+  std::error_code ec = std::error_code();
+
+  // Retry while we see recoverable errors.
+  // System scanners (eg. indexer) might open the source file when it is written
+  // and closed.
+
+  bool TryReplace = true;
+
+  for (int i = 0; i < 2000; i++) {
+    if (i > 0)
+      ::Sleep(1);
+
+    if (TryReplace) {
+      // Try ReplaceFile first, as it is able to associate a new data stream
+      // with the destination even if the destination file is currently open.
+      if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL))
+        return std::error_code();
+
+      DWORD ReplaceError = ::GetLastError();
+      ec = mapWindowsError(ReplaceError);
+
+      // If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or
+      // ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW().
+      if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT ||
+          ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) {
+        TryReplace = false;
+        continue;
+      }
+      // If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry
+      // using ReplaceFileW().
+      if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED)
+        continue;
+      // We get ERROR_FILE_NOT_FOUND if the destination file is missing.
+      // MoveFileEx can handle this case.
+      if (ReplaceError != ERROR_ACCESS_DENIED &&
+          ReplaceError != ERROR_FILE_NOT_FOUND &&
+          ReplaceError != ERROR_SHARING_VIOLATION)
+        break;
+    }
+
+    if (::MoveFileExW(wide_from.begin(), wide_to.begin(),
+                      MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
+      return std::error_code();
+
+    DWORD MoveError = ::GetLastError();
+    ec = mapWindowsError(MoveError);
+    if (MoveError != ERROR_ACCESS_DENIED) break;
+  }
+
+  return ec;
+}
+
+std::error_code resize_file(int FD, uint64_t Size) {
+#ifdef HAVE__CHSIZE_S
+  errno_t error = ::_chsize_s(FD, Size);
+#else
+  errno_t error = ::_chsize(FD, Size);
+#endif
+  return std::error_code(error, std::generic_category());
+}
+
+std::error_code access(const Twine &Path, AccessMode Mode) {
+  SmallVector<wchar_t, 128> PathUtf16;
+
+  if (std::error_code EC = widenPath(Path, PathUtf16))
+    return EC;
+
+  DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin());
+
+  if (Attributes == INVALID_FILE_ATTRIBUTES) {
+    // See if the file didn't actually exist.
+    DWORD LastError = ::GetLastError();
+    if (LastError != ERROR_FILE_NOT_FOUND &&
+        LastError != ERROR_PATH_NOT_FOUND)
+      return mapWindowsError(LastError);
+    return errc::no_such_file_or_directory;
+  }
+
+  if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY))
+    return errc::permission_denied;
+
+  return std::error_code();
+}
+
+bool can_execute(const Twine &Path) {
+  return !access(Path, AccessMode::Execute) ||
+         !access(Path + ".exe", AccessMode::Execute);
+}
+
+bool equivalent(file_status A, file_status B) {
+  assert(status_known(A) && status_known(B));
+  return A.FileIndexHigh         == B.FileIndexHigh &&
+         A.FileIndexLow          == B.FileIndexLow &&
+         A.FileSizeHigh          == B.FileSizeHigh &&
+         A.FileSizeLow           == B.FileSizeLow &&
+         A.LastAccessedTimeHigh  == B.LastAccessedTimeHigh &&
+         A.LastAccessedTimeLow   == B.LastAccessedTimeLow &&
+         A.LastWriteTimeHigh     == B.LastWriteTimeHigh &&
+         A.LastWriteTimeLow      == B.LastWriteTimeLow &&
+         A.VolumeSerialNumber    == B.VolumeSerialNumber;
+}
+
+std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
+  file_status fsA, fsB;
+  if (std::error_code ec = status(A, fsA))
+    return ec;
+  if (std::error_code ec = status(B, fsB))
+    return ec;
+  result = equivalent(fsA, fsB);
+  return std::error_code();
+}
+
+static bool isReservedName(StringRef path) {
+  // This list of reserved names comes from MSDN, at:
+  // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
+  static const char *const sReservedNames[] = { "nul", "con", "prn", "aux",
+                                                "com1", "com2", "com3", "com4",
+                                                "com5", "com6", "com7", "com8",
+                                                "com9", "lpt1", "lpt2", "lpt3",
+                                                "lpt4", "lpt5", "lpt6", "lpt7",
+                                                "lpt8", "lpt9" };
+
+  // First, check to see if this is a device namespace, which always
+  // starts with \\.\, since device namespaces are not legal file paths.
+  if (path.startswith("\\\\.\\"))
+    return true;
+
+  // Then compare against the list of ancient reserved names.
+  for (size_t i = 0; i < array_lengthof(sReservedNames); ++i) {
+    if (path.equals_lower(sReservedNames[i]))
+      return true;
+  }
+
+  // The path isn't what we consider reserved.
+  return false;
+}
+
+static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
+  if (FileHandle == INVALID_HANDLE_VALUE)
+    goto handle_status_error;
+
+  switch (::GetFileType(FileHandle)) {
+  default:
+    llvm_unreachable("Don't know anything about this file type");
+  case FILE_TYPE_UNKNOWN: {
+    DWORD Err = ::GetLastError();
+    if (Err != NO_ERROR)
+      return mapWindowsError(Err);
+    Result = file_status(file_type::type_unknown);
+    return std::error_code();
+  }
+  case FILE_TYPE_DISK:
+    break;
+  case FILE_TYPE_CHAR:
+    Result = file_status(file_type::character_file);
+    return std::error_code();
+  case FILE_TYPE_PIPE:
+    Result = file_status(file_type::fifo_file);
+    return std::error_code();
+  }
+
+  BY_HANDLE_FILE_INFORMATION Info;
+  if (!::GetFileInformationByHandle(FileHandle, &Info))
+    goto handle_status_error;
+
+  {
+    file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                         ? file_type::directory_file
+                         : file_type::regular_file;
+    Result =
+        file_status(Type, Info.ftLastAccessTime.dwHighDateTime,
+                    Info.ftLastAccessTime.dwLowDateTime,
+                    Info.ftLastWriteTime.dwHighDateTime,
+                    Info.ftLastWriteTime.dwLowDateTime,
+                    Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
+                    Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
+    return std::error_code();
+  }
+
+handle_status_error:
+  DWORD LastError = ::GetLastError();
+  if (LastError == ERROR_FILE_NOT_FOUND ||
+      LastError == ERROR_PATH_NOT_FOUND)
+    Result = file_status(file_type::file_not_found);
+  else if (LastError == ERROR_SHARING_VIOLATION)
+    Result = file_status(file_type::type_unknown);
+  else
+    Result = file_status(file_type::status_error);
+  return mapWindowsError(LastError);
+}
+
+std::error_code status(const Twine &path, file_status &result) {
+  SmallString<128> path_storage;
+  SmallVector<wchar_t, 128> path_utf16;
+
+  StringRef path8 = path.toStringRef(path_storage);
+  if (isReservedName(path8)) {
+    result = file_status(file_type::character_file);
+    return std::error_code();
+  }
+
+  if (std::error_code ec = widenPath(path8, path_utf16))
+    return ec;
+
+  DWORD attr = ::GetFileAttributesW(path_utf16.begin());
+  if (attr == INVALID_FILE_ATTRIBUTES)
+    return getStatus(INVALID_HANDLE_VALUE, result);
+
+  // Handle reparse points.
+  if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
+    ScopedFileHandle h(
+      ::CreateFileW(path_utf16.begin(),
+                    0, // Attributes only.
+                    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                    NULL,
+                    OPEN_EXISTING,
+                    FILE_FLAG_BACKUP_SEMANTICS,
+                    0));
+    if (!h)
+      return getStatus(INVALID_HANDLE_VALUE, result);
+  }
+
+  ScopedFileHandle h(
+      ::CreateFileW(path_utf16.begin(), 0, // Attributes only.
+                    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                    NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
+    if (!h)
+      return getStatus(INVALID_HANDLE_VALUE, result);
+
+    return getStatus(h, result);
+}
+
+std::error_code status(int FD, file_status &Result) {
+  HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+  return getStatus(FileHandle, Result);
+}
+
+std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) {
+  ULARGE_INTEGER UI;
+  UI.QuadPart = Time.toWin32Time();
+  FILETIME FT;
+  FT.dwLowDateTime = UI.LowPart;
+  FT.dwHighDateTime = UI.HighPart;
+  HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+  if (!SetFileTime(FileHandle, NULL, &FT, &FT))
+    return mapWindowsError(::GetLastError());
+  return std::error_code();
+}
+
+std::error_code mapped_file_region::init(int FD, uint64_t Offset,
+                                         mapmode Mode) {
+  // Make sure that the requested size fits within SIZE_T.
+  if (Size > std::numeric_limits<SIZE_T>::max())
+    return make_error_code(errc::invalid_argument);
+
+  HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+  if (FileHandle == INVALID_HANDLE_VALUE)
+    return make_error_code(errc::bad_file_descriptor);
+
+  DWORD flprotect;
+  switch (Mode) {
+  case readonly:  flprotect = PAGE_READONLY; break;
+  case readwrite: flprotect = PAGE_READWRITE; break;
+  case priv:      flprotect = PAGE_WRITECOPY; break;
+  }
+
+  HANDLE FileMappingHandle =
+      ::CreateFileMappingW(FileHandle, 0, flprotect,
+                           (Offset + Size) >> 32,
+                           (Offset + Size) & 0xffffffff,
+                           0);
+  if (FileMappingHandle == NULL) {
+    std::error_code ec = mapWindowsError(GetLastError());
+    return ec;
+  }
+
+  DWORD dwDesiredAccess;
+  switch (Mode) {
+  case readonly:  dwDesiredAccess = FILE_MAP_READ; break;
+  case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break;
+  case priv:      dwDesiredAccess = FILE_MAP_COPY; break;
+  }
+  Mapping = ::MapViewOfFile(FileMappingHandle,
+                            dwDesiredAccess,
+                            Offset >> 32,
+                            Offset & 0xffffffff,
+                            Size);
+  if (Mapping == NULL) {
+    std::error_code ec = mapWindowsError(GetLastError());
+    ::CloseHandle(FileMappingHandle);
+    return ec;
+  }
+
+  if (Size == 0) {
+    MEMORY_BASIC_INFORMATION mbi;
+    SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi));
+    if (Result == 0) {
+      std::error_code ec = mapWindowsError(GetLastError());
+      ::UnmapViewOfFile(Mapping);
+      ::CloseHandle(FileMappingHandle);
+      return ec;
+    }
+    Size = mbi.RegionSize;
+  }
+
+  // Close all the handles except for the view. It will keep the other handles
+  // alive.
+  ::CloseHandle(FileMappingHandle);
+  return std::error_code();
+}
+
+mapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length,
+                                       uint64_t offset, std::error_code &ec)
+    : Size(length), Mapping() {
+  ec = init(fd, offset, mode);
+  if (ec)
+    Mapping = 0;
+}
+
+mapped_file_region::~mapped_file_region() {
+  if (Mapping)
+    ::UnmapViewOfFile(Mapping);
+}
+
+uint64_t mapped_file_region::size() const {
+  assert(Mapping && "Mapping failed but used anyway!");
+  return Size;
+}
+
+char *mapped_file_region::data() const {
+  assert(Mapping && "Mapping failed but used anyway!");
+  return reinterpret_cast<char*>(Mapping);
+}
+
+const char *mapped_file_region::const_data() const {
+  assert(Mapping && "Mapping failed but used anyway!");
+  return reinterpret_cast<const char*>(Mapping);
+}
+
+int mapped_file_region::alignment() {
+  SYSTEM_INFO SysInfo;
+  ::GetSystemInfo(&SysInfo);
+  return SysInfo.dwAllocationGranularity;
+}
+
+std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
+                                                StringRef path){
+  SmallVector<wchar_t, 128> path_utf16;
+
+  if (std::error_code ec = widenPath(path, path_utf16))
+    return ec;
+
+  // Convert path to the format that Windows is happy with.
+  if (path_utf16.size() > 0 &&
+      !is_separator(path_utf16[path.size() - 1]) &&
+      path_utf16[path.size() - 1] != L':') {
+    path_utf16.push_back(L'\\');
+    path_utf16.push_back(L'*');
+  } else {
+    path_utf16.push_back(L'*');
+  }
+
+  //  Get the first directory entry.
+  WIN32_FIND_DATAW FirstFind;
+  ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind));
+  if (!FindHandle)
+    return mapWindowsError(::GetLastError());
+
+  size_t FilenameLen = ::wcslen(FirstFind.cFileName);
+  while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') ||
+         (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' &&
+                              FirstFind.cFileName[1] == L'.'))
+    if (!::FindNextFileW(FindHandle, &FirstFind)) {
+      DWORD LastError = ::GetLastError();
+      // Check for end.
+      if (LastError == ERROR_NO_MORE_FILES)
+        return detail::directory_iterator_destruct(it);
+      return mapWindowsError(LastError);
+    } else
+      FilenameLen = ::wcslen(FirstFind.cFileName);
+
+  // Construct the current directory entry.
+  SmallString<128> directory_entry_name_utf8;
+  if (std::error_code ec =
+          UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName),
+                      directory_entry_name_utf8))
+    return ec;
+
+  it.IterationHandle = intptr_t(FindHandle.take());
+  SmallString<128> directory_entry_path(path);
+  path::append(directory_entry_path, directory_entry_name_utf8);
+  it.CurrentEntry = directory_entry(directory_entry_path);
+
+  return std::error_code();
+}
+
+std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
+  if (it.IterationHandle != 0)
+    // Closes the handle if it's valid.
+    ScopedFindHandle close(HANDLE(it.IterationHandle));
+  it.IterationHandle = 0;
+  it.CurrentEntry = directory_entry();
+  return std::error_code();
+}
+
+std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
+  WIN32_FIND_DATAW FindData;
+  if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) {
+    DWORD LastError = ::GetLastError();
+    // Check for end.
+    if (LastError == ERROR_NO_MORE_FILES)
+      return detail::directory_iterator_destruct(it);
+    return mapWindowsError(LastError);
+  }
+
+  size_t FilenameLen = ::wcslen(FindData.cFileName);
+  if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') ||
+      (FilenameLen == 2 && FindData.cFileName[0] == L'.' &&
+                           FindData.cFileName[1] == L'.'))
+    return directory_iterator_increment(it);
+
+  SmallString<128> directory_entry_path_utf8;
+  if (std::error_code ec =
+          UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName),
+                      directory_entry_path_utf8))
+    return ec;
+
+  it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8));
+  return std::error_code();
+}
+
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+                                SmallVectorImpl<char> *RealPath) {
+  SmallVector<wchar_t, 128> PathUTF16;
+
+  if (std::error_code EC = widenPath(Name, PathUTF16))
+    return EC;
+
+  HANDLE H =
+      ::CreateFileW(PathUTF16.begin(), GENERIC_READ,
+                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (H == INVALID_HANDLE_VALUE) {
+    DWORD LastError = ::GetLastError();
+    std::error_code EC = mapWindowsError(LastError);
+    // Provide a better error message when trying to open directories.
+    // This only runs if we failed to open the file, so there is probably
+    // no performances issues.
+    if (LastError != ERROR_ACCESS_DENIED)
+      return EC;
+    if (is_directory(Name))
+      return make_error_code(errc::is_a_directory);
+    return EC;
+  }
+
+  int FD = ::_open_osfhandle(intptr_t(H), 0);
+  if (FD == -1) {
+    ::CloseHandle(H);
+    return mapWindowsError(ERROR_INVALID_HANDLE);
+  }
+
+  // Fetch the real name of the file, if the user asked
+  if (RealPath) {
+    RealPath->clear();
+    wchar_t RealPathUTF16[MAX_PATH];
+    DWORD CountChars =
+      ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH,
+                                  FILE_NAME_NORMALIZED);
+    if (CountChars > 0 && CountChars < MAX_PATH) {
+      // Convert the result from UTF-16 to UTF-8.
+      SmallString<MAX_PATH> RealPathUTF8;
+      if (!UTF16ToUTF8(RealPathUTF16, CountChars, RealPathUTF8))
+        RealPath->append(RealPathUTF8.data(),
+                         RealPathUTF8.data() + strlen(RealPathUTF8.data()));
+    }
+  }
+
+  ResultFD = FD;
+  return std::error_code();
+}
+
+std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
+                            sys::fs::OpenFlags Flags, unsigned Mode) {
+  // Verify that we don't have both "append" and "excl".
+  assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
+         "Cannot specify both 'excl' and 'append' file creation flags!");
+
+  SmallVector<wchar_t, 128> PathUTF16;
+
+  if (std::error_code EC = widenPath(Name, PathUTF16))
+    return EC;
+
+  DWORD CreationDisposition;
+  if (Flags & F_Excl)
+    CreationDisposition = CREATE_NEW;
+  else if (Flags & F_Append)
+    CreationDisposition = OPEN_ALWAYS;
+  else
+    CreationDisposition = CREATE_ALWAYS;
+
+  DWORD Access = GENERIC_WRITE;
+  if (Flags & F_RW)
+    Access |= GENERIC_READ;
+
+  HANDLE H = ::CreateFileW(PathUTF16.begin(), Access,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                           CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
+
+  if (H == INVALID_HANDLE_VALUE) {
+    DWORD LastError = ::GetLastError();
+    std::error_code EC = mapWindowsError(LastError);
+    // Provide a better error message when trying to open directories.
+    // This only runs if we failed to open the file, so there is probably
+    // no performances issues.
+    if (LastError != ERROR_ACCESS_DENIED)
+      return EC;
+    if (is_directory(Name))
+      return make_error_code(errc::is_a_directory);
+    return EC;
+  }
+
+  int OpenFlags = 0;
+  if (Flags & F_Append)
+    OpenFlags |= _O_APPEND;
+
+  if (Flags & F_Text)
+    OpenFlags |= _O_TEXT;
+
+  int FD = ::_open_osfhandle(intptr_t(H), OpenFlags);
+  if (FD == -1) {
+    ::CloseHandle(H);
+    return mapWindowsError(ERROR_INVALID_HANDLE);
+  }
+
+  ResultFD = FD;
+  return std::error_code();
+}
+
+std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) {
+  HANDLE FileHandle = reinterpret_cast<HANDLE>(::_get_osfhandle(FD));
+  if (FileHandle == INVALID_HANDLE_VALUE)
+    return make_error_code(errc::bad_file_descriptor);
+
+  DWORD CharCount;
+  SmallVector<wchar_t, 1024> TempPath;
+  do {
+    CharCount = ::GetFinalPathNameByHandleW(FileHandle, TempPath.begin(),
+                                            TempPath.capacity(),
+                                            FILE_NAME_NORMALIZED);
+    if (CharCount < TempPath.capacity())
+      break;
+
+    // Reserve sufficient space for the path as well as the null character. Even
+    // though the API does not document that it is required, if we reserve just
+    // CharCount space, the function call will not store the resulting path and
+    // still report success.
+    TempPath.reserve(CharCount + 1);
+  } while (true);
+
+  if (CharCount == 0)
+    return mapWindowsError(::GetLastError());
+
+  TempPath.set_size(CharCount);
+
+  // On earlier Windows releases, the character count includes the terminating
+  // null.
+  if (TempPath.back() == L'\0') {
+    --CharCount;
+    TempPath.pop_back();
+  }
+
+  return windows::UTF16ToUTF8(TempPath.data(), CharCount, ResultPath);
+}
+} // end namespace fs
+
+namespace path {
+static bool getKnownFolderPath(KNOWNFOLDERID folderId,
+                               SmallVectorImpl<char> &result) {
+  wchar_t *path = nullptr;
+  if (::SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, nullptr, &path) != S_OK)
+    return false;
+
+  bool ok = !UTF16ToUTF8(path, ::wcslen(path), result);
+  ::CoTaskMemFree(path);
+  return ok;
+}
+
+bool getUserCacheDir(SmallVectorImpl<char> &Result) {
+  return getKnownFolderPath(FOLDERID_LocalAppData, Result);
+}
+
+bool home_directory(SmallVectorImpl<char> &result) {
+  return getKnownFolderPath(FOLDERID_Profile, result);
+}
+
+static bool getTempDirEnvVar(const wchar_t *Var, SmallVectorImpl<char> &Res) {
+  SmallVector<wchar_t, 1024> Buf;
+  size_t Size = 1024;
+  do {
+    Buf.reserve(Size);
+    Size = GetEnvironmentVariableW(Var, Buf.data(), Buf.capacity());
+    if (Size == 0)
+      return false;
+
+    // Try again with larger buffer.
+  } while (Size > Buf.capacity());
+  Buf.set_size(Size);
+
+  return !windows::UTF16ToUTF8(Buf.data(), Size, Res);
+}
+
+static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) {
+  const wchar_t *EnvironmentVariables[] = {L"TMP", L"TEMP", L"USERPROFILE"};
+  for (auto *Env : EnvironmentVariables) {
+    if (getTempDirEnvVar(Env, Res))
+      return true;
+  }
+  return false;
+}
+
+void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
+  (void)ErasedOnReboot;
+  Result.clear();
+
+  // Check whether the temporary directory is specified by an environment var.
+  // This matches GetTempPath logic to some degree. GetTempPath is not used
+  // directly as it cannot handle evn var longer than 130 chars on Windows 7
+  // (fixed on Windows 8).
+  if (getTempDirEnvVar(Result)) {
+    assert(!Result.empty() && "Unexpected empty path");
+    native(Result); // Some Unix-like shells use Unix path separator in $TMP.
+    fs::make_absolute(Result); // Make it absolute if not already.
+    return;
+  }
+
+  // Fall back to a system default.
+  const char *DefaultResult = "C:\\Temp";
+  Result.append(DefaultResult, DefaultResult + strlen(DefaultResult));
+}
+} // end namespace path
+
+namespace windows {
+std::error_code UTF8ToUTF16(llvm::StringRef utf8,
+                            llvm::SmallVectorImpl<wchar_t> &utf16) {
+  if (!utf8.empty()) {
+    int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(),
+                                    utf8.size(), utf16.begin(), 0);
+
+    if (len == 0)
+      return mapWindowsError(::GetLastError());
+
+    utf16.reserve(len + 1);
+    utf16.set_size(len);
+
+    len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(),
+                                utf8.size(), utf16.begin(), utf16.size());
+
+    if (len == 0)
+      return mapWindowsError(::GetLastError());
+  }
+
+  // Make utf16 null terminated.
+  utf16.push_back(0);
+  utf16.pop_back();
+
+  return std::error_code();
+}
+
+static
+std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
+                                size_t utf16_len,
+                                llvm::SmallVectorImpl<char> &utf8) {
+  if (utf16_len) {
+    // Get length.
+    int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(),
+                                    0, NULL, NULL);
+
+    if (len == 0)
+      return mapWindowsError(::GetLastError());
+
+    utf8.reserve(len);
+    utf8.set_size(len);
+
+    // Now do the actual conversion.
+    len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(),
+                                utf8.size(), NULL, NULL);
+
+    if (len == 0)
+      return mapWindowsError(::GetLastError());
+  }
+
+  // Make utf8 null terminated.
+  utf8.push_back(0);
+  utf8.pop_back();
+
+  return std::error_code();
+}
+
+std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
+                            llvm::SmallVectorImpl<char> &utf8) {
+  return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8);
+}
+
+std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
+                             llvm::SmallVectorImpl<char> &utf8) {
+  return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8);
+}
+
+} // end namespace windows
+} // end namespace sys
+} // end namespace llvm
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Process.inc b/third_party/llvm-subzero/lib/Support/Windows/Process.inc
new file mode 100644
index 0000000..b012991
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/Process.inc
@@ -0,0 +1,473 @@
+//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Win32 specific implementation of the Process class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/WindowsError.h"
+#include <malloc.h>
+
+// The Windows.h header must be after LLVM and standard headers.
+#include "WindowsSupport.h"
+
+#include <direct.h>
+#include <io.h>
+#include <psapi.h>
+#include <shellapi.h>
+
+#ifdef __MINGW32__
+ #if (HAVE_LIBPSAPI != 1)
+  #error "libpsapi.a should be present"
+ #endif
+ #if (HAVE_LIBSHELL32 != 1)
+  #error "libshell32.a should be present"
+ #endif
+#else
+ #pragma comment(lib, "psapi.lib")
+ #pragma comment(lib, "shell32.lib")
+#endif
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//===          and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+#ifdef __MINGW32__
+// This ban should be lifted when MinGW 1.0+ has defined this value.
+#  define _HEAPOK (-2)
+#endif
+
+using namespace llvm;
+using namespace sys;
+
+static TimeValue getTimeValueFromFILETIME(FILETIME Time) {
+  ULARGE_INTEGER TimeInteger;
+  TimeInteger.LowPart = Time.dwLowDateTime;
+  TimeInteger.HighPart = Time.dwHighDateTime;
+
+  // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
+  return TimeValue(
+      static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000),
+      static_cast<TimeValue::NanoSecondsType>(
+          (TimeInteger.QuadPart % 10000000) * 100));
+}
+
+// This function retrieves the page size using GetNativeSystemInfo() and is
+// present solely so it can be called once to initialize the self_process member
+// below.
+static unsigned computePageSize() {
+  // GetNativeSystemInfo() provides the physical page size which may differ
+  // from GetSystemInfo() in 32-bit applications running under WOW64.
+  SYSTEM_INFO info;
+  GetNativeSystemInfo(&info);
+  // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
+  // but dwAllocationGranularity.
+  return static_cast<unsigned>(info.dwPageSize);
+}
+
+unsigned Process::getPageSize() {
+  static unsigned Ret = computePageSize();
+  return Ret;
+}
+
+size_t
+Process::GetMallocUsage()
+{
+  _HEAPINFO hinfo;
+  hinfo._pentry = NULL;
+
+  size_t size = 0;
+
+  while (_heapwalk(&hinfo) == _HEAPOK)
+    size += hinfo._size;
+
+  return size;
+}
+
+void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
+                           TimeValue &sys_time) {
+  elapsed = TimeValue::now();
+
+  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
+  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
+                      &UserTime) == 0)
+    return;
+
+  user_time = getTimeValueFromFILETIME(UserTime);
+  sys_time = getTimeValueFromFILETIME(KernelTime);
+}
+
+// Some LLVM programs such as bugpoint produce core files as a normal part of
+// their operation. To prevent the disk from filling up, this configuration
+// item does what's necessary to prevent their generation.
+void Process::PreventCoreFiles() {
+  // Windows does have the concept of core files, called minidumps.  However,
+  // disabling minidumps for a particular application extends past the lifetime
+  // of that application, which is the incorrect behavior for this API.
+  // Additionally, the APIs require elevated privileges to disable and re-
+  // enable minidumps, which makes this untenable. For more information, see
+  // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
+  // later).
+  //
+  // Windows also has modal pop-up message boxes.  As this method is used by
+  // bugpoint, preventing these pop-ups is additionally important.
+  SetErrorMode(SEM_FAILCRITICALERRORS |
+               SEM_NOGPFAULTERRORBOX |
+               SEM_NOOPENFILEERRORBOX);
+
+  coreFilesPrevented = true;
+}
+
+/// Returns the environment variable \arg Name's value as a string encoded in
+/// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
+Optional<std::string> Process::GetEnv(StringRef Name) {
+  // Convert the argument to UTF-16 to pass it to _wgetenv().
+  SmallVector<wchar_t, 128> NameUTF16;
+  if (windows::UTF8ToUTF16(Name, NameUTF16))
+    return None;
+
+  // Environment variable can be encoded in non-UTF8 encoding, and there's no
+  // way to know what the encoding is. The only reliable way to look up
+  // multibyte environment variable is to use GetEnvironmentVariableW().
+  SmallVector<wchar_t, MAX_PATH> Buf;
+  size_t Size = MAX_PATH;
+  do {
+    Buf.reserve(Size);
+    Size =
+        GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
+    if (Size == 0)
+      return None;
+
+    // Try again with larger buffer.
+  } while (Size > Buf.capacity());
+  Buf.set_size(Size);
+
+  // Convert the result from UTF-16 to UTF-8.
+  SmallVector<char, MAX_PATH> Res;
+  if (windows::UTF16ToUTF8(Buf.data(), Size, Res))
+    return None;
+  return std::string(Res.data());
+}
+
+static void AllocateAndPush(const SmallVectorImpl<char> &S,
+                            SmallVectorImpl<const char *> &Vector,
+                            SpecificBumpPtrAllocator<char> &Allocator) {
+  char *Buffer = Allocator.Allocate(S.size() + 1);
+  ::memcpy(Buffer, S.data(), S.size());
+  Buffer[S.size()] = '\0';
+  Vector.push_back(Buffer);
+}
+
+/// Convert Arg from UTF-16 to UTF-8 and push it onto Args.
+static std::error_code
+ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
+                  SpecificBumpPtrAllocator<char> &Allocator) {
+  SmallVector<char, MAX_PATH> ArgString;
+  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString))
+    return ec;
+  AllocateAndPush(ArgString, Args, Allocator);
+  return std::error_code();
+}
+
+/// \brief Perform wildcard expansion of Arg, or just push it into Args if it
+/// doesn't have wildcards or doesn't match any files.
+static std::error_code
+WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
+               SpecificBumpPtrAllocator<char> &Allocator) {
+  if (!wcspbrk(Arg, L"*?")) {
+    // Arg does not contain any wildcard characters. This is the common case.
+    return ConvertAndPushArg(Arg, Args, Allocator);
+  }
+
+  if (wcscmp(Arg, L"/?") == 0 || wcscmp(Arg, L"-?") == 0) {
+    // Don't wildcard expand /?. Always treat it as an option.
+    return ConvertAndPushArg(Arg, Args, Allocator);
+  }
+
+  // Extract any directory part of the argument.
+  SmallVector<char, MAX_PATH> Dir;
+  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), Dir))
+    return ec;
+  sys::path::remove_filename(Dir);
+  const int DirSize = Dir.size();
+
+  // Search for matching files.
+  // FIXME:  This assumes the wildcard is only in the file name and not in the
+  // directory portion of the file path.  For example, it doesn't handle
+  // "*\foo.c" nor "s?c\bar.cpp".
+  WIN32_FIND_DATAW FileData;
+  HANDLE FindHandle = FindFirstFileW(Arg, &FileData);
+  if (FindHandle == INVALID_HANDLE_VALUE) {
+    return ConvertAndPushArg(Arg, Args, Allocator);
+  }
+
+  std::error_code ec;
+  do {
+    SmallVector<char, MAX_PATH> FileName;
+    ec = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName),
+                              FileName);
+    if (ec)
+      break;
+
+    // Append FileName to Dir, and remove it afterwards.
+    llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size()));
+    AllocateAndPush(Dir, Args, Allocator);
+    Dir.resize(DirSize);
+  } while (FindNextFileW(FindHandle, &FileData));
+
+  FindClose(FindHandle);
+  return ec;
+}
+
+static std::error_code
+ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
+                    SpecificBumpPtrAllocator<char> &Allocator) {
+  SmallVector<wchar_t, MAX_PATH> LongPath;
+  DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity());
+  if (Length == 0)
+    return mapWindowsError(GetLastError());
+  if (Length > LongPath.capacity()) {
+    // We're not going to try to deal with paths longer than MAX_PATH, so we'll
+    // treat this as an error.  GetLastError() returns ERROR_SUCCESS, which
+    // isn't useful, so we'll hardcode an appropriate error value.
+    return mapWindowsError(ERROR_INSUFFICIENT_BUFFER);
+  }
+  LongPath.set_size(Length);
+  return ConvertAndPushArg(LongPath.data(), Args, Allocator);
+}
+
+std::error_code
+Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
+                           ArrayRef<const char *>,
+                           SpecificBumpPtrAllocator<char> &ArgAllocator) {
+  int ArgCount;
+  wchar_t **UnicodeCommandLine =
+      CommandLineToArgvW(GetCommandLineW(), &ArgCount);
+  if (!UnicodeCommandLine)
+    return mapWindowsError(::GetLastError());
+
+  Args.reserve(ArgCount);
+  std::error_code ec;
+
+  // The first argument may contain just the name of the executable (e.g.,
+  // "clang") rather than the full path, so swap it with the full path.
+  wchar_t ModuleName[MAX_PATH];
+  int Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH);
+  if (0 < Length && Length < MAX_PATH)
+    UnicodeCommandLine[0] = ModuleName;
+
+  // If the first argument is a shortened (8.3) name (which is possible even
+  // if we got the module name), the driver will have trouble distinguishing it
+  // (e.g., clang.exe v. clang++.exe), so expand it now.
+  ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator);
+
+  for (int i = 1; i < ArgCount && !ec; ++i) {
+    ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
+    if (ec)
+      break;
+  }
+
+  LocalFree(UnicodeCommandLine);
+  return ec;
+}
+
+std::error_code Process::FixupStandardFileDescriptors() {
+  return std::error_code();
+}
+
+std::error_code Process::SafelyCloseFileDescriptor(int FD) {
+  if (::close(FD) < 0)
+    return std::error_code(errno, std::generic_category());
+  return std::error_code();
+}
+
+bool Process::StandardInIsUserInput() {
+  return FileDescriptorIsDisplayed(0);
+}
+
+bool Process::StandardOutIsDisplayed() {
+  return FileDescriptorIsDisplayed(1);
+}
+
+bool Process::StandardErrIsDisplayed() {
+  return FileDescriptorIsDisplayed(2);
+}
+
+bool Process::FileDescriptorIsDisplayed(int fd) {
+  DWORD Mode;  // Unused
+  return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
+}
+
+unsigned Process::StandardOutColumns() {
+  unsigned Columns = 0;
+  CONSOLE_SCREEN_BUFFER_INFO csbi;
+  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
+    Columns = csbi.dwSize.X;
+  return Columns;
+}
+
+unsigned Process::StandardErrColumns() {
+  unsigned Columns = 0;
+  CONSOLE_SCREEN_BUFFER_INFO csbi;
+  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
+    Columns = csbi.dwSize.X;
+  return Columns;
+}
+
+// The terminal always has colors.
+bool Process::FileDescriptorHasColors(int fd) {
+  return FileDescriptorIsDisplayed(fd);
+}
+
+bool Process::StandardOutHasColors() {
+  return FileDescriptorHasColors(1);
+}
+
+bool Process::StandardErrHasColors() {
+  return FileDescriptorHasColors(2);
+}
+
+static bool UseANSI = false;
+void Process::UseANSIEscapeCodes(bool enable) {
+  UseANSI = enable;
+}
+
+namespace {
+class DefaultColors
+{
+  private:
+    WORD defaultColor;
+  public:
+    DefaultColors()
+     :defaultColor(GetCurrentColor()) {}
+    static unsigned GetCurrentColor() {
+      CONSOLE_SCREEN_BUFFER_INFO csbi;
+      if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
+        return csbi.wAttributes;
+      return 0;
+    }
+    WORD operator()() const { return defaultColor; }
+};
+
+DefaultColors defaultColors;
+
+WORD fg_color(WORD color) {
+  return color & (FOREGROUND_BLUE | FOREGROUND_GREEN |
+                  FOREGROUND_INTENSITY | FOREGROUND_RED);
+}
+
+WORD bg_color(WORD color) {
+  return color & (BACKGROUND_BLUE | BACKGROUND_GREEN |
+                  BACKGROUND_INTENSITY | BACKGROUND_RED);
+}
+}
+
+bool Process::ColorNeedsFlush() {
+  return !UseANSI;
+}
+
+const char *Process::OutputBold(bool bg) {
+  if (UseANSI) return "\033[1m";
+
+  WORD colors = DefaultColors::GetCurrentColor();
+  if (bg)
+    colors |= BACKGROUND_INTENSITY;
+  else
+    colors |= FOREGROUND_INTENSITY;
+  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
+  return 0;
+}
+
+const char *Process::OutputColor(char code, bool bold, bool bg) {
+  if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
+
+  WORD current = DefaultColors::GetCurrentColor();
+  WORD colors;
+  if (bg) {
+    colors = ((code&1) ? BACKGROUND_RED : 0) |
+      ((code&2) ? BACKGROUND_GREEN : 0 ) |
+      ((code&4) ? BACKGROUND_BLUE : 0);
+    if (bold)
+      colors |= BACKGROUND_INTENSITY;
+    colors |= fg_color(current);
+  } else {
+    colors = ((code&1) ? FOREGROUND_RED : 0) |
+      ((code&2) ? FOREGROUND_GREEN : 0 ) |
+      ((code&4) ? FOREGROUND_BLUE : 0);
+    if (bold)
+      colors |= FOREGROUND_INTENSITY;
+    colors |= bg_color(current);
+  }
+  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
+  return 0;
+}
+
+static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
+  CONSOLE_SCREEN_BUFFER_INFO info;
+  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
+  return info.wAttributes;
+}
+
+const char *Process::OutputReverse() {
+  if (UseANSI) return "\033[7m";
+
+  const WORD attributes
+   = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
+
+  const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
+    FOREGROUND_RED | FOREGROUND_INTENSITY;
+  const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
+    BACKGROUND_RED | BACKGROUND_INTENSITY;
+  const WORD color_mask = foreground_mask | background_mask;
+
+  WORD new_attributes =
+    ((attributes & FOREGROUND_BLUE     )?BACKGROUND_BLUE     :0) |
+    ((attributes & FOREGROUND_GREEN    )?BACKGROUND_GREEN    :0) |
+    ((attributes & FOREGROUND_RED      )?BACKGROUND_RED      :0) |
+    ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
+    ((attributes & BACKGROUND_BLUE     )?FOREGROUND_BLUE     :0) |
+    ((attributes & BACKGROUND_GREEN    )?FOREGROUND_GREEN    :0) |
+    ((attributes & BACKGROUND_RED      )?FOREGROUND_RED      :0) |
+    ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
+    0;
+  new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
+
+  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
+  return 0;
+}
+
+const char *Process::ResetColor() {
+  if (UseANSI) return "\033[0m";
+  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
+  return 0;
+}
+
+// Include GetLastError() in a fatal error message.
+static void ReportLastErrorFatal(const char *Msg) {
+  std::string ErrMsg;
+  MakeErrMsg(&ErrMsg, Msg);
+  report_fatal_error(ErrMsg);
+}
+
+unsigned Process::GetRandomNumber() {
+  HCRYPTPROV HCPC;
+  if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
+                              CRYPT_VERIFYCONTEXT))
+    ReportLastErrorFatal("Could not acquire a cryptographic context");
+
+  ScopedCryptContext CryptoProvider(HCPC);
+  unsigned Ret;
+  if (!::CryptGenRandom(CryptoProvider, sizeof(Ret),
+                        reinterpret_cast<BYTE *>(&Ret)))
+    ReportLastErrorFatal("Could not generate a random number");
+  return Ret;
+}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Program.inc b/third_party/llvm-subzero/lib/Support/Windows/Program.inc
new file mode 100644
index 0000000..78fc538
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/Program.inc
@@ -0,0 +1,554 @@
+//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Win32 specific implementation of the Program class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WindowsSupport.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/WindowsError.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+#include <fcntl.h>
+#include <io.h>
+#include <malloc.h>
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//===          and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+using namespace sys;
+
+ProcessInfo::ProcessInfo() : ProcessHandle(0), Pid(0), ReturnCode(0) {}
+
+ErrorOr<std::string> sys::findProgramByName(StringRef Name,
+                                            ArrayRef<StringRef> Paths) {
+  assert(!Name.empty() && "Must have a name!");
+
+  if (Name.find_first_of("/\\") != StringRef::npos)
+    return std::string(Name);
+
+  const wchar_t *Path = nullptr;
+  std::wstring PathStorage;
+  if (!Paths.empty()) {
+    PathStorage.reserve(Paths.size() * MAX_PATH);
+    for (unsigned i = 0; i < Paths.size(); ++i) {
+      if (i)
+        PathStorage.push_back(L';');
+      StringRef P = Paths[i];
+      SmallVector<wchar_t, MAX_PATH> TmpPath;
+      if (std::error_code EC = windows::UTF8ToUTF16(P, TmpPath))
+        return EC;
+      PathStorage.append(TmpPath.begin(), TmpPath.end());
+    }
+    Path = PathStorage.c_str();
+  }
+
+  SmallVector<wchar_t, MAX_PATH> U16Name;
+  if (std::error_code EC = windows::UTF8ToUTF16(Name, U16Name))
+    return EC;
+
+  SmallVector<StringRef, 12> PathExts;
+  PathExts.push_back("");
+  PathExts.push_back(".exe"); // FIXME: This must be in %PATHEXT%.
+  if (const char *PathExtEnv = std::getenv("PATHEXT"))
+    SplitString(PathExtEnv, PathExts, ";");
+
+  SmallVector<wchar_t, MAX_PATH> U16Result;
+  DWORD Len = MAX_PATH;
+  for (StringRef Ext : PathExts) {
+    SmallVector<wchar_t, MAX_PATH> U16Ext;
+    if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext))
+      return EC;
+
+    do {
+      U16Result.reserve(Len);
+      // Lets attach the extension manually. That is needed for files
+      // with a point in name like aaa.bbb. SearchPathW will not add extension
+      // from its argument to such files because it thinks they already had one.
+      SmallVector<wchar_t, MAX_PATH> U16NameExt;
+      if (std::error_code EC =
+              windows::UTF8ToUTF16(Twine(Name + Ext).str(), U16NameExt))
+        return EC;
+
+      Len = ::SearchPathW(Path, c_str(U16NameExt), nullptr,
+                          U16Result.capacity(), U16Result.data(), nullptr);
+    } while (Len > U16Result.capacity());
+
+    if (Len != 0)
+      break; // Found it.
+  }
+
+  if (Len == 0)
+    return mapWindowsError(::GetLastError());
+
+  U16Result.set_size(Len);
+
+  SmallVector<char, MAX_PATH> U8Result;
+  if (std::error_code EC =
+          windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result))
+    return EC;
+
+  return std::string(U8Result.begin(), U8Result.end());
+}
+
+static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) {
+  HANDLE h;
+  if (path == 0) {
+    if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
+                         GetCurrentProcess(), &h,
+                         0, TRUE, DUPLICATE_SAME_ACCESS))
+      return INVALID_HANDLE_VALUE;
+    return h;
+  }
+
+  std::string fname;
+  if (path->empty())
+    fname = "NUL";
+  else
+    fname = *path;
+
+  SECURITY_ATTRIBUTES sa;
+  sa.nLength = sizeof(sa);
+  sa.lpSecurityDescriptor = 0;
+  sa.bInheritHandle = TRUE;
+
+  SmallVector<wchar_t, 128> fnameUnicode;
+  if (path->empty()) {
+    // Don't play long-path tricks on "NUL".
+    if (windows::UTF8ToUTF16(fname, fnameUnicode))
+      return INVALID_HANDLE_VALUE;
+  } else {
+    if (path::widenPath(fname, fnameUnicode))
+      return INVALID_HANDLE_VALUE;
+  }
+  h = CreateFileW(fnameUnicode.data(), fd ? GENERIC_WRITE : GENERIC_READ,
+                  FILE_SHARE_READ, &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS,
+                  FILE_ATTRIBUTE_NORMAL, NULL);
+  if (h == INVALID_HANDLE_VALUE) {
+    MakeErrMsg(ErrMsg, fname + ": Can't open file for " +
+        (fd ? "input" : "output"));
+  }
+
+  return h;
+}
+
+/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling
+/// CreateProcess.
+static bool ArgNeedsQuotes(const char *Str) {
+  return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0;
+}
+
+/// CountPrecedingBackslashes - Returns the number of backslashes preceding Cur
+/// in the C string Start.
+static unsigned int CountPrecedingBackslashes(const char *Start,
+                                              const char *Cur) {
+  unsigned int Count = 0;
+  --Cur;
+  while (Cur >= Start && *Cur == '\\') {
+    ++Count;
+    --Cur;
+  }
+  return Count;
+}
+
+/// EscapePrecedingEscapes - Append a backslash to Dst for every backslash
+/// preceding Cur in the Start string.  Assumes Dst has enough space.
+static char *EscapePrecedingEscapes(char *Dst, const char *Start,
+                                    const char *Cur) {
+  unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Cur);
+  while (PrecedingEscapes > 0) {
+    *Dst++ = '\\';
+    --PrecedingEscapes;
+  }
+  return Dst;
+}
+
+/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling
+/// CreateProcess and returns length of quoted arg with escaped quotes
+static unsigned int ArgLenWithQuotes(const char *Str) {
+  const char *Start = Str;
+  bool Quoted = ArgNeedsQuotes(Str);
+  unsigned int len = Quoted ? 2 : 0;
+
+  while (*Str != '\0') {
+    if (*Str == '\"') {
+      // We need to add a backslash, but ensure that it isn't escaped.
+      unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
+      len += PrecedingEscapes + 1;
+    }
+    // Note that we *don't* need to escape runs of backslashes that don't
+    // precede a double quote!  See MSDN:
+    // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
+
+    ++len;
+    ++Str;
+  }
+
+  if (Quoted) {
+    // Make sure the closing quote doesn't get escaped by a trailing backslash.
+    unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
+    len += PrecedingEscapes + 1;
+  }
+
+  return len;
+}
+
+}
+
+static std::unique_ptr<char[]> flattenArgs(const char **args) {
+  // First, determine the length of the command line.
+  unsigned len = 0;
+  for (unsigned i = 0; args[i]; i++) {
+    len += ArgLenWithQuotes(args[i]) + 1;
+  }
+
+  // Now build the command line.
+  std::unique_ptr<char[]> command(new char[len+1]);
+  char *p = command.get();
+
+  for (unsigned i = 0; args[i]; i++) {
+    const char *arg = args[i];
+    const char *start = arg;
+
+    bool needsQuoting = ArgNeedsQuotes(arg);
+    if (needsQuoting)
+      *p++ = '"';
+
+    while (*arg != '\0') {
+      if (*arg == '\"') {
+        // Escape all preceding escapes (if any), and then escape the quote.
+        p = EscapePrecedingEscapes(p, start, arg);
+        *p++ = '\\';
+      }
+
+      *p++ = *arg++;
+    }
+
+    if (needsQuoting) {
+      // Make sure our quote doesn't get escaped by a trailing backslash.
+      p = EscapePrecedingEscapes(p, start, arg);
+      *p++ = '"';
+    }
+    *p++ = ' ';
+  }
+
+  *p = 0;
+  return command;
+}
+
+static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,
+                    const char **envp, const StringRef **redirects,
+                    unsigned memoryLimit, std::string *ErrMsg) {
+  if (!sys::fs::can_execute(Program)) {
+    if (ErrMsg)
+      *ErrMsg = "program not executable";
+    return false;
+  }
+
+  // can_execute may succeed by looking at Program + ".exe". CreateProcessW
+  // will implicitly add the .exe if we provide a command line without an
+  // executable path, but since we use an explicit executable, we have to add
+  // ".exe" ourselves.
+  SmallString<64> ProgramStorage;
+  if (!sys::fs::exists(Program))
+    Program = Twine(Program + ".exe").toStringRef(ProgramStorage);
+
+  // Windows wants a command line, not an array of args, to pass to the new
+  // process.  We have to concatenate them all, while quoting the args that
+  // have embedded spaces (or are empty).
+  std::unique_ptr<char[]> command = flattenArgs(args);
+
+  // The pointer to the environment block for the new process.
+  std::vector<wchar_t> EnvBlock;
+
+  if (envp) {
+    // An environment block consists of a null-terminated block of
+    // null-terminated strings. Convert the array of environment variables to
+    // an environment block by concatenating them.
+    for (unsigned i = 0; envp[i]; ++i) {
+      SmallVector<wchar_t, MAX_PATH> EnvString;
+      if (std::error_code ec = windows::UTF8ToUTF16(envp[i], EnvString)) {
+        SetLastError(ec.value());
+        MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16");
+        return false;
+      }
+
+      EnvBlock.insert(EnvBlock.end(), EnvString.begin(), EnvString.end());
+      EnvBlock.push_back(0);
+    }
+    EnvBlock.push_back(0);
+  }
+
+  // Create a child process.
+  STARTUPINFOW si;
+  memset(&si, 0, sizeof(si));
+  si.cb = sizeof(si);
+  si.hStdInput = INVALID_HANDLE_VALUE;
+  si.hStdOutput = INVALID_HANDLE_VALUE;
+  si.hStdError = INVALID_HANDLE_VALUE;
+
+  if (redirects) {
+    si.dwFlags = STARTF_USESTDHANDLES;
+
+    si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
+    if (si.hStdInput == INVALID_HANDLE_VALUE) {
+      MakeErrMsg(ErrMsg, "can't redirect stdin");
+      return false;
+    }
+    si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
+    if (si.hStdOutput == INVALID_HANDLE_VALUE) {
+      CloseHandle(si.hStdInput);
+      MakeErrMsg(ErrMsg, "can't redirect stdout");
+      return false;
+    }
+    if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
+      // If stdout and stderr should go to the same place, redirect stderr
+      // to the handle already open for stdout.
+      if (!DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
+                           GetCurrentProcess(), &si.hStdError,
+                           0, TRUE, DUPLICATE_SAME_ACCESS)) {
+        CloseHandle(si.hStdInput);
+        CloseHandle(si.hStdOutput);
+        MakeErrMsg(ErrMsg, "can't dup stderr to stdout");
+        return false;
+      }
+    } else {
+      // Just redirect stderr
+      si.hStdError = RedirectIO(redirects[2], 2, ErrMsg);
+      if (si.hStdError == INVALID_HANDLE_VALUE) {
+        CloseHandle(si.hStdInput);
+        CloseHandle(si.hStdOutput);
+        MakeErrMsg(ErrMsg, "can't redirect stderr");
+        return false;
+      }
+    }
+  }
+
+  PROCESS_INFORMATION pi;
+  memset(&pi, 0, sizeof(pi));
+
+  fflush(stdout);
+  fflush(stderr);
+
+  SmallVector<wchar_t, MAX_PATH> ProgramUtf16;
+  if (std::error_code ec = path::widenPath(Program, ProgramUtf16)) {
+    SetLastError(ec.value());
+    MakeErrMsg(ErrMsg,
+               std::string("Unable to convert application name to UTF-16"));
+    return false;
+  }
+
+  SmallVector<wchar_t, MAX_PATH> CommandUtf16;
+  if (std::error_code ec = windows::UTF8ToUTF16(command.get(), CommandUtf16)) {
+    SetLastError(ec.value());
+    MakeErrMsg(ErrMsg,
+               std::string("Unable to convert command-line to UTF-16"));
+    return false;
+  }
+
+  BOOL rc = CreateProcessW(ProgramUtf16.data(), CommandUtf16.data(), 0, 0,
+                           TRUE, CREATE_UNICODE_ENVIRONMENT,
+                           EnvBlock.empty() ? 0 : EnvBlock.data(), 0, &si,
+                           &pi);
+  DWORD err = GetLastError();
+
+  // Regardless of whether the process got created or not, we are done with
+  // the handles we created for it to inherit.
+  CloseHandle(si.hStdInput);
+  CloseHandle(si.hStdOutput);
+  CloseHandle(si.hStdError);
+
+  // Now return an error if the process didn't get created.
+  if (!rc) {
+    SetLastError(err);
+    MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
+               Program.str() + "'");
+    return false;
+  }
+
+  PI.Pid = pi.dwProcessId;
+  PI.ProcessHandle = pi.hProcess;
+
+  // Make sure these get closed no matter what.
+  ScopedCommonHandle hThread(pi.hThread);
+
+  // Assign the process to a job if a memory limit is defined.
+  ScopedJobHandle hJob;
+  if (memoryLimit != 0) {
+    hJob = CreateJobObjectW(0, 0);
+    bool success = false;
+    if (hJob) {
+      JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
+      memset(&jeli, 0, sizeof(jeli));
+      jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
+      jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576;
+      if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
+                                  &jeli, sizeof(jeli))) {
+        if (AssignProcessToJobObject(hJob, pi.hProcess))
+          success = true;
+      }
+    }
+    if (!success) {
+      SetLastError(GetLastError());
+      MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
+      TerminateProcess(pi.hProcess, 1);
+      WaitForSingleObject(pi.hProcess, INFINITE);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+namespace llvm {
+ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
+                      bool WaitUntilChildTerminates, std::string *ErrMsg) {
+  assert(PI.Pid && "invalid pid to wait on, process not started?");
+  assert(PI.ProcessHandle &&
+         "invalid process handle to wait on, process not started?");
+  DWORD milliSecondsToWait = 0;
+  if (WaitUntilChildTerminates)
+    milliSecondsToWait = INFINITE;
+  else if (SecondsToWait > 0)
+    milliSecondsToWait = SecondsToWait * 1000;
+
+  ProcessInfo WaitResult = PI;
+  DWORD WaitStatus = WaitForSingleObject(PI.ProcessHandle, milliSecondsToWait);
+  if (WaitStatus == WAIT_TIMEOUT) {
+    if (SecondsToWait) {
+      if (!TerminateProcess(PI.ProcessHandle, 1)) {
+        if (ErrMsg)
+          MakeErrMsg(ErrMsg, "Failed to terminate timed-out program");
+
+        // -2 indicates a crash or timeout as opposed to failure to execute.
+        WaitResult.ReturnCode = -2;
+        CloseHandle(PI.ProcessHandle);
+        return WaitResult;
+      }
+      WaitForSingleObject(PI.ProcessHandle, INFINITE);
+      CloseHandle(PI.ProcessHandle);
+    } else {
+      // Non-blocking wait.
+      return ProcessInfo();
+    }
+  }
+
+  // Get its exit status.
+  DWORD status;
+  BOOL rc = GetExitCodeProcess(PI.ProcessHandle, &status);
+  DWORD err = GetLastError();
+  if (err != ERROR_INVALID_HANDLE)
+    CloseHandle(PI.ProcessHandle);
+
+  if (!rc) {
+    SetLastError(err);
+    if (ErrMsg)
+      MakeErrMsg(ErrMsg, "Failed getting status for program");
+
+    // -2 indicates a crash or timeout as opposed to failure to execute.
+    WaitResult.ReturnCode = -2;
+    return WaitResult;
+  }
+
+  if (!status)
+    return WaitResult;
+
+  // Pass 10(Warning) and 11(Error) to the callee as negative value.
+  if ((status & 0xBFFF0000U) == 0x80000000U)
+    WaitResult.ReturnCode = static_cast<int>(status);
+  else if (status & 0xFF)
+    WaitResult.ReturnCode = status & 0x7FFFFFFF;
+  else
+    WaitResult.ReturnCode = 1;
+
+  return WaitResult;
+}
+
+std::error_code sys::ChangeStdinToBinary() {
+  int result = _setmode(_fileno(stdin), _O_BINARY);
+  if (result == -1)
+    return std::error_code(errno, std::generic_category());
+  return std::error_code();
+}
+
+std::error_code sys::ChangeStdoutToBinary() {
+  int result = _setmode(_fileno(stdout), _O_BINARY);
+  if (result == -1)
+    return std::error_code(errno, std::generic_category());
+  return std::error_code();
+}
+
+std::error_code
+llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
+                                 WindowsEncodingMethod Encoding) {
+  std::error_code EC;
+  llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
+  if (EC)
+    return EC;
+
+  if (Encoding == WEM_UTF8) {
+    OS << Contents;
+  } else if (Encoding == WEM_CurrentCodePage) {
+    SmallVector<wchar_t, 1> ArgsUTF16;
+    SmallVector<char, 1> ArgsCurCP;
+
+    if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16)))
+      return EC;
+
+    if ((EC = windows::UTF16ToCurCP(
+             ArgsUTF16.data(), ArgsUTF16.size(), ArgsCurCP)))
+      return EC;
+
+    OS.write(ArgsCurCP.data(), ArgsCurCP.size());
+  } else if (Encoding == WEM_UTF16) {
+    SmallVector<wchar_t, 1> ArgsUTF16;
+
+    if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16)))
+      return EC;
+
+    // Endianness guessing
+    char BOM[2];
+    uint16_t src = UNI_UTF16_BYTE_ORDER_MARK_NATIVE;
+    memcpy(BOM, &src, 2);
+    OS.write(BOM, 2);
+    OS.write((char *)ArgsUTF16.data(), ArgsUTF16.size() << 1);
+  } else {
+    llvm_unreachable("Unknown encoding");
+  }
+
+  if (OS.has_error())
+    return make_error_code(errc::io_error);
+
+  return EC;
+}
+
+bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef<const char*> Args) {
+  // The documented max length of the command line passed to CreateProcess.
+  static const size_t MaxCommandStringLength = 32768;
+  // Account for the trailing space for the program path and the
+  // trailing NULL of the last argument.
+  size_t ArgLength = ArgLenWithQuotes(Program.str().c_str()) + 2;
+  for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end();
+       I != E; ++I) {
+    // Account for the trailing space for every arg
+    ArgLength += ArgLenWithQuotes(*I) + 1;
+    if (ArgLength > MaxCommandStringLength) {
+      return false;
+    }
+  }
+  return true;
+}
+}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Signals.inc b/third_party/llvm-subzero/lib/Support/Windows/Signals.inc
new file mode 100644
index 0000000..d3a70c3
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/Signals.inc
@@ -0,0 +1,846 @@
+//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Win32 specific implementation of the Signals class.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/WindowsError.h"
+#include <algorithm>
+#include <io.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+// The Windows.h header must be after LLVM and standard headers.
+#include "WindowsSupport.h"
+
+#ifdef __MINGW32__
+ #include <imagehlp.h>
+#else
+ #include <dbghelp.h>
+#endif
+#include <psapi.h>
+
+#ifdef _MSC_VER
+ #pragma comment(lib, "psapi.lib")
+#elif __MINGW32__
+ #if (HAVE_LIBPSAPI != 1)
+  #error "libpsapi.a should be present"
+ #endif
+ // The version of g++ that comes with MinGW does *not* properly understand
+ // the ll format specifier for printf. However, MinGW passes the format
+ // specifiers on to the MSVCRT entirely, and the CRT understands the ll
+ // specifier. So these warnings are spurious in this case. Since we compile
+ // with -Wall, this will generate these warnings which should be ignored. So
+ // we will turn off the warnings for this just file. However, MinGW also does
+ // not support push and pop for diagnostics, so we have to manually turn it
+ // back on at the end of the file.
+ #pragma GCC diagnostic ignored "-Wformat"
+ #pragma GCC diagnostic ignored "-Wformat-extra-args"
+
+ #if !defined(__MINGW64_VERSION_MAJOR)
+ // MinGW.org does not have updated support for the 64-bit versions of the
+ // DebugHlp APIs. So we will have to load them manually. The structures and
+ // method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
+ // and adjusted for brevity.
+ typedef struct _IMAGEHLP_LINE64 {
+   DWORD    SizeOfStruct;
+   PVOID    Key;
+   DWORD    LineNumber;
+   PCHAR    FileName;
+   DWORD64  Address;
+ } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
+
+ typedef struct _IMAGEHLP_SYMBOL64 {
+   DWORD   SizeOfStruct;
+   DWORD64 Address;
+   DWORD   Size;
+   DWORD   Flags;
+   DWORD   MaxNameLength;
+   CHAR    Name[1];
+ } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
+
+ typedef struct _tagADDRESS64 {
+   DWORD64       Offset;
+   WORD          Segment;
+   ADDRESS_MODE  Mode;
+ } ADDRESS64, *LPADDRESS64;
+
+ typedef struct _KDHELP64 {
+   DWORD64   Thread;
+   DWORD   ThCallbackStack;
+   DWORD   ThCallbackBStore;
+   DWORD   NextCallback;
+   DWORD   FramePointer;
+   DWORD64   KiCallUserMode;
+   DWORD64   KeUserCallbackDispatcher;
+   DWORD64   SystemRangeStart;
+   DWORD64   KiUserExceptionDispatcher;
+   DWORD64   StackBase;
+   DWORD64   StackLimit;
+   DWORD64   Reserved[5];
+ } KDHELP64, *PKDHELP64;
+
+ typedef struct _tagSTACKFRAME64 {
+   ADDRESS64   AddrPC;
+   ADDRESS64   AddrReturn;
+   ADDRESS64   AddrFrame;
+   ADDRESS64   AddrStack;
+   ADDRESS64   AddrBStore;
+   PVOID       FuncTableEntry;
+   DWORD64     Params[4];
+   BOOL        Far;
+   BOOL        Virtual;
+   DWORD64     Reserved[3];
+   KDHELP64    KdHelp;
+ } STACKFRAME64, *LPSTACKFRAME64;
+ #endif // !defined(__MINGW64_VERSION_MAJOR)
+#endif // __MINGW32__
+
+typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,
+                      DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
+                      LPDWORD lpNumberOfBytesRead);
+
+typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess,
+                      DWORD64 AddrBase);
+
+typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
+                      DWORD64 Address);
+
+typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
+                      HANDLE hThread, LPADDRESS64 lpaddr);
+
+typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
+                                          PMINIDUMP_EXCEPTION_INFORMATION,
+                                          PMINIDUMP_USER_STREAM_INFORMATION,
+                                          PMINIDUMP_CALLBACK_INFORMATION);
+static fpMiniDumpWriteDump fMiniDumpWriteDump;
+
+typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
+                      PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
+                      PFUNCTION_TABLE_ACCESS_ROUTINE64,
+                      PGET_MODULE_BASE_ROUTINE64,
+                      PTRANSLATE_ADDRESS_ROUTINE64);
+static fpStackWalk64 fStackWalk64;
+
+typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
+static fpSymGetModuleBase64 fSymGetModuleBase64;
+
+typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64,
+                      PDWORD64, PIMAGEHLP_SYMBOL64);
+static fpSymGetSymFromAddr64 fSymGetSymFromAddr64;
+
+typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64,
+                      PDWORD, PIMAGEHLP_LINE64);
+static fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
+
+typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr,
+                                           PIMAGEHLP_MODULE64 ModuleInfo);
+static fpSymGetModuleInfo64 fSymGetModuleInfo64;
+
+typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
+static fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
+
+typedef DWORD (WINAPI *fpSymSetOptions)(DWORD);
+static fpSymSetOptions fSymSetOptions;
+
+typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
+static fpSymInitialize fSymInitialize;
+
+typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
+static fpEnumerateLoadedModules fEnumerateLoadedModules;
+
+static bool load64BitDebugHelp(void) {
+  HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
+  if (hLib) {
+    fMiniDumpWriteDump = (fpMiniDumpWriteDump)
+                      ::GetProcAddress(hLib, "MiniDumpWriteDump");
+    fStackWalk64 = (fpStackWalk64)
+                      ::GetProcAddress(hLib, "StackWalk64");
+    fSymGetModuleBase64 = (fpSymGetModuleBase64)
+                      ::GetProcAddress(hLib, "SymGetModuleBase64");
+    fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64)
+                      ::GetProcAddress(hLib, "SymGetSymFromAddr64");
+    fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64)
+                      ::GetProcAddress(hLib, "SymGetLineFromAddr64");
+    fSymGetModuleInfo64 = (fpSymGetModuleInfo64)
+                      ::GetProcAddress(hLib, "SymGetModuleInfo64");
+    fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)
+                     ::GetProcAddress(hLib, "SymFunctionTableAccess64");
+    fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions");
+    fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize");
+    fEnumerateLoadedModules = (fpEnumerateLoadedModules)
+      ::GetProcAddress(hLib, "EnumerateLoadedModules64");
+  }
+  return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
+}
+
+using namespace llvm;
+
+// Forward declare.
+static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
+static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
+
+// InterruptFunction - The function to call if ctrl-c is pressed.
+static void (*InterruptFunction)() = 0;
+
+static std::vector<std::string> *FilesToRemove = NULL;
+static bool RegisteredUnhandledExceptionFilter = false;
+static bool CleanupExecuted = false;
+static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
+
+// Windows creates a new thread to execute the console handler when an event
+// (such as CTRL/C) occurs.  This causes concurrency issues with the above
+// globals which this critical section addresses.
+static CRITICAL_SECTION CriticalSection;
+static bool CriticalSectionInitialized = false;
+
+static StringRef Argv0;
+
+enum {
+#if defined(_M_X64)
+  NativeMachineType = IMAGE_FILE_MACHINE_AMD64
+#else
+  NativeMachineType = IMAGE_FILE_MACHINE_I386
+#endif
+};
+
+static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
+                                              HANDLE hProcess, HANDLE hThread,
+                                              STACKFRAME64 &StackFrameOrig,
+                                              CONTEXT *ContextOrig) {
+  // StackWalk64 modifies the incoming stack frame and context, so copy them.
+  STACKFRAME64 StackFrame = StackFrameOrig;
+
+  // Copy the register context so that we don't modify it while we unwind. We
+  // could use InitializeContext + CopyContext, but that's only required to get
+  // at AVX registers, which typically aren't needed by StackWalk64. Reduce the
+  // flag set to indicate that there's less data.
+  CONTEXT Context = *ContextOrig;
+  Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+
+  static void *StackTrace[256];
+  size_t Depth = 0;
+  while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
+                      &Context, 0, fSymFunctionTableAccess64,
+                      fSymGetModuleBase64, 0)) {
+    if (StackFrame.AddrFrame.Offset == 0)
+      break;
+    StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset;
+    if (Depth >= array_lengthof(StackTrace))
+      break;
+  }
+
+  return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS);
+}
+
+namespace {
+struct FindModuleData {
+  void **StackTrace;
+  int Depth;
+  const char **Modules;
+  intptr_t *Offsets;
+  StringSaver *StrPool;
+};
+}
+
+static BOOL CALLBACK findModuleCallback(PCSTR ModuleName,
+                                        DWORD64 ModuleBase, ULONG ModuleSize,
+                                        void *VoidData) {
+  FindModuleData *Data = (FindModuleData*)VoidData;
+  intptr_t Beg = ModuleBase;
+  intptr_t End = Beg + ModuleSize;
+  for (int I = 0; I < Data->Depth; I++) {
+    if (Data->Modules[I])
+      continue;
+    intptr_t Addr = (intptr_t)Data->StackTrace[I];
+    if (Beg <= Addr && Addr < End) {
+      Data->Modules[I] = Data->StrPool->save(ModuleName);
+      Data->Offsets[I] = Addr - Beg;
+    }
+  }
+  return TRUE;
+}
+
+static bool findModulesAndOffsets(void **StackTrace, int Depth,
+                                  const char **Modules, intptr_t *Offsets,
+                                  const char *MainExecutableName,
+                                  StringSaver &StrPool) {
+  if (!fEnumerateLoadedModules)
+    return false;
+  FindModuleData Data;
+  Data.StackTrace = StackTrace;
+  Data.Depth = Depth;
+  Data.Modules = Modules;
+  Data.Offsets = Offsets;
+  Data.StrPool = &StrPool;
+  fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data);
+  return true;
+}
+
+static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
+                                     HANDLE hThread, STACKFRAME64 &StackFrame,
+                                     CONTEXT *Context) {
+  // Initialize the symbol handler.
+  fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
+  fSymInitialize(hProcess, NULL, TRUE);
+
+  // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs
+  // and DWARF, so it should do a good job regardless of what debug info or
+  // linker is in use.
+  if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame,
+                                        Context)) {
+    return;
+  }
+
+  while (true) {
+    if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
+                      Context, 0, fSymFunctionTableAccess64,
+                      fSymGetModuleBase64, 0)) {
+      break;
+    }
+
+    if (StackFrame.AddrFrame.Offset == 0)
+      break;
+
+    using namespace llvm;
+    // Print the PC in hexadecimal.
+    DWORD64 PC = StackFrame.AddrPC.Offset;
+#if defined(_M_X64)
+    OS << format("0x%016llX", PC);
+#elif defined(_M_IX86)
+    OS << format("0x%08lX", static_cast<DWORD>(PC));
+#endif
+
+// Print the parameters.  Assume there are four.
+#if defined(_M_X64)
+    OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
+            StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2],
+            StackFrame.Params[3]);
+#elif defined(_M_IX86)
+    OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
+            static_cast<DWORD>(StackFrame.Params[0]),
+            static_cast<DWORD>(StackFrame.Params[1]),
+            static_cast<DWORD>(StackFrame.Params[2]),
+            static_cast<DWORD>(StackFrame.Params[3]));
+#endif
+    // Verify the PC belongs to a module in this process.
+    if (!fSymGetModuleBase64(hProcess, PC)) {
+      OS << " <unknown module>\n";
+      continue;
+    }
+
+    // Print the symbol name.
+    char buffer[512];
+    IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
+    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
+    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+    symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
+
+    DWORD64 dwDisp;
+    if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
+      OS << '\n';
+      continue;
+    }
+
+    buffer[511] = 0;
+    if (dwDisp > 0)
+      OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name,
+                   dwDisp);
+    else
+      OS << format(", %s", (const char*)symbol->Name);
+
+    // Print the source file and line number information.
+    IMAGEHLP_LINE64 line = {};
+    DWORD dwLineDisp;
+    line.SizeOfStruct = sizeof(line);
+    if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
+      OS << format(", %s, line %lu", line.FileName, line.LineNumber);
+      if (dwLineDisp > 0)
+        OS << format(" + 0x%lX byte(s)", dwLineDisp);
+    }
+
+    OS << '\n';
+  }
+}
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//===          and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+#ifdef _MSC_VER
+/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry,
+/// ignore" CRT debug report dialog.  "retry" raises an exception which
+/// ultimately triggers our stack dumper.
+static LLVM_ATTRIBUTE_UNUSED int
+AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
+  // Set *Return to the retry code for the return value of _CrtDbgReport:
+  // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx
+  // This may also trigger just-in-time debugging via DebugBreak().
+  if (Return)
+    *Return = 1;
+  // Don't call _CrtDbgReport.
+  return TRUE;
+}
+
+#endif
+
+extern "C" void HandleAbort(int Sig) {
+  if (Sig == SIGABRT) {
+    LLVM_BUILTIN_TRAP;
+  }
+}
+
+static void InitializeThreading() {
+  if (CriticalSectionInitialized)
+    return;
+
+  // Now's the time to create the critical section. This is the first time
+  // through here, and there's only one thread.
+  InitializeCriticalSection(&CriticalSection);
+  CriticalSectionInitialized = true;
+}
+
+static void RegisterHandler() {
+  // If we cannot load up the APIs (which would be unexpected as they should
+  // exist on every version of Windows we support), we will bail out since
+  // there would be nothing to report.
+  if (!load64BitDebugHelp()) {
+    assert(false && "These APIs should always be available");
+    return;
+  }
+
+  if (RegisteredUnhandledExceptionFilter) {
+    EnterCriticalSection(&CriticalSection);
+    return;
+  }
+
+  InitializeThreading();
+
+  // Enter it immediately.  Now if someone hits CTRL/C, the console handler
+  // can't proceed until the globals are updated.
+  EnterCriticalSection(&CriticalSection);
+
+  RegisteredUnhandledExceptionFilter = true;
+  OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
+  SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
+
+  // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
+  // else multi-threading problems will ensue.
+}
+
+// RemoveFileOnSignal - The public API
+bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) {
+  RegisterHandler();
+
+  if (CleanupExecuted) {
+    if (ErrMsg)
+      *ErrMsg = "Process terminating -- cannot register for removal";
+    return true;
+  }
+
+  if (FilesToRemove == NULL)
+    FilesToRemove = new std::vector<std::string>;
+
+  FilesToRemove->push_back(Filename);
+
+  LeaveCriticalSection(&CriticalSection);
+  return false;
+}
+
+// DontRemoveFileOnSignal - The public API
+void sys::DontRemoveFileOnSignal(StringRef Filename) {
+  if (FilesToRemove == NULL)
+    return;
+
+  RegisterHandler();
+
+  std::vector<std::string>::reverse_iterator I =
+      find(reverse(*FilesToRemove), Filename);
+  if (I != FilesToRemove->rend())
+    FilesToRemove->erase(I.base()-1);
+
+  LeaveCriticalSection(&CriticalSection);
+}
+
+void sys::DisableSystemDialogsOnCrash() {
+  // Crash to stack trace handler on abort.
+  signal(SIGABRT, HandleAbort);
+
+  // The following functions are not reliably accessible on MinGW.
+#ifdef _MSC_VER
+  // We're already handling writing a "something went wrong" message.
+  _set_abort_behavior(0, _WRITE_ABORT_MSG);
+  // Disable Dr. Watson.
+  _set_abort_behavior(0, _CALL_REPORTFAULT);
+  _CrtSetReportHook(AvoidMessageBoxHook);
+#endif
+
+  // Disable standard error dialog box.
+  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
+               SEM_NOOPENFILEERRORBOX);
+  _set_error_mode(_OUT_TO_STDERR);
+}
+
+/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
+/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
+void sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
+                                       bool DisableCrashReporting) {
+  ::Argv0 = Argv0;
+
+  if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT"))
+    Process::PreventCoreFiles();
+
+  DisableSystemDialogsOnCrash();
+  RegisterHandler();
+  LeaveCriticalSection(&CriticalSection);
+}
+}
+
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is
+// missing it but mingw-w64 has it.
+extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
+#endif
+
+void llvm::sys::PrintStackTrace(raw_ostream &OS) {
+  STACKFRAME64 StackFrame = {};
+  CONTEXT Context = {};
+  ::RtlCaptureContext(&Context);
+#if defined(_M_X64)
+  StackFrame.AddrPC.Offset = Context.Rip;
+  StackFrame.AddrStack.Offset = Context.Rsp;
+  StackFrame.AddrFrame.Offset = Context.Rbp;
+#else
+  StackFrame.AddrPC.Offset = Context.Eip;
+  StackFrame.AddrStack.Offset = Context.Esp;
+  StackFrame.AddrFrame.Offset = Context.Ebp;
+#endif
+  StackFrame.AddrPC.Mode = AddrModeFlat;
+  StackFrame.AddrStack.Mode = AddrModeFlat;
+  StackFrame.AddrFrame.Mode = AddrModeFlat;
+  PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
+                           StackFrame, &Context);
+}
+
+
+void llvm::sys::SetInterruptFunction(void (*IF)()) {
+  RegisterHandler();
+  InterruptFunction = IF;
+  LeaveCriticalSection(&CriticalSection);
+}
+
+
+/// AddSignalHandler - Add a function to be called when a signal is delivered
+/// to the process.  The handler can have a cookie passed to it to identify
+/// what instance of the handler it is.
+void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
+  CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
+  RegisterHandler();
+  LeaveCriticalSection(&CriticalSection);
+}
+
+static void Cleanup() {
+  if (CleanupExecuted)
+    return;
+
+  EnterCriticalSection(&CriticalSection);
+
+  // Prevent other thread from registering new files and directories for
+  // removal, should we be executing because of the console handler callback.
+  CleanupExecuted = true;
+
+  // FIXME: open files cannot be deleted.
+  if (FilesToRemove != NULL)
+    while (!FilesToRemove->empty()) {
+      llvm::sys::fs::remove(FilesToRemove->back());
+      FilesToRemove->pop_back();
+    }
+  llvm::sys::RunSignalHandlers();
+  LeaveCriticalSection(&CriticalSection);
+}
+
+void llvm::sys::RunInterruptHandlers() {
+  // The interrupt handler may be called from an interrupt, but it may also be
+  // called manually (such as the case of report_fatal_error with no registered
+  // error handler). We must ensure that the critical section is properly
+  // initialized.
+  InitializeThreading();
+  Cleanup();
+}
+
+/// \brief Find the Windows Registry Key for a given location.
+///
+/// \returns a valid HKEY if the location exists, else NULL.
+static HKEY FindWERKey(const llvm::Twine &RegistryLocation) {
+  HKEY Key;
+  if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+                                       RegistryLocation.str().c_str(), 0,
+                                       KEY_QUERY_VALUE | KEY_READ, &Key))
+    return NULL;
+
+  return Key;
+}
+
+/// \brief Populate ResultDirectory with the value for "DumpFolder" for a given
+/// Windows Registry key.
+///
+/// \returns true if a valid value for DumpFolder exists, false otherwise.
+static bool GetDumpFolder(HKEY Key,
+                          llvm::SmallVectorImpl<char> &ResultDirectory) {
+  using llvm::sys::windows::UTF16ToUTF8;
+
+  if (!Key)
+    return false;
+
+  DWORD BufferLengthBytes = 0;
+
+  if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
+                                      NULL, NULL, &BufferLengthBytes))
+    return false;
+
+  SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes);
+
+  if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
+                                      NULL, Buffer.data(), &BufferLengthBytes))
+    return false;
+
+  DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0);
+
+  if (!ExpandBufferSize)
+    return false;
+
+  SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize);
+
+  if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(),
+                                                      ExpandBuffer.data(),
+                                                      ExpandBufferSize))
+    return false;
+
+  if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory))
+    return false;
+
+  return true;
+}
+
+/// \brief Populate ResultType with a valid MINIDUMP_TYPE based on the value of
+/// "DumpType" for a given Windows Registry key.
+///
+/// According to
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx
+/// valid values for DumpType are:
+///   * 0: Custom dump
+///   * 1: Mini dump
+///   * 2: Full dump
+/// If "Custom dump" is specified then the "CustomDumpFlags" field is read
+/// containing a bitwise combination of MINIDUMP_TYPE values.
+///
+/// \returns true if a valid value for ResultType can be set, false otherwise.
+static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) {
+  if (!Key)
+    return false;
+
+  DWORD DumpType;
+  DWORD TypeSize = sizeof(DumpType);
+  if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD,
+                                      NULL, &DumpType,
+                                      &TypeSize))
+    return false;
+
+  switch (DumpType) {
+  case 0: {
+    DWORD Flags = 0;
+    if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags",
+                                        RRF_RT_REG_DWORD, NULL, &Flags,
+                                        &TypeSize))
+      return false;
+
+    ResultType = static_cast<MINIDUMP_TYPE>(Flags);
+    break;
+  }
+  case 1:
+    ResultType = MiniDumpNormal;
+    break;
+  case 2:
+    ResultType = MiniDumpWithFullMemory;
+    break;
+  default:
+    return false;
+  }
+  return true;
+}
+
+/// \brief Write a Windows dump file containing process information that can be
+/// used for post-mortem debugging.
+///
+/// \returns zero error code if a mini dump created, actual error code
+/// otherwise.
+static std::error_code WINAPI
+WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
+  using namespace llvm;
+  using namespace llvm::sys;
+
+  std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr);
+  StringRef ProgramName;
+
+  if (MainExecutableName.empty()) {
+    // If we can't get the executable filename,
+    // things are in worse shape than we realize
+    // and we should just bail out.
+    return mapWindowsError(::GetLastError());
+  }
+
+  ProgramName = path::filename(MainExecutableName.c_str());
+
+  // The Windows Registry location as specified at
+  // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx
+  // "Collecting User-Mode Dumps" that may optionally be set to collect crash
+  // dumps in a specified location.
+  StringRef LocalDumpsRegistryLocation =
+      "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
+
+  // The key pointing to the Registry location that may contain global crash
+  // dump settings.  This will be NULL if the location can not be found.
+  ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation));
+
+  // The key pointing to the Registry location that may contain
+  // application-specific crash dump settings.  This will be NULL if the
+  // location can not be found.
+  ScopedRegHandle AppSpecificKey(
+      FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName));
+
+  // Look to see if a dump type is specified in the registry; first with the
+  // app-specific key and failing that with the global key.  If none are found
+  // default to a normal dump (GetDumpType will return false either if the key
+  // is NULL or if there is no valid DumpType value at its location).
+  MINIDUMP_TYPE DumpType;
+  if (!GetDumpType(AppSpecificKey, DumpType))
+    if (!GetDumpType(DefaultLocalDumpsKey, DumpType))
+      DumpType = MiniDumpNormal;
+
+  // Look to see if a dump location is specified in the registry; first with the
+  // app-specific key and failing that with the global key.  If none are found
+  // we'll just create the dump file in the default temporary file location
+  // (GetDumpFolder will return false either if the key is NULL or if there is
+  // no valid DumpFolder value at its location).
+  bool ExplicitDumpDirectorySet = true;
+  SmallString<MAX_PATH> DumpDirectory;
+  if (!GetDumpFolder(AppSpecificKey, DumpDirectory))
+    if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory))
+      ExplicitDumpDirectorySet = false;
+
+  int FD;
+  SmallString<MAX_PATH> DumpPath;
+
+  if (ExplicitDumpDirectorySet) {
+    if (std::error_code EC = fs::create_directories(DumpDirectory))
+      return EC;
+    if (std::error_code EC = fs::createUniqueFile(
+            Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD,
+            DumpPath))
+      return EC;
+  } else if (std::error_code EC =
+                 fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath))
+    return EC;
+
+  // Our support functions return a file descriptor but Windows wants a handle.
+  ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD)));
+
+  if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(),
+                          FileHandle, DumpType, ExceptionInfo, NULL, NULL))
+    return mapWindowsError(::GetLastError());
+
+  llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n";
+  return std::error_code();
+}
+
+static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
+  Cleanup();
+
+  // We'll automatically write a Minidump file here to help diagnose
+  // the nasty sorts of crashes that aren't 100% reproducible from a set of
+  // inputs (or in the event that the user is unable or unwilling to provide a
+  // reproducible case).
+  if (!llvm::Process::AreCoreFilesPrevented()) {
+    MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
+    ExceptionInfo.ThreadId = ::GetCurrentThreadId();
+    ExceptionInfo.ExceptionPointers = ep;
+    ExceptionInfo.ClientPointers = FALSE;
+
+    if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo))
+      llvm::errs() << "Could not write crash dump file: " << EC.message()
+                   << "\n";
+  }
+
+  // Initialize the STACKFRAME structure.
+  STACKFRAME64 StackFrame = {};
+
+#if defined(_M_X64)
+  StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
+  StackFrame.AddrPC.Mode = AddrModeFlat;
+  StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
+  StackFrame.AddrStack.Mode = AddrModeFlat;
+  StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
+  StackFrame.AddrFrame.Mode = AddrModeFlat;
+#elif defined(_M_IX86)
+  StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
+  StackFrame.AddrPC.Mode = AddrModeFlat;
+  StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
+  StackFrame.AddrStack.Mode = AddrModeFlat;
+  StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
+  StackFrame.AddrFrame.Mode = AddrModeFlat;
+#endif
+
+  HANDLE hProcess = GetCurrentProcess();
+  HANDLE hThread = GetCurrentThread();
+  PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
+                           ep->ContextRecord);
+
+  _exit(ep->ExceptionRecord->ExceptionCode);
+}
+
+static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
+  // We are running in our very own thread, courtesy of Windows.
+  EnterCriticalSection(&CriticalSection);
+  Cleanup();
+
+  // If an interrupt function has been set, go and run one it; otherwise,
+  // the process dies.
+  void (*IF)() = InterruptFunction;
+  InterruptFunction = 0;      // Don't run it on another CTRL-C.
+
+  if (IF) {
+    // Note: if the interrupt function throws an exception, there is nothing
+    // to catch it in this thread so it will kill the process.
+    IF();                     // Run it now.
+    LeaveCriticalSection(&CriticalSection);
+    return TRUE;              // Don't kill the process.
+  }
+
+  // Allow normal processing to take place; i.e., the process dies.
+  LeaveCriticalSection(&CriticalSection);
+  return FALSE;
+}
+
+#if __MINGW32__
+ // We turned these warnings off for this file so that MinGW-g++ doesn't
+ // complain about the ll format specifiers used.  Now we are turning the
+ // warnings back on.  If MinGW starts to support diagnostic stacks, we can
+ // replace this with a pop.
+ #pragma GCC diagnostic warning "-Wformat"
+ #pragma GCC diagnostic warning "-Wformat-extra-args"
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/Windows/TimeValue.inc b/third_party/llvm-subzero/lib/Support/Windows/TimeValue.inc
new file mode 100644
index 0000000..b90b4f1
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/TimeValue.inc
@@ -0,0 +1,61 @@
+//===- Win32/TimeValue.cpp - Win32 TimeValue Implementation -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Win32 implementation of the TimeValue class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WindowsSupport.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cctype>
+#include <time.h>
+
+using namespace llvm;
+using namespace llvm::sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code.
+//===----------------------------------------------------------------------===//
+
+TimeValue TimeValue::now() {
+  uint64_t ft;
+  GetSystemTimeAsFileTime(reinterpret_cast<FILETIME *>(&ft));
+
+  TimeValue t(0, 0);
+  t.fromWin32Time(ft);
+  return t;
+}
+
+std::string TimeValue::str() const {
+  std::string S;
+  struct tm *LT;
+#ifdef __MINGW32__
+  // Old versions of mingw don't have _localtime64_s. Remove this once we drop support
+  // for them.
+  time_t OurTime = time_t(this->toEpochTime());
+  LT = ::localtime(&OurTime);
+  assert(LT);
+#else
+  struct tm Storage;
+  __time64_t OurTime = this->toEpochTime();
+  int Error = ::_localtime64_s(&Storage, &OurTime);
+  assert(!Error);
+  (void)Error;
+  LT = &Storage;
+#endif
+
+  char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
+  strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", LT);
+  raw_string_ostream OS(S);
+  OS << format("%s.%.9u", static_cast<const char *>(Buffer),
+               this->nanoseconds());
+  OS.flush();
+  return S;
+}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h b/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h
new file mode 100644
index 0000000..18ecdf4
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h
@@ -0,0 +1,230 @@
+//===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines things specific to Windows implementations.  In addition to
+// providing some helpers for working with win32 APIs, this header wraps
+// <windows.h> with some portability macros.  Always include WindowsSupport.h
+// instead of including <windows.h> directly.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//===          is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
+#define LLVM_SUPPORT_WINDOWSSUPPORT_H
+
+// mingw-w64 tends to define it as 0x0502 in its headers.
+#undef _WIN32_WINNT
+#undef _WIN32_IE
+
+// Require at least Windows 7 API.
+#define _WIN32_WINNT 0x0601
+#define _WIN32_IE    0x0800 // MinGW at it again. FIXME: verify if still needed.
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h" // Get build system configuration settings
+#include "llvm/Support/Compiler.h"
+#include <system_error>
+#include <windows.h>
+#include <wincrypt.h>
+#include <cassert>
+#include <string>
+
+/// Determines if the program is running on Windows 8 or newer. This
+/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
+/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
+/// yet have VersionHelpers.h, so we have our own helper.
+inline bool RunningWindows8OrGreater() {
+  // Windows 8 is version 6.2, service pack 0.
+  OSVERSIONINFOEXW osvi = {};
+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+  osvi.dwMajorVersion = 6;
+  osvi.dwMinorVersion = 2;
+  osvi.wServicePackMajor = 0;
+
+  DWORDLONG Mask = 0;
+  Mask = VerSetConditionMask(Mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+  Mask = VerSetConditionMask(Mask, VER_MINORVERSION, VER_GREATER_EQUAL);
+  Mask = VerSetConditionMask(Mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+
+  return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION |
+                                       VER_SERVICEPACKMAJOR,
+                            Mask) != FALSE;
+}
+
+inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
+  if (!ErrMsg)
+    return true;
+  char *buffer = NULL;
+  DWORD LastError = GetLastError();
+  DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                               FORMAT_MESSAGE_FROM_SYSTEM |
+                               FORMAT_MESSAGE_MAX_WIDTH_MASK,
+                           NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
+  if (R)
+    *ErrMsg = prefix + ": " + buffer;
+  else
+    *ErrMsg = prefix + ": Unknown error";
+  *ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")";
+
+  LocalFree(buffer);
+  return R != 0;
+}
+
+template <typename HandleTraits>
+class ScopedHandle {
+  typedef typename HandleTraits::handle_type handle_type;
+  handle_type Handle;
+
+  ScopedHandle(const ScopedHandle &other); // = delete;
+  void operator=(const ScopedHandle &other); // = delete;
+public:
+  ScopedHandle()
+    : Handle(HandleTraits::GetInvalid()) {}
+
+  explicit ScopedHandle(handle_type h)
+    : Handle(h) {}
+
+  ~ScopedHandle() {
+    if (HandleTraits::IsValid(Handle))
+      HandleTraits::Close(Handle);
+  }
+
+  handle_type take() {
+    handle_type t = Handle;
+    Handle = HandleTraits::GetInvalid();
+    return t;
+  }
+
+  ScopedHandle &operator=(handle_type h) {
+    if (HandleTraits::IsValid(Handle))
+      HandleTraits::Close(Handle);
+    Handle = h;
+    return *this;
+  }
+
+  // True if Handle is valid.
+  explicit operator bool() const {
+    return HandleTraits::IsValid(Handle) ? true : false;
+  }
+
+  operator handle_type() const {
+    return Handle;
+  }
+};
+
+struct CommonHandleTraits {
+  typedef HANDLE handle_type;
+
+  static handle_type GetInvalid() {
+    return INVALID_HANDLE_VALUE;
+  }
+
+  static void Close(handle_type h) {
+    ::CloseHandle(h);
+  }
+
+  static bool IsValid(handle_type h) {
+    return h != GetInvalid();
+  }
+};
+
+struct JobHandleTraits : CommonHandleTraits {
+  static handle_type GetInvalid() {
+    return NULL;
+  }
+};
+
+struct CryptContextTraits : CommonHandleTraits {
+  typedef HCRYPTPROV handle_type;
+
+  static handle_type GetInvalid() {
+    return 0;
+  }
+
+  static void Close(handle_type h) {
+    ::CryptReleaseContext(h, 0);
+  }
+
+  static bool IsValid(handle_type h) {
+    return h != GetInvalid();
+  }
+};
+
+struct RegTraits : CommonHandleTraits {
+  typedef HKEY handle_type;
+
+  static handle_type GetInvalid() {
+    return NULL;
+  }
+
+  static void Close(handle_type h) {
+    ::RegCloseKey(h);
+  }
+
+  static bool IsValid(handle_type h) {
+    return h != GetInvalid();
+  }
+};
+
+struct FindHandleTraits : CommonHandleTraits {
+  static void Close(handle_type h) {
+    ::FindClose(h);
+  }
+};
+
+struct FileHandleTraits : CommonHandleTraits {};
+
+typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
+typedef ScopedHandle<FileHandleTraits>   ScopedFileHandle;
+typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
+typedef ScopedHandle<RegTraits>          ScopedRegHandle;
+typedef ScopedHandle<FindHandleTraits>   ScopedFindHandle;
+typedef ScopedHandle<JobHandleTraits>    ScopedJobHandle;
+
+namespace llvm {
+template <class T>
+class SmallVectorImpl;
+
+template <class T>
+typename SmallVectorImpl<T>::const_pointer
+c_str(SmallVectorImpl<T> &str) {
+  str.push_back(0);
+  str.pop_back();
+  return str.data();
+}
+
+namespace sys {
+namespace path {
+std::error_code widenPath(const Twine &Path8,
+                          SmallVectorImpl<wchar_t> &Path16);
+} // end namespace path
+
+namespace windows {
+std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
+std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
+                            SmallVectorImpl<char> &utf8);
+/// Convert from UTF16 to the current code page used in the system
+std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
+                             SmallVectorImpl<char> &utf8);
+} // end namespace windows
+} // end namespace sys
+} // end namespace llvm.
+
+#endif
diff --git a/third_party/llvm-subzero/lib/Support/circular_raw_ostream.cpp b/third_party/llvm-subzero/lib/Support/circular_raw_ostream.cpp
new file mode 100644
index 0000000..ca0d30d
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/circular_raw_ostream.cpp
@@ -0,0 +1,45 @@
+//===- circular_raw_ostream.cpp - Implement circular_raw_ostream ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements support for circular buffered streams.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/circular_raw_ostream.h"
+#include <algorithm>
+using namespace llvm;
+
+void circular_raw_ostream::write_impl(const char *Ptr, size_t Size) {
+  if (BufferSize == 0) {
+    TheStream->write(Ptr, Size);
+    return;
+  }
+
+  // Write into the buffer, wrapping if necessary.
+  while (Size != 0) {
+    unsigned Bytes =
+      std::min(unsigned(Size), unsigned(BufferSize - (Cur - BufferArray)));
+    memcpy(Cur, Ptr, Bytes);
+    Size -= Bytes;
+    Cur += Bytes;
+    if (Cur == BufferArray + BufferSize) {
+      // Reset the output pointer to the start of the buffer.
+      Cur = BufferArray;
+      Filled = true;
+    }
+  }    
+}
+
+void circular_raw_ostream::flushBufferWithBanner() {
+  if (BufferSize != 0) {
+    // Write out the buffer
+    TheStream->write(Banner, std::strlen(Banner));
+    flushBuffer();
+  }
+}
diff --git a/third_party/llvm-subzero/lib/Support/raw_os_ostream.cpp b/third_party/llvm-subzero/lib/Support/raw_os_ostream.cpp
new file mode 100644
index 0000000..44f2325
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/raw_os_ostream.cpp
@@ -0,0 +1,30 @@
+//===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements support adapting raw_ostream to std::ostream.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_os_ostream.h"
+#include <ostream>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//  raw_os_ostream
+//===----------------------------------------------------------------------===//
+
+raw_os_ostream::~raw_os_ostream() {
+  flush();
+}
+
+void raw_os_ostream::write_impl(const char *Ptr, size_t Size) {
+  OS.write(Ptr, Size);
+}
+
+uint64_t raw_os_ostream::current_pos() const { return OS.tellp(); }
diff --git a/third_party/llvm-subzero/lib/Support/raw_ostream.cpp b/third_party/llvm-subzero/lib/Support/raw_ostream.cpp
new file mode 100644
index 0000000..df4c8dc
--- /dev/null
+++ b/third_party/llvm-subzero/lib/Support/raw_ostream.cpp
@@ -0,0 +1,789 @@
+//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements support for bulk buffered stream output.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
+#include <algorithm>
+#include <cctype>
+#include <cerrno>
+#include <cstdio>
+#include <iterator>
+#include <system_error>
+#include <sys/stat.h>
+
+// <fcntl.h> may provide O_BINARY.
+#if defined(HAVE_FCNTL_H)
+# include <fcntl.h>
+#endif
+
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV)
+#  include <sys/uio.h>
+#endif
+
+#if defined(__CYGWIN__)
+#include <io.h>
+#endif
+
+#if defined(_MSC_VER)
+#include <io.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+#endif
+
+#ifdef LLVM_ON_WIN32
+#include "Windows/WindowsSupport.h"
+#endif
+
+using namespace llvm;
+
+raw_ostream::~raw_ostream() {
+  // raw_ostream's subclasses should take care to flush the buffer
+  // in their destructors.
+  assert(OutBufCur == OutBufStart &&
+         "raw_ostream destructor called with non-empty buffer!");
+
+  if (BufferMode == InternalBuffer)
+    delete [] OutBufStart;
+}
+
+// An out of line virtual method to provide a home for the class vtable.
+void raw_ostream::handle() {}
+
+size_t raw_ostream::preferred_buffer_size() const {
+  // BUFSIZ is intended to be a reasonable default.
+  return BUFSIZ;
+}
+
+void raw_ostream::SetBuffered() {
+  // Ask the subclass to determine an appropriate buffer size.
+  if (size_t Size = preferred_buffer_size())
+    SetBufferSize(Size);
+  else
+    // It may return 0, meaning this stream should be unbuffered.
+    SetUnbuffered();
+}
+
+void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
+                                   BufferKind Mode) {
+  assert(((Mode == Unbuffered && !BufferStart && Size == 0) ||
+          (Mode != Unbuffered && BufferStart && Size != 0)) &&
+         "stream must be unbuffered or have at least one byte");
+  // Make sure the current buffer is free of content (we can't flush here; the
+  // child buffer management logic will be in write_impl).
+  assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
+
+  if (BufferMode == InternalBuffer)
+    delete [] OutBufStart;
+  OutBufStart = BufferStart;
+  OutBufEnd = OutBufStart+Size;
+  OutBufCur = OutBufStart;
+  BufferMode = Mode;
+
+  assert(OutBufStart <= OutBufEnd && "Invalid size!");
+}
+
+raw_ostream &raw_ostream::operator<<(unsigned long N) {
+  // Zero is a special case.
+  if (N == 0)
+    return *this << '0';
+
+  char NumberBuffer[20];
+  char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
+  char *CurPtr = EndPtr;
+
+  while (N) {
+    *--CurPtr = '0' + char(N % 10);
+    N /= 10;
+  }
+  return write(CurPtr, EndPtr-CurPtr);
+}
+
+raw_ostream &raw_ostream::operator<<(long N) {
+  if (N <  0) {
+    *this << '-';
+    // Avoid undefined behavior on LONG_MIN with a cast.
+    N = -(unsigned long)N;
+  }
+
+  return this->operator<<(static_cast<unsigned long>(N));
+}
+
+raw_ostream &raw_ostream::operator<<(unsigned long long N) {
+  // Output using 32-bit div/mod when possible.
+  if (N == static_cast<unsigned long>(N))
+    return this->operator<<(static_cast<unsigned long>(N));
+
+  char NumberBuffer[20];
+  char *EndPtr = std::end(NumberBuffer);
+  char *CurPtr = EndPtr;
+
+  while (N) {
+    *--CurPtr = '0' + char(N % 10);
+    N /= 10;
+  }
+  return write(CurPtr, EndPtr-CurPtr);
+}
+
+raw_ostream &raw_ostream::operator<<(long long N) {
+  if (N < 0) {
+    *this << '-';
+    // Avoid undefined behavior on INT64_MIN with a cast.
+    N = -(unsigned long long)N;
+  }
+
+  return this->operator<<(static_cast<unsigned long long>(N));
+}
+
+raw_ostream &raw_ostream::write_hex(unsigned long long N) {
+  // Zero is a special case.
+  if (N == 0)
+    return *this << '0';
+
+  char NumberBuffer[16];
+  char *EndPtr = std::end(NumberBuffer);
+  char *CurPtr = EndPtr;
+
+  while (N) {
+    unsigned char x = static_cast<unsigned char>(N) % 16;
+    *--CurPtr = hexdigit(x, /*LowerCase*/true);
+    N /= 16;
+  }
+
+  return write(CurPtr, EndPtr-CurPtr);
+}
+
+raw_ostream &raw_ostream::write_escaped(StringRef Str,
+                                        bool UseHexEscapes) {
+  for (unsigned char c : Str) {
+    switch (c) {
+    case '\\':
+      *this << '\\' << '\\';
+      break;
+    case '\t':
+      *this << '\\' << 't';
+      break;
+    case '\n':
+      *this << '\\' << 'n';
+      break;
+    case '"':
+      *this << '\\' << '"';
+      break;
+    default:
+      if (std::isprint(c)) {
+        *this << c;
+        break;
+      }
+
+      // Write out the escaped representation.
+      if (UseHexEscapes) {
+        *this << '\\' << 'x';
+        *this << hexdigit((c >> 4 & 0xF));
+        *this << hexdigit((c >> 0) & 0xF);
+      } else {
+        // Always use a full 3-character octal escape.
+        *this << '\\';
+        *this << char('0' + ((c >> 6) & 7));
+        *this << char('0' + ((c >> 3) & 7));
+        *this << char('0' + ((c >> 0) & 7));
+      }
+    }
+  }
+
+  return *this;
+}
+
+raw_ostream &raw_ostream::operator<<(const void *P) {
+  *this << '0' << 'x';
+
+  return write_hex((uintptr_t) P);
+}
+
+raw_ostream &raw_ostream::operator<<(double N) {
+#ifdef _WIN32
+  // On MSVCRT and compatible, output of %e is incompatible to Posix
+  // by default. Number of exponent digits should be at least 2. "%+03d"
+  // FIXME: Implement our formatter to here or Support/Format.h!
+#if defined(__MINGW32__)
+  // FIXME: It should be generic to C++11.
+  if (N == 0.0 && std::signbit(N))
+    return *this << "-0.000000e+00";
+#else
+  int fpcl = _fpclass(N);
+
+  // negative zero
+  if (fpcl == _FPCLASS_NZ)
+    return *this << "-0.000000e+00";
+#endif
+
+  char buf[16];
+  unsigned len;
+  len = format("%e", N).snprint(buf, sizeof(buf));
+  if (len <= sizeof(buf) - 2) {
+    if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') {
+      int cs = buf[len - 4];
+      if (cs == '+' || cs == '-') {
+        int c1 = buf[len - 2];
+        int c0 = buf[len - 1];
+        if (isdigit(static_cast<unsigned char>(c1)) &&
+            isdigit(static_cast<unsigned char>(c0))) {
+          // Trim leading '0': "...e+012" -> "...e+12\0"
+          buf[len - 3] = c1;
+          buf[len - 2] = c0;
+          buf[--len] = 0;
+        }
+      }
+    }
+    return this->operator<<(buf);
+  }
+#endif
+  return this->operator<<(format("%e", N));
+}
+
+void raw_ostream::flush_nonempty() {
+  assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
+  size_t Length = OutBufCur - OutBufStart;
+  OutBufCur = OutBufStart;
+  write_impl(OutBufStart, Length);
+}
+
+raw_ostream &raw_ostream::write(unsigned char C) {
+  // Group exceptional cases into a single branch.
+  if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {
+    if (LLVM_UNLIKELY(!OutBufStart)) {
+      if (BufferMode == Unbuffered) {
+        write_impl(reinterpret_cast<char*>(&C), 1);
+        return *this;
+      }
+      // Set up a buffer and start over.
+      SetBuffered();
+      return write(C);
+    }
+
+    flush_nonempty();
+  }
+
+  *OutBufCur++ = C;
+  return *this;
+}
+
+raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
+  // Group exceptional cases into a single branch.
+  if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {
+    if (LLVM_UNLIKELY(!OutBufStart)) {
+      if (BufferMode == Unbuffered) {
+        write_impl(Ptr, Size);
+        return *this;
+      }
+      // Set up a buffer and start over.
+      SetBuffered();
+      return write(Ptr, Size);
+    }
+
+    size_t NumBytes = OutBufEnd - OutBufCur;
+
+    // If the buffer is empty at this point we have a string that is larger
+    // than the buffer. Directly write the chunk that is a multiple of the
+    // preferred buffer size and put the remainder in the buffer.
+    if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) {
+      assert(NumBytes != 0 && "undefined behavior");
+      size_t BytesToWrite = Size - (Size % NumBytes);
+      write_impl(Ptr, BytesToWrite);
+      size_t BytesRemaining = Size - BytesToWrite;
+      if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) {
+        // Too much left over to copy into our buffer.
+        return write(Ptr + BytesToWrite, BytesRemaining);
+      }
+      copy_to_buffer(Ptr + BytesToWrite, BytesRemaining);
+      return *this;
+    }
+
+    // We don't have enough space in the buffer to fit the string in. Insert as
+    // much as possible, flush and start over with the remainder.
+    copy_to_buffer(Ptr, NumBytes);
+    flush_nonempty();
+    return write(Ptr + NumBytes, Size - NumBytes);
+  }
+
+  copy_to_buffer(Ptr, Size);
+
+  return *this;
+}
+
+void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {
+  assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!");
+
+  // Handle short strings specially, memcpy isn't very good at very short
+  // strings.
+  switch (Size) {
+  case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH;
+  case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH;
+  case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH;
+  case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH;
+  case 0: break;
+  default:
+    memcpy(OutBufCur, Ptr, Size);
+    break;
+  }
+
+  OutBufCur += Size;
+}
+
+// Formatted output.
+raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
+  // If we have more than a few bytes left in our output buffer, try
+  // formatting directly onto its end.
+  size_t NextBufferSize = 127;
+  size_t BufferBytesLeft = OutBufEnd - OutBufCur;
+  if (BufferBytesLeft > 3) {
+    size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
+
+    // Common case is that we have plenty of space.
+    if (BytesUsed <= BufferBytesLeft) {
+      OutBufCur += BytesUsed;
+      return *this;
+    }
+
+    // Otherwise, we overflowed and the return value tells us the size to try
+    // again with.
+    NextBufferSize = BytesUsed;
+  }
+
+  // If we got here, we didn't have enough space in the output buffer for the
+  // string.  Try printing into a SmallVector that is resized to have enough
+  // space.  Iterate until we win.
+  SmallVector<char, 128> V;
+
+  while (true) {
+    V.resize(NextBufferSize);
+
+    // Try formatting into the SmallVector.
+    size_t BytesUsed = Fmt.print(V.data(), NextBufferSize);
+
+    // If BytesUsed fit into the vector, we win.
+    if (BytesUsed <= NextBufferSize)
+      return write(V.data(), BytesUsed);
+
+    // Otherwise, try again with a new size.
+    assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
+    NextBufferSize = BytesUsed;
+  }
+}
+
+raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
+  unsigned Len = FS.Str.size(); 
+  int PadAmount = FS.Width - Len;
+  if (FS.RightJustify && (PadAmount > 0))
+    this->indent(PadAmount);
+  this->operator<<(FS.Str);
+  if (!FS.RightJustify && (PadAmount > 0))
+    this->indent(PadAmount);
+  return *this;
+}
+
+raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
+  if (FN.Hex) {
+    unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4;
+    unsigned PrefixChars = FN.HexPrefix ? 2 : 0;
+    unsigned Width = std::max(FN.Width, Nibbles + PrefixChars);
+
+    char NumberBuffer[20] = "0x0000000000000000";
+    if (!FN.HexPrefix)
+      NumberBuffer[1] = '0';
+    char *EndPtr = NumberBuffer+Width;
+    char *CurPtr = EndPtr;
+    unsigned long long N = FN.HexValue;
+    while (N) {
+      unsigned char x = static_cast<unsigned char>(N) % 16;
+      *--CurPtr = hexdigit(x, !FN.Upper);
+      N /= 16;
+    }
+
+    return write(NumberBuffer, Width);
+  } else {
+    // Zero is a special case.
+    if (FN.DecValue == 0) {
+      this->indent(FN.Width-1);
+      return *this << '0';
+    }
+    char NumberBuffer[32];
+    char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
+    char *CurPtr = EndPtr;
+    bool Neg = (FN.DecValue < 0);
+    uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue;
+    while (N) {
+      *--CurPtr = '0' + char(N % 10);
+      N /= 10;
+    }
+    int Len = EndPtr - CurPtr;
+    int Pad = FN.Width - Len;
+    if (Neg) 
+      --Pad;
+    if (Pad > 0)
+      this->indent(Pad);
+    if (Neg)
+      *this << '-';
+    return write(CurPtr, Len);
+  }
+}
+
+/// indent - Insert 'NumSpaces' spaces.
+raw_ostream &raw_ostream::indent(unsigned NumSpaces) {
+  static const char Spaces[] = "                                "
+                               "                                "
+                               "                ";
+
+  // Usually the indentation is small, handle it with a fastpath.
+  if (NumSpaces < array_lengthof(Spaces))
+    return write(Spaces, NumSpaces);
+
+  while (NumSpaces) {
+    unsigned NumToWrite = std::min(NumSpaces,
+                                   (unsigned)array_lengthof(Spaces)-1);
+    write(Spaces, NumToWrite);
+    NumSpaces -= NumToWrite;
+  }
+  return *this;
+}
+
+//===----------------------------------------------------------------------===//
+//  Formatted Output
+//===----------------------------------------------------------------------===//
+
+// Out of line virtual method.
+void format_object_base::home() {
+}
+
+//===----------------------------------------------------------------------===//
+//  raw_fd_ostream
+//===----------------------------------------------------------------------===//
+
+static int getFD(StringRef Filename, std::error_code &EC,
+                 sys::fs::OpenFlags Flags) {
+  // Handle "-" as stdout. Note that when we do this, we consider ourself
+  // the owner of stdout. This means that we can do things like close the
+  // file descriptor when we're done and set the "binary" flag globally.
+  if (Filename == "-") {
+    EC = std::error_code();
+    // If user requested binary then put stdout into binary mode if
+    // possible.
+    if (!(Flags & sys::fs::F_Text))
+      sys::ChangeStdoutToBinary();
+    return STDOUT_FILENO;
+  }
+
+  int FD;
+  EC = sys::fs::openFileForWrite(Filename, FD, Flags);
+  if (EC)
+    return -1;
+
+  return FD;
+}
+
+raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
+                               sys::fs::OpenFlags Flags)
+    : raw_fd_ostream(getFD(Filename, EC, Flags), true) {}
+
+/// FD is the file descriptor that this writes to.  If ShouldClose is true, this
+/// closes the file when the stream is destroyed.
+raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
+    : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose),
+      Error(false) {
+  if (FD < 0 ) {
+    ShouldClose = false;
+    return;
+  }
+
+  // Get the starting position.
+  off_t loc = ::lseek(FD, 0, SEEK_CUR);
+#ifdef LLVM_ON_WIN32
+  // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.
+  sys::fs::file_status Status;
+  std::error_code EC = status(FD, Status);
+  SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file;
+#else
+  SupportsSeeking = loc != (off_t)-1;
+#endif
+  if (!SupportsSeeking)
+    pos = 0;
+  else
+    pos = static_cast<uint64_t>(loc);
+}
+
+raw_fd_ostream::~raw_fd_ostream() {
+  if (FD >= 0) {
+    flush();
+    if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD))
+      error_detected();
+  }
+
+#ifdef __MINGW32__
+  // On mingw, global dtors should not call exit().
+  // report_fatal_error() invokes exit(). We know report_fatal_error()
+  // might not write messages to stderr when any errors were detected
+  // on FD == 2.
+  if (FD == 2) return;
+#endif
+
+  // If there are any pending errors, report them now. Clients wishing
+  // to avoid report_fatal_error calls should check for errors with
+  // has_error() and clear the error flag with clear_error() before
+  // destructing raw_ostream objects which may have errors.
+  if (has_error())
+    report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false);
+}
+
+void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
+  assert(FD >= 0 && "File already closed.");
+  pos += Size;
+
+#ifndef LLVM_ON_WIN32
+  bool ShouldWriteInChunks = false;
+#else
+  // Writing a large size of output to Windows console returns ENOMEM. It seems
+  // that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and
+  // the latter has a size limit (66000 bytes or less, depending on heap usage).
+  bool ShouldWriteInChunks = !!::_isatty(FD) && !RunningWindows8OrGreater();
+#endif
+
+  do {
+    size_t ChunkSize = Size;
+    if (ChunkSize > 32767 && ShouldWriteInChunks)
+        ChunkSize = 32767;
+
+    ssize_t ret = ::write(FD, Ptr, ChunkSize);
+
+    if (ret < 0) {
+      // If it's a recoverable error, swallow it and retry the write.
+      //
+      // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since
+      // raw_ostream isn't designed to do non-blocking I/O. However, some
+      // programs, such as old versions of bjam, have mistakenly used
+      // O_NONBLOCK. For compatibility, emulate blocking semantics by
+      // spinning until the write succeeds. If you don't want spinning,
+      // don't use O_NONBLOCK file descriptors with raw_ostream.
+      if (errno == EINTR || errno == EAGAIN
+#ifdef EWOULDBLOCK
+          || errno == EWOULDBLOCK
+#endif
+          )
+        continue;
+
+      // Otherwise it's a non-recoverable error. Note it and quit.
+      error_detected();
+      break;
+    }
+
+    // The write may have written some or all of the data. Update the
+    // size and buffer pointer to reflect the remainder that needs
+    // to be written. If there are no bytes left, we're done.
+    Ptr += ret;
+    Size -= ret;
+  } while (Size > 0);
+}
+
+void raw_fd_ostream::close() {
+  assert(ShouldClose);
+  ShouldClose = false;
+  flush();
+  if (sys::Process::SafelyCloseFileDescriptor(FD))
+    error_detected();
+  FD = -1;
+}
+
+uint64_t raw_fd_ostream::seek(uint64_t off) {
+  assert(SupportsSeeking && "Stream does not support seeking!");
+  flush();
+  pos = ::lseek(FD, off, SEEK_SET);
+  if (pos == (uint64_t)-1)
+    error_detected();
+  return pos;
+}
+
+void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size,
+                                 uint64_t Offset) {
+  uint64_t Pos = tell();
+  seek(Offset);
+  write(Ptr, Size);
+  seek(Pos);
+}
+
+size_t raw_fd_ostream::preferred_buffer_size() const {
+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix)
+  // Windows and Minix have no st_blksize.
+  assert(FD >= 0 && "File not yet open!");
+  struct stat statbuf;
+  if (fstat(FD, &statbuf) != 0)
+    return 0;
+
+  // If this is a terminal, don't use buffering. Line buffering
+  // would be a more traditional thing to do, but it's not worth
+  // the complexity.
+  if (S_ISCHR(statbuf.st_mode) && isatty(FD))
+    return 0;
+  // Return the preferred block size.
+  return statbuf.st_blksize;
+#else
+  return raw_ostream::preferred_buffer_size();
+#endif
+}
+
+raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
+                                         bool bg) {
+  if (sys::Process::ColorNeedsFlush())
+    flush();
+  const char *colorcode =
+    (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
+    : sys::Process::OutputColor(colors, bold, bg);
+  if (colorcode) {
+    size_t len = strlen(colorcode);
+    write(colorcode, len);
+    // don't account colors towards output characters
+    pos -= len;
+  }
+  return *this;
+}
+
+raw_ostream &raw_fd_ostream::resetColor() {
+  if (sys::Process::ColorNeedsFlush())
+    flush();
+  const char *colorcode = sys::Process::ResetColor();
+  if (colorcode) {
+    size_t len = strlen(colorcode);
+    write(colorcode, len);
+    // don't account colors towards output characters
+    pos -= len;
+  }
+  return *this;
+}
+
+raw_ostream &raw_fd_ostream::reverseColor() {
+  if (sys::Process::ColorNeedsFlush())
+    flush();
+  const char *colorcode = sys::Process::OutputReverse();
+  if (colorcode) {
+    size_t len = strlen(colorcode);
+    write(colorcode, len);
+    // don't account colors towards output characters
+    pos -= len;
+  }
+  return *this;
+}
+
+bool raw_fd_ostream::is_displayed() const {
+  return sys::Process::FileDescriptorIsDisplayed(FD);
+}
+
+bool raw_fd_ostream::has_colors() const {
+  return sys::Process::FileDescriptorHasColors(FD);
+}
+
+//===----------------------------------------------------------------------===//
+//  outs(), errs(), nulls()
+//===----------------------------------------------------------------------===//
+
+/// outs() - This returns a reference to a raw_ostream for standard output.
+/// Use it like: outs() << "foo" << "bar";
+raw_ostream &llvm::outs() {
+  // Set buffer settings to model stdout behavior.  Delete the file descriptor
+  // when the program exits, forcing error detection.  This means that if you
+  // ever call outs(), you can't open another raw_fd_ostream on stdout, as we'll
+  // close stdout twice and print an error the second time.
+  std::error_code EC;
+  static raw_fd_ostream S("-", EC, sys::fs::F_None);
+  assert(!EC);
+  return S;
+}
+
+/// errs() - This returns a reference to a raw_ostream for standard error.
+/// Use it like: errs() << "foo" << "bar";
+raw_ostream &llvm::errs() {
+  // Set standard error to be unbuffered by default.
+  static raw_fd_ostream S(STDERR_FILENO, false, true);
+  return S;
+}
+
+/// nulls() - This returns a reference to a raw_ostream which discards output.
+raw_ostream &llvm::nulls() {
+  static raw_null_ostream S;
+  return S;
+}
+
+//===----------------------------------------------------------------------===//
+//  raw_string_ostream
+//===----------------------------------------------------------------------===//
+
+raw_string_ostream::~raw_string_ostream() {
+  flush();
+}
+
+void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
+  OS.append(Ptr, Size);
+}
+
+//===----------------------------------------------------------------------===//
+//  raw_svector_ostream
+//===----------------------------------------------------------------------===//
+
+uint64_t raw_svector_ostream::current_pos() const { return OS.size(); }
+
+void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
+  OS.append(Ptr, Ptr + Size);
+}
+
+void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
+                                      uint64_t Offset) {
+  memcpy(OS.data() + Offset, Ptr, Size);
+}
+
+//===----------------------------------------------------------------------===//
+//  raw_null_ostream
+//===----------------------------------------------------------------------===//
+
+raw_null_ostream::~raw_null_ostream() {
+#ifndef NDEBUG
+  // ~raw_ostream asserts that the buffer is empty. This isn't necessary
+  // with raw_null_ostream, but it's better to have raw_null_ostream follow
+  // the rules than to change the rules just for raw_null_ostream.
+  flush();
+#endif
+}
+
+void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
+}
+
+uint64_t raw_null_ostream::current_pos() const {
+  return 0;
+}
+
+void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,
+                                   uint64_t Offset) {}