Commits

ebo  committed 3cce85d

Updated to LLVM 3.3, begin adding guard-lifting.

  • Participants
  • Parent commits 864cd20

Comments (0)

Files changed (3)

 # HG changeset patch
-# Parent 2d146914d446edd1f9c66921c1d11d67d47e66be
+# Parent 7c2b521aaaa9ab47f9b4118cdc1fa7ff535c7128
 
 diff --git a/.hgignore b/.hgignore
 --- a/.hgignore
 +++ b/.hgignore
-@@ -48,6 +48,8 @@
+@@ -49,6 +49,8 @@
  *.pyd
  *.cover
  *~
  Lib/lib2to3/*.pickle
  Lib/test/data/*
  Misc/*.wpu
-@@ -88,3 +90,4 @@
+@@ -89,3 +91,4 @@
  .coverage
  coverage/
  htmlcov/
 +#include "JIT/global_jit_data.h"
 +
 +#include "llvm/ExecutionEngine/ExecutionEngine.h"
-+#include "llvm/Target/TargetData.h"
++#include "llvm/IR/DataLayout.h"
 +
 +unsigned int
 +_PyTypeBuilder_GetFieldIndexFromOffset(
 +    llvm::StructType *type, size_t offset)
 +{
-+    const llvm::TargetData *target_data =
-+        PyGlobalJITData::Get()->getExecutionEngine()->getTargetData();
-+    const llvm::StructLayout *layout = target_data->getStructLayout(type);
++    const llvm::DataLayout *data_layout =
++        PyGlobalJITData::Get()->getExecutionEngine()->getDataLayout();
++    const llvm::StructLayout *layout = data_layout->getStructLayout(type);
 +    unsigned int index = layout->getElementContainingOffset(offset);
 +    assert(layout->getElementOffset(index) == offset &&
 +           "offset must be at start of element");
 +
 +#include "global_jit_data.h"
 +
-+#include "llvm/Module.h"
-+#include "llvm/Support/IRBuilder.h"
-+#include "llvm/Support/TypeBuilder.h"
++#include "llvm/IR/Module.h"
++#include "llvm/IR/IRBuilder.h"
++#include "llvm/IR/TypeBuilder.h"
 +
 +template<typename T>
 +class PyTypeBuilder : public llvm::TypeBuilder<T, false> {};
 @@ -0,0 +1,81 @@
 +#include "JIT/SingleFunctionInliner.h"
 +
-+#include "llvm/Attributes.h"
-+#include "llvm/BasicBlock.h"
-+#include "llvm/Function.h"
-+#include "llvm/Instructions.h"
-+#include "llvm/Module.h"
++#include "llvm/IR/Attributes.h"
++#include "llvm/IR/BasicBlock.h"
++#include "llvm/IR/Function.h"
++#include "llvm/IR/Instructions.h"
++#include "llvm/IR/Module.h"
 +#include "llvm/Pass.h"
 +#include "llvm/Transforms/Utils/Cloning.h"
 +
 +namespace {
 +
-+namespace Attribute = llvm::Attribute;
++using llvm::Attribute;
 +using llvm::BasicBlock;
 +using llvm::CallInst;
 +using llvm::Function;
 +                        continue;
 +                }
 +                if (!called_function->isDeclaration() &&
-+                    called_function->hasFnAttr(Attribute::AlwaysInline)) {
++                    called_function->hasFnAttribute(Attribute::AlwaysInline)) {
 +                    call_sites.push_back(call);
 +                }
 +            }
 new file mode 100644
 --- /dev/null
 +++ b/JIT/global_jit_data.cc
-@@ -0,0 +1,194 @@
+@@ -0,0 +1,196 @@
 +#include "Python.h"
 +
 +#include "osdefs.h"
 +#include "llvm/Analysis/Verifier.h"
 +#include "llvm/Bitcode/ReaderWriter.h"
 +#include "llvm/ExecutionEngine/JIT.h"
-+#include "llvm/Function.h"
-+#include "llvm/Module.h"
++#include "llvm/IR/Function.h"
++#include "llvm/IR/Module.h"
 +#include "llvm/Support/Path.h"
 +#include "llvm/Support/raw_ostream.h"
 +#include "llvm/Support/system_error.h"
-+#include "llvm/Target/TargetData.h"
++#include "llvm/IR/DataLayout.h"
++// #include "llvm/Target/TargetData.h"
 +#include "llvm/Transforms/Scalar.h"
 +#include <llvm/ExecutionEngine/ExecutionEngine.h>
 +#include <llvm/Support/MemoryBuffer.h>
 +  this->opt_ = new llvm::FunctionPassManager(this->module_);
 +
 +#ifdef Py_DEBUG
-+  this->opt_->add(new llvm::TargetData(*engine_->getTargetData()));
++  // this->opt_->add(new llvm::TargetData(*engine_->getTargetData()));
++  this->opt_->add(new llvm::DataLayout(*engine_->getDataLayout()));
 +  // this->opt_->add(PyCreateSingleFunctionInliningPass());
 +  this->opt_->add(llvm::createPromoteMemoryToRegisterPass());
 +  this->opt_->add(llvm::createInstructionCombiningPass());
 +#include "frameobject.h"
 +#include "global_jit_data_fwd.h"
 +
-+#include "llvm/LLVMContext.h"
++#include "llvm/IR/LLVMContext.h"
 +#include "llvm/PassManager.h"
 +
 +#include <vector>
 +#include "JIT/jit_fstate.h"
 +#include "JIT/PyTypeBuilder.h"
 +
-+#include "llvm/Type.h"
-+#include "llvm/Support/IRBuilder.h"
++#include "llvm/IR/Type.h"
++#include "llvm/IR/IRBuilder.h"
 +
 +#include <vector>
 +
 +#include "JIT/jit_fstate.h"
 +#include "JIT/PyTypeBuilder.h"
 +
-+#include "llvm/Module.h"
-+#include "llvm/Type.h"
-+#include "llvm/Constant.h"
-+#include "llvm/Constants.h"
-+#include "llvm/Support/TypeBuilder.h"
++#include "llvm/IR/Module.h"
++#include "llvm/IR/Type.h"
++#include "llvm/IR/Constant.h"
++#include "llvm/IR/Constants.h"
++#include "llvm/IR/TypeBuilder.h"
 +#include "llvm/ExecutionEngine/ExecutionEngine.h"
 +
 +#include <string>
 +                                       "#u#trace",
 +                                       this->module_)),
 +      builder_(this->context_,
-+               llvm::TargetFolder(jit_data_->getExecutionEngine()->getTargetData()))
++               llvm::TargetFolder(jit_data_->getExecutionEngine()->getDataLayout()))
 +  {
 +  }
 +
 +#include "JIT/global_jit_data.h"
 +#include "JIT/PyTypeBuilder.h"
 +
-+#include "llvm/LLVMContext.h"
-+#include "llvm/Support/IRBuilder.h"
++#include "llvm/IR/LLVMContext.h"
++#include "llvm/IR/IRBuilder.h"
 +#include "llvm/Support/TargetFolder.h"
 +#include "llvm/ADT/Twine.h"
 +
  LDLIBRARYDIR=   @LDLIBRARYDIR@
  INSTSONAME=	@INSTSONAME@
  
-@@ -334,7 +348,7 @@
+@@ -338,7 +352,7 @@
  		Python/asdl.o \
  		Python/ast.o \
  		Python/bltinmodule.o \
  		Python/compile.o \
  		Python/codecs.o \
  		Python/dynamic_annotations.o \
-@@ -377,6 +391,21 @@
+@@ -381,6 +395,21 @@
  		$(MACHDEP_OBJS) \
  		$(THREADOBJ)
  
  
  ##########################################################################
  # Objects
-@@ -471,8 +500,8 @@
+@@ -475,8 +504,8 @@
  
  
  # Build the interpreter
  
  platform: $(BUILDPYTHON) pybuilddir.txt
  	$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print(get_platform()+"-"+sys.version[0:3])' >platform
-@@ -497,33 +526,33 @@
+@@ -502,33 +531,33 @@
  
  # Build static library
  # avoid long command lines, same as LIBRARY_OBJS
  
  # Copy up the gdb python hooks into a position where they can be automatically
  # loaded by gdb during Lib/test/test_gdb.py
-@@ -562,7 +591,7 @@
+@@ -567,7 +596,7 @@
  # for a shared core library; otherwise, this rule is a noop.
  $(DLLLIBRARY) libpython$(VERSION).dll.a: $(LIBRARY_OBJS)
  	if test -n "$(DLLLIBRARY)"; then \
  			$(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST); \
  	else true; \
  	fi
-@@ -597,7 +626,7 @@
+@@ -602,7 +631,7 @@
  	fi
  
  Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
  
  ############################################################################
  # Importlib
-@@ -636,10 +665,10 @@
+@@ -641,10 +670,10 @@
  		-o $@ $(srcdir)/Modules/getpath.c
  
  Modules/python.o: $(srcdir)/Modules/python.c
  
  Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c $(srcdir)/Modules/posixmodule.h
  
-@@ -744,7 +773,7 @@
+@@ -749,7 +778,7 @@
  $(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
  	$(OPCODETARGETGEN) $(OPCODETARGETS_H)
  
  
  Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \
  				$(BYTESTR_DEPS)
-@@ -842,11 +871,35 @@
+@@ -847,11 +876,35 @@
  		$(srcdir)/Include/unicodeobject.h \
  		$(srcdir)/Include/warnings.h \
  		$(srcdir)/Include/weakrefobject.h \
  
  ######################################################################
  
-@@ -1203,6 +1256,7 @@
+@@ -1209,6 +1262,7 @@
  			echo Skip install of $(LIBRARY) - use make frameworkinstall; \
  		fi; \
  	fi
  	$(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c
  	$(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o
  	$(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in
-@@ -1331,6 +1385,16 @@
+@@ -1337,6 +1391,16 @@
  .c.o:
  	$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<
  
  # Run reindent on the library
  reindent:
  	./$(BUILDPYTHON) $(srcdir)/Tools/scripts/reindent.py -r $(srcdir)/Lib
-@@ -1388,6 +1452,8 @@
+@@ -1394,6 +1458,8 @@
  	find build -name 'fficonfig.h' -exec rm -f {} ';' || true
  	find build -name '*.py' -exec rm -f {} ';' || true
  	find build -name '*.py[co]' -exec rm -f {} ';' || true
 diff --git a/Python/pythonrun.c b/Python/pythonrun.c
 --- a/Python/pythonrun.c
 +++ b/Python/pythonrun.c
-@@ -277,6 +277,9 @@
+@@ -281,6 +281,9 @@
  
      _PyRandom_Init();
  
      interp = PyInterpreterState_New();
      if (interp == NULL)
          Py_FatalError("Py_Initialize: can't make first interpreter");
-@@ -490,6 +493,7 @@
+@@ -494,6 +497,7 @@
       * the threads created via Threading.
       */
      call_py_exitfuncs();
  
      /* Get current thread state and interpreter pointer */
      tstate = PyThreadState_GET();
-@@ -610,6 +614,7 @@
+@@ -614,6 +618,7 @@
      PyFloat_Fini();
      PyDict_Fini();
      PySlice_Fini();
 diff --git a/configure b/configure
 --- a/configure
 +++ b/configure
-@@ -658,6 +658,7 @@
+@@ -660,6 +660,7 @@
  OTHER_LIBTOOL_OPT
  UNIVERSAL_ARCH_FLAGS
  BASECFLAGS
  OPT
  ABIFLAGS
  LN
-@@ -674,6 +675,7 @@
+@@ -676,6 +677,7 @@
  AR
  RANLIB
  USE_INLINE
  GNULD
  LINKCC
  LDVERSION
-@@ -701,6 +703,13 @@
+@@ -703,6 +705,13 @@
  LDFLAGS
  CFLAGS
  CC
  EXPORT_MACOSX_DEPLOYMENT_TARGET
  CONFIGURE_MACOSX_DEPLOYMENT_TARGET
  SGI_ABI
-@@ -783,6 +792,7 @@
+@@ -785,6 +794,7 @@
  with_framework_name
  enable_framework
  with_gcc
  with_cxx_main
  with_suffix
  enable_shared
-@@ -812,6 +822,7 @@
+@@ -816,6 +826,7 @@
  host_alias
  target_alias
  MACHDEP
  CC
  CFLAGS
  LDFLAGS
-@@ -1454,6 +1465,11 @@
+@@ -1458,6 +1469,11 @@
                            specify an alternate name of the framework built
                            with --enable-framework
    --without-gcc           never use gcc
    --with-cxx-main=<compiler>
                            compile main() and link python executable with C++
                            compiler
-@@ -1487,6 +1503,7 @@
+@@ -1495,6 +1511,7 @@
  
  Some influential environment variables:
    MACHDEP     name for machine-dependent library files
    CC          C compiler command
    CFLAGS      C compiler flags
    LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-@@ -3493,6 +3510,240 @@
+@@ -3501,6 +3518,240 @@
  (it is also a good idea to do 'make clean' before compiling)" "$LINENO" 5
  fi
  
  # Don't let AC_PROG_CC set the default CFLAGS. It normally sets -g -O2
  # when the compiler supports them, but we don't always want -O2, and
  # we set -g later.
-@@ -4372,14 +4623,26 @@
+@@ -4380,14 +4631,26 @@
  	esac
  else
  
  preset_cxx="$CXX"
  if test -z "$CXX"
  then
-@@ -5453,6 +5716,12 @@
+@@ -5461,6 +5724,12 @@
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GNULD" >&5
  $as_echo "$GNULD" >&6; }
  
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
  $as_echo_n "checking for inline... " >&6; }
  if ${ac_cv_c_inline+:} false; then :
-@@ -6207,6 +6476,7 @@
+@@ -6215,6 +6484,7 @@
  # tweak OPT based on compiler and platform, only if the user didn't set
  # it on the command line
  
  if test "${OPT-unset}" = "unset"
  then
      case $GCC in
-@@ -6231,22 +6501,28 @@
+@@ -6239,22 +6509,28 @@
  		# Optimization messes up debuggers, so turn it off for
  		# debug builds.
  		OPT="-g -O0 -Wall $STRICT_PROTO"
  	;;
      esac
  fi
-@@ -14996,7 +15272,7 @@
+@@ -15044,7 +15320,7 @@
  done
  
  
  	;;
      esac
  fi
-@@ -4541,7 +4636,7 @@
+@@ -4569,7 +4664,7 @@
  done
  
  AC_SUBST(SRCDIRS)
+# HG changeset patch
+# Parent 47bc8478892fadd73c6677ebf02152905af3575a
+
+diff -r 47bc8478892f JIT/jit_analyse.cc
+--- a/JIT/jit_analyse.cc	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_analyse.cc	Fri Nov 01 23:00:19 2013 +0100
+@@ -5,6 +5,7 @@
+ #include "JIT/global_jit_data.h"
+ #include "JIT/jit_fbuilder.h"
+ #include "JIT/jit_tracer.h"
++#include "JIT/jit_fanalysis.h"
+ 
+ #include <iostream>
+ 
+@@ -33,11 +34,11 @@
+                  bool inplace);
+ 
+   JITBasicFunction *
+-  JITTraceRoot::analyse()
++  JITTraceRoot::analyse(const std::vector<std::string> &varnames)
+   {
+     JITBasicFunction *bfunc = new JITBasicFunction();
+     JITStack stack(bfunc);
+-    JITLocals locals(bfunc);
++    JITLocals locals(bfunc, varnames);
+     JITOpBuilder opb(bfunc);
+ 
+     assert(parts.size() > 0);
+@@ -113,6 +114,8 @@
+     int oparg = iter->oparg;
+     int flag = iter->flag;
+ 
++    (void) oparg;
++
+     // std::cout << "PC " << pc << " " << stack.stack.size() << "\n";
+     opb.createOpcodeInfo(pc, opid, stack, locals);
+ 
+@@ -187,7 +190,7 @@
+ 
+       case LOAD_FAST:
+         v = locals.Load(oparg);
+-        if (!hasNullGuard(v)) {
++        if (canBeNull(v)) {
+           opb.createGuardNull(v, BH_LOAD_FAST_FAIL, pc, stack, locals);
+         }
+         opb.createIncRef(v);
+@@ -202,7 +205,7 @@
+ 
+       case LOAD_GLOBAL:
+         v = opb.createLoadGlobal(oparg);
+-        if (!hasNullGuard(v)) {
++        if (canBeNull(v)) {
+           opb.createGuardNull(v, BH_EXC_RAISED, pc, stack, locals);
+         }
+         opb.createIncRef(v);
+@@ -213,7 +216,7 @@
+         v = stack.Pop();
+         x = opb.createLoadAttr(v, oparg);
+         opb.createDecRef(v);
+-        if (!hasNullGuard(x)) {
++        if (canBeNull(x)) {
+           opb.createGuardNull(x, BH_EXC_RAISED, pc, stack, locals);
+         }
+         stack.Push(x);
+@@ -235,7 +238,7 @@
+         if (arg1 != NULL)
+           w->registerStaticType(arg1);
+         x = opb.createCompareOp(v, w, oparg);
+-        if (!hasNullGuard(x)) {
++        if (canBeNull(x)) {
+           opb.createGuardNull(x, BH_BINARY_OP_FAIL, pc, stack, locals);
+         }
+         stack.Push(x);
+@@ -373,7 +376,7 @@
+     JITValue *x = opb.createGenericBinOp(impl, inplace, v, w);
+ 
+     assert(x != NULL);
+-    if (!hasNullGuard(x)) {
++    if (canBeNull(x)) {
+       opb.createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack, locals);
+     }
+     stack.Push(x);
+diff -r 47bc8478892f JIT/jit_blackhole.cc
+--- a/JIT/jit_blackhole.cc	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_blackhole.cc	Fri Nov 01 23:00:19 2013 +0100
+@@ -91,6 +91,9 @@
+     int opcode;
+     int oparg;
+     PyObject *u, *v, *w;
++    (void) u;
++    (void) v;
++    (void) w;
+ 
+     switch (reason) {
+     case BH_FOR_ITER_EXC:
+diff -r 47bc8478892f JIT/jit_env.cc
+--- a/JIT/jit_env.cc	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_env.cc	Fri Nov 01 23:00:19 2013 +0100
+@@ -81,11 +81,14 @@
+     return v;
+   }
+ 
+-  JITLocals::JITLocals(JITBasicFrame *frame, int num)
+-      : locals(num, NULL), frame_(frame), no_load_(false) {}
++  JITLocals::JITLocals(JITBasicFrame *frame,
++                       const std::vector<std::string> &varnames, int num)
++      : locals(num, NULL), frame_(frame), varnames_(varnames), no_load_(false) {
++  }
+ 
+   JITLocals::JITLocals(const JITLocals &other)
+-      : locals(other.locals), frame_(other.frame_), no_load_(other.no_load_) {}
++      : locals(other.locals), frame_(other.frame_), varnames_(other.varnames_),
++        no_load_(other.no_load_) {}
+ 
+   JITPhiNode *
+   JITLocals::Find(size_t num)
+@@ -119,7 +122,13 @@
+   std::pair<JITLocalValue *, JITPhiNode *>
+   JITLocals::Generate(size_t num)
+   {
+-    JITLocalValue *v = new JITLocalValue(static_cast<int>(num));
++    std::string name = "<unknown>";
++    if (varnames_.size() > num && varnames_[num].size() > 0) {
++      name = varnames_[num];
++    }
++
++    JITLocalValue *v =
++        new JITLocalValue(static_cast<int>(num), std::move(name));
+     JITPhiNode *p = new JITPhiNode(v);
+ 
+     auto &flocals = frame_->locals();
+diff -r 47bc8478892f JIT/jit_env.h
+--- a/JIT/jit_env.h	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_env.h	Fri Nov 01 23:00:19 2013 +0100
+@@ -42,7 +42,8 @@
+ 
+   class JITLocals {
+   public:
+-    JITLocals(JITBasicFrame *frame, int num = 0);
++    JITLocals(JITBasicFrame *frame, const std::vector<std::string> &varnames,
++              int num = 0);
+     JITLocals(const JITLocals &other);
+ 
+     void TraceEnd(JITTraceEnd *t);
+@@ -59,6 +60,7 @@
+     JITPhiNode *Find(size_t num);
+ 
+     JITBasicFrame *frame_;
++    std::vector<std::string> varnames_;
+     bool no_load_;
+   };
+ 
+diff -r 47bc8478892f JIT/jit_fanalysis.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/jit_fanalysis.h	Fri Nov 01 23:00:19 2013 +0100
+@@ -0,0 +1,55 @@
++// -*- C++ -*-
++#ifndef PYTHON_JIT_FANALYSIS_H_
++#define PYTHON_JIT_FANALYSIS_H_
++
++#ifndef __cplusplus
++#error This header expects to be included only in C++ source
++#endif
++
++#include "JIT/jit_opcode.h"
++
++namespace jit {
++
++  class JITFunctionAnalysis {
++  public:
++    JITFunctionAnalysis();
++    virtual ~JITFunctionAnalysis() {}
++
++    virtual void run(JITBasicFunction *func) = 0;
++  };
++
++
++  class GuardNullMoveAnalysis : public JITFunctionAnalysis {
++  public:
++    GuardNullMoveAnalysis() {}
++    ~GuardNullMoveAnalysis() {}
++
++    virtual void run(JITBasicFunction *func)
++    {
++      for (auto block : func->blocks()) {
++        auto &opcodes = block->opcodes();
++        for (auto op : opcodes) {
++          JITPhiNode *p = dyn_cast<JITPhiNode>(op);
++          if (p) {
++            doit(func, p);
++          }
++        }
++      }
++    }
++
++  private:
++    virtual void doit(JITBasicFunction *func, JITPhiNode *op)
++    {
++      bool valid = true;
++      for (auto val : op->edges()) {
++        valid = true;
++      }
++      (void) valid;
++    }
++
++  };
++
++}
++
++
++#endif
+diff -r 47bc8478892f JIT/jit_opcode.cc
+--- a/JIT/jit_opcode.cc	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_opcode.cc	Fri Nov 01 23:00:19 2013 +0100
+@@ -96,6 +96,22 @@
+   }
+ 
+   void
++  JITPhiNode::dump()
++  {
++    std::cout << "PHI_NODE " << edges_.size();
++    if (isa<JITLocalValue>(incoming_)) {
++      std::cout << " " << dyn_cast<JITLocalValue>(incoming_)->name() << "\n";
++    }
++    else {
++      std::cout << " <stack>\n";
++    }
++    std::cout << "         " << incoming_->getStaticType()->name() << "\n";
++    for (auto v : edges_) {
++      std::cout << "         " << v->getStaticType()->name() << "\n";
++    }
++  }
++
++  void
+   JITForIter::emit(JITFunctionBuilder &fbuilder)
+   {
+     JITFunctionState::BuilderT &builder = fbuilder.builder();
+diff -r 47bc8478892f JIT/jit_opcode.h
+--- a/JIT/jit_opcode.h	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_opcode.h	Fri Nov 01 23:00:19 2013 +0100
+@@ -17,6 +17,8 @@
+ 
+ namespace jit {
+ 
++  class JITBasicBlock;
++
+   class JITOpcode {
+   public:
+     JITOpcode() {}
+@@ -27,8 +29,15 @@
+ 
+     virtual uintptr_t type() = 0;
+ 
++    void setParent(JITBasicBlock *parent)
++    {
++      parent_ = parent;
++    }
++
++    JITBasicBlock *getParent() const { return parent_; }
++
+   private:
+-    std::vector<JITValue *> operands_;
++    JITBasicBlock *parent_;
+   };
+ 
+   template<class T>
+@@ -65,11 +74,13 @@
+     void push_front(JITOpcode *opcode)
+     {
+       opcodes_.insert(opcodes_.begin(), opcode);
++      opcode->setParent(this);
+     }
+ 
+     void push_back(JITOpcode *opcode)
+     {
+       opcodes_.push_back(opcode);
++      opcode->setParent(this);
+     }
+ 
+     void emit(JITFunctionBuilder &builder)
+@@ -86,6 +97,11 @@
+       }
+     }
+ 
++    std::vector<JITOpcode *> &opcodes()
++    {
++      return opcodes_;
++    }
++
+   private:
+     std::vector<JITOpcode *> opcodes_;
+   };
+@@ -142,6 +158,11 @@
+       return loaded_locals_;
+     }
+ 
++    std::vector<JITBasicBlock *> &blocks()
++    {
++      return blocks_;
++    }
++
+   private:
+     JITBasicBlock *entry_;
+     std::vector<JITBasicBlock *> blocks_;
+@@ -282,10 +303,10 @@
+       return alloca_;
+     }
+ 
+-    virtual void dump()
+-    {
+-      std::cout << "PHI_NODE " << edges_.size() << "\n";
+-    }
++    JITValue *incoming() { return incoming_; }
++    std::vector<JITValue *> &edges() { return edges_; }
++
++    virtual void dump();
+ 
+     virtual void emit(JITFunctionBuilder &fbuilder);
+     virtual JITType *getStaticType() const
+@@ -326,23 +347,28 @@
+ 
+   class JITLocalValue : public JITValue {
+   public:
+-    JITLocalValue(int num)
++    JITLocalValue(int num, std::string name)
+       : value_(NULL), type_(new JITOpaqueObject),
+-        num_(num)
++        num_(num), name_(name)
+     {}
+     ~JITLocalValue()
+     {
+       delete type_;
+     }
+ 
+-    int number()
++    int number() const
+     {
+       return num_;
+     }
+ 
++    const std::string &name() const
++    {
++      return name_;
++    }
++
+     virtual void dump()
+     {
+-      std::cout << "Local Value " << num_ << "\n";
++      std::cout << "Local Value " << num_ << " \"" << name_ << "\"\n";
+     }
+     virtual void emit(JITFunctionBuilder &fbuilder);
+ 
+@@ -378,6 +404,7 @@
+     llvm::Value *value_;
+     JITType *type_;
+     int num_;
++    std::string name_;
+   };
+ 
+   class JITStackValue : public JITValue {
+@@ -1281,6 +1308,19 @@
+     return NULL;
+   }
+ 
++  inline bool canBeNull(JITValue *v)
++  {
++    if (!v->getStaticType()->canBeNull()) {
++      return false;
++    }
++
++    if (hasNullGuard(v) != nullptr) {
++      return false;
++    }
++
++    return true;
++  }
++
+   class JITGuardTrueSplit : public JITOpcode {
+   public:
+     JITGuardTrueSplit(JITValue *arg,
+diff -r 47bc8478892f JIT/jit_tracer.cc
+--- a/JIT/jit_tracer.cc	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_tracer.cc	Fri Nov 01 23:00:19 2013 +0100
+@@ -102,6 +102,46 @@
+ #define JIT_COMPILE_TIME
+ #endif
+ 
++static std::vector<std::string> get_local_names(PyCodeObject *code)
++{
++  PyObject *varnames = code->co_varnames;
++
++  if (!PySequence_Check(varnames)) {
++    return std::vector<std::string>{};
++  }
++
++  int size = PySequence_Size(varnames);
++  if (size == -1) {
++    return std::vector<std::string>{};
++  }
++
++  std::vector<std::string> result;
++  for (int i = 0; i < size; ++i) {
++    PyObject *v = PySequence_GetItem(varnames, i);
++    if (v == 0) {
++      result.push_back(std::string());
++      continue;
++    }
++
++    if (!PyUnicode_CheckExact(v)) {
++      Py_DECREF(v);
++      continue;
++    }
++
++    const char *str = _PyUnicode_AsString(v);
++    Py_DECREF(v);
++
++    if (str == nullptr) {
++      result.push_back(std::string());
++      continue;
++    }
++
++    result.push_back(std::string(str));
++  }
++
++  return result;
++}
++
+ void
+ PyJITTracer::do_trace(PyCodeObject *code, size_t start)
+ {
+@@ -134,11 +174,10 @@
+   }
+ 
+   // root->dump();
+-
+-  jit::JITBasicFunction *bfunc = root->analyse();
++  jit::JITBasicFunction *bfunc = root->analyse(get_local_names(code));
+   assert(bfunc != NULL);
+ 
+-  // bfunc->dump();
++  bfunc->dump();
+ 
+   jit::JITFunctionState state(PyGlobalJITData::Get());
+   jit::JITFrameFBuilder builder(&state, bfunc);
+@@ -252,7 +291,7 @@
+   root = root->copy();
+   src_part = root->get_part(bail_block);
+ 
+-  auto old_part = root->split(src_part, bail_opcode);
++  root->split(src_part, bail_opcode);
+   auto new_part = new jit::JITTraceContainer();
+   root->add_part(new_part);
+   src_part->next.push_back(new_part);
+@@ -266,11 +305,11 @@
+   // std::cout << "BAIL GENERATE " << bail_block << " " << bail_opcode
+   //           << "\n";
+   int verify_result = root->verify();
++  (void) verify_result;
+   assert(verify_result == jit::VERIFY_OK);
+ 
+   // root->dump();
+-
+-  jit::JITBasicFunction *bfunc = root->analyse();
++  jit::JITBasicFunction *bfunc = root->analyse(get_local_names(code));
+   assert(bfunc != NULL);
+ 
+   jit::JITFunctionState state(PyGlobalJITData::Get());
+diff -r 47bc8478892f JIT/jit_tracer.h
+--- a/JIT/jit_tracer.h	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_tracer.h	Fri Nov 01 23:00:19 2013 +0100
+@@ -63,7 +63,7 @@
+     int nextid;
+ 
+     int verify();
+-    JITBasicFunction *analyse();
++    JITBasicFunction *analyse(const std::vector<std::string> &varnames);
+   };
+ 
+   // struct JITTraceAnalysis {
+diff -r 47bc8478892f JIT/jit_types.h
+--- a/JIT/jit_types.h	Fri Nov 01 20:57:10 2013 +0100
++++ b/JIT/jit_types.h	Fri Nov 01 23:00:19 2013 +0100
+@@ -25,6 +25,8 @@
+     virtual bool matchesType(const PyTypeObject *) const = 0;
+     virtual bool canSpecialize(const PyTypeObject *) const = 0;
+ 
++    virtual std::string name() = 0;
++
+     virtual llvm::Value *getValue(JITFunctionBuilder &fbuilder, bool mayBeNull=false,
+                                   bool keepValue=true) = 0;
+     virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder) = 0;
+@@ -37,6 +39,10 @@
+     {
+       return false;
+     }
++    virtual bool canBeNull() const
++    {
++      return true;
++    }
+ 
+     virtual PyTypeObject *getPyType() const = 0;
+     virtual uintptr_t type() = 0;
+@@ -75,6 +81,11 @@
+       return true;
+     }
+ 
++    virtual std::string name()
++    {
++      return "<opaque>";
++    }
++
+     virtual llvm::Value *getValue(JITFunctionBuilder &fbuilder, bool mayBeNull=false,
+                                   bool keepValue=true)
+     {
+@@ -138,11 +149,21 @@
+       return false;
+     }
+ 
++    virtual std::string name()
++    {
++      return "<naked_float>";
++    }
++
+     virtual bool isFloat() const
+     {
+       return true;
+     }
+ 
++    virtual bool canBeNull() const
++    {
++      return false;
++    }
++
+     virtual llvm::Value *getValue(JITFunctionBuilder &fbuilder, bool mayBeNull=false,
+                                   bool keepValue=true)
+     {
+diff -r 47bc8478892f Makefile.pre.in
+--- a/Makefile.pre.in	Fri Nov 01 20:57:10 2013 +0100
++++ b/Makefile.pre.in	Fri Nov 01 23:00:19 2013 +0100
+@@ -888,6 +888,7 @@
+ 		$(srcdir)/JIT/jit_binop.h \
+ 		$(srcdir)/JIT/jit_opcode.h \
+ 		$(srcdir)/JIT/jit_env.h \
++		$(srcdir)/JIT/jit_fanalysis.h \
+ 		$(srcdir)/JIT/PyTypeBuilder.h \
+ 		$(srcdir)/JIT/SingleFunctionInliner.h \
+ 		pyconfig.h \
 jit.patch
+lift.patch
 loadattr.patch