Commits

ebo committed f9603e0

Added some type feedback

  • Participants
  • Parent commits a7ffea3

Comments (0)

Files changed (1)

 # HG changeset patch
 # Parent 7b530b3ed07bbc09b6ea3ef291ce796f06f54f0b
 
+diff --git a/JIT/PyTypeBuilder.h b/JIT/PyTypeBuilder.h
+--- a/JIT/PyTypeBuilder.h
++++ b/JIT/PyTypeBuilder.h
+@@ -214,6 +214,19 @@
+     DEFINE_FIELD(PyTupleObject, ob_item)
+   };
+ 
++  template<> class TypeBuilder<PyFloatObject, false> {
++  public:
++    static StructType *get(llvm::LLVMContext &context) {
++      return cast<StructType>(
++        PyGlobalJITData::Get()->module()->getTypeByName(
++          // Clang's name for the PyFloatObject struct.
++          "struct.PyFloatObject"));
++    }
++
++    // DEFINE_OBJECT_HEAD_FIELDS(PyFloatObject)
++    DEFINE_FIELD(PyFloatObject, ob_fval)
++  };
++
+ }
+ 
+ namespace jit {
+@@ -231,6 +244,7 @@
+   typedef PyTypeBuilder<PyThreadState> ThreadStateTy;
+   typedef PyTypeBuilder<PyCFunctionObject> CFunctionTy;
+   typedef PyTypeBuilder<PyMethodDef> MethodDefTy;
++  typedef PyTypeBuilder<PyFloatObject> FloatTy;
+ }
+ 
+ #endif
 diff --git a/JIT/global_jit_data.cc b/JIT/global_jit_data.cc
 --- a/JIT/global_jit_data.cc
 +++ b/JIT/global_jit_data.cc
  int _PyJIT_Init(void);
  void _PyJIT_Fini(void);
  
+diff --git a/JIT/jit_binop.cc b/JIT/jit_binop.cc
+new file mode 100644
+--- /dev/null
++++ b/JIT/jit_binop.cc
+@@ -0,0 +1,75 @@
++#include "JIT/jit_binop.h"
++#include "JIT/jit_types.h"
++#include "JIT/jit_tracer.h"
++
++using llvm::Value;
++
++namespace jit {
++
++  class BinaryAddImpl : public BinaryOpImpl {
++  public:
++    BinaryAddImpl(JITValue *arg0, JITValue *arg1)
++      : arg0_(arg0), arg1_(arg1), float_inline_(false)
++    {
++      if (arg0_->getStaticType()->isFloat() && arg1_->getStaticType()->isFloat()) {
++        float_inline_ = true;
++      }
++    }
++
++    virtual bool inlined() const
++    {
++      return float_inline_;
++    }
++
++    virtual void emit_inline(JITFunctionBuilder &fbuilder, JITType *result)
++    {
++      JITFunctionState::BuilderT &builder = fbuilder.builder();
++      JITFunctionState *state = fbuilder.getState();
++
++      Value *naked0 = arg0_->getStaticType()->getNakedValue(fbuilder);
++      Value *naked1 = arg1_->getStaticType()->getNakedValue(fbuilder);
++      Value *naked_result = builder.CreateFAdd(naked0, naked1);
++
++      Value *func = state->GetGlobalFunction<PyObject*(double)>("PyFloat_FromDouble");
++      Value *value = state->CreateCall(func, naked_result);
++      result->init(value);
++    }
++
++    virtual void emit_inplace_inline(JITFunctionBuilder &fbuilder, JITType *result)
++    {
++      this->emit_inline(fbuilder, result);
++    }
++
++    virtual void emit(JITFunctionBuilder &fbuilder, JITType *result)
++    {
++      JITFunctionState *state = fbuilder.getState();
++      Value *func = state->GetGlobalFunction<PyObject*(PyObject*, PyObject*)>("PyNumber_Add");
++      llvm::Value *value = state->CreateCall(func,
++                                             arg0_->getValue(),
++                                             arg1_->getValue());
++      result->init(value);
++    }
++
++    virtual void emit_inplace(JITFunctionBuilder &fbuilder, JITType *result)
++    {
++      JITFunctionState *state = fbuilder.getState();
++      Value *func = state->GetGlobalFunction<PyObject*(PyObject*, PyObject*)>("PyNumber_InPlaceAdd");
++      llvm::Value *value = state->CreateCall(func,
++                                             arg0_->getValue(),
++                                             arg1_->getValue());
++      result->init(value);
++    }
++
++  private:
++    JITValue *arg0_;
++    JITValue *arg1_;
++    bool float_inline_;
++  };
++
++
++  BinaryOpImpl *BinaryOpImpl::create(int opcode, JITValue *arg0, JITValue *arg1)
++  {
++    return new BinaryAddImpl(arg0, arg1);
++  }
++
++}
+diff --git a/JIT/jit_binop.h b/JIT/jit_binop.h
+new file mode 100644
+--- /dev/null
++++ b/JIT/jit_binop.h
+@@ -0,0 +1,34 @@
++// -*- C++ -*-
++#ifndef PYTHON_JIT_BINOP_H_
++#define PYTHON_JIT_BINOP_H_
++
++#ifndef __cplusplus
++#error This header expects to be included only in C++ source
++#endif
++
++#include "JIT/global_jit_data.h"
++#include "JIT/jit_fbuilder.h"
++
++namespace jit {
++
++  class JITValue;
++  class JITType;
++
++  class BinaryOpImpl {
++  public:
++    static BinaryOpImpl *create(int opcode, JITValue *arg0, JITValue *arg1);
++
++    virtual bool inlined() const = 0;
++
++    virtual void emit_inplace_inline(JITFunctionBuilder &builder, JITType *result) = 0;
++    virtual void emit_inline(JITFunctionBuilder &builder, JITType *result) = 0;
++
++    virtual void emit_inplace(JITFunctionBuilder &builder, JITType *result) = 0;
++    virtual void emit(JITFunctionBuilder &builder, JITType *result) = 0;
++  };
++
++
++
++}
++
++#endif
 diff --git a/JIT/jit_blackhole.cc b/JIT/jit_blackhole.cc
 --- a/JIT/jit_blackhole.cc
 +++ b/JIT/jit_blackhole.cc
      return;
    }
  
-@@ -144,11 +145,11 @@
+@@ -144,7 +145,7 @@
  
    jit::JITTraceAnalysis analysis;
    analysis.analyseTrace(cut_trace);
    jit::JITFunctionState state(PyGlobalJITData::Get());
    analysis.emit(state);
    PyGlobalJITData::Get()->optimize(state.function());
--  state.function()->dump();
-+  // state.function()->dump();
- 
-   typedef int(*pyfunc_t)(PyFrameObject*);
-   pyfunc_t trace_func =
 @@ -160,7 +161,8 @@
  }
  
    JITTraceAnalysis::JITTraceAnalysis()
      : stack_counter_(0)
    {
-@@ -206,37 +238,47 @@
+@@ -206,37 +238,55 @@
      }
    }
  
 -  JITValue *
 -  JITTraceAnalysis::Pop()
-+  void
-+  JITTraceAnalysis::createBinaryOp(JITStack &stack, TraceEntry &entry)
++  static bool binop_needs_guards(int opcode, JITType *v, JITType *w)
    {
 -    if (stack_.size() > 0) {
 -      JITValue *v = stack_.back();
 -      stack_.pop_back();
 -      return v;
-+    int opcode = entry.opcode;
-+    JITValue *w = stack.Pop();
-+    JITValue *v = stack.Pop();
-+    if (entry.arg0 != NULL)
-+      v->registerStaticType(entry.arg0);
-+    if (entry.arg1 != NULL)
-+      w->registerStaticType(entry.arg1);
-+
-+    JITValue *x = NULL;
-+    switch (opcode) {
++    switch(opcode) {
 +    case INPLACE_ADD:
-+      x = this->createInplaceAdd(v, w);
-+      break;
-+
-+    case BINARY_ADD:
-+      x = this->createBinaryAdd(v, w);
-+      break;
-+
-+    case BINARY_SUBTRACT:
-+      x = this->createBinarySubtract(v, w);
-+      break;
-+
-+    case BINARY_MULTIPLY:
-+      x = this->createBinaryMultiply(v, w);
-+      break;
-+
-+    case BINARY_FLOOR_DIVIDE:
-+      x = this->createBinaryDivide(v, w);
-+      break;
++      if (v->isFloat() && w->isFloat()) {
++        return true;
++      }
      }
 -
 -    JITStackValue *v = new JITStackValue;
 -    JITValue *v = this->Pop();
 -    this->Push(v);
 -    return v;
--  }
--
--  void
++    return false;
+   }
+ 
+   void
 -  JITTraceAnalysis::Push(JITValue *value)
--  {
++  JITTraceAnalysis::createBinaryOp(bool inplace, JITStack &stack, TraceEntry &entry)
+   {
 -    stack_.push_back(value);
++    int opcode = entry.opcode;
++    JITValue *w = stack.Pop();
++    JITValue *v = stack.Pop();
++    if (entry.arg0 != NULL)
++      v->registerStaticType(entry.arg0);
++    if (entry.arg1 != NULL)
++      w->registerStaticType(entry.arg1);
++
++    BinaryOpImpl *impl = BinaryOpImpl::create(opcode, v, w);
++
++    JITType *type_v = v->getStaticType();
++    JITType *type_w = w->getStaticType();
++    if (impl->inlined()) {
++      if (!type_v->hasGuard()) {
++        type_v->setGuard(true);
++        this->createGuardType(v, BH_NO_BLACKHOLE, entry.pc, stack);
++      }
++
++      if (!type_w->hasGuard()) {
++        type_w->setGuard(true);
++        this->createGuardType(w, BH_NO_BLACKHOLE, entry.pc, stack);
++      }
++    }
++
++    JITValue *x = this->createGenericBinOp(impl, inplace, v, w);
++
++    assert(x != NULL);
 +    this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
 +    stack.Push(x);
    }
      for (size_t i = 0; i < trace.size(); ++i) {
        TraceEntry &entry = trace[i];
        int opcode = entry.opcode;
-@@ -249,87 +291,89 @@
+@@ -249,94 +299,72 @@
  
  
        case POP_JUMP_IF_FALSE:
 -        this->Push(x);
 -        continue;
 -
++        this->createBinaryOp(true, stack, entry);
++        break;
        case BINARY_ADD:
 -        w = this->Pop();
 -        v = this->Pop();
 -        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc);
 -        this->Push(x);
 -        continue;
-+        this->createBinaryOp(stack, entry);
++        this->createBinaryOp(false, stack, entry);
 +        break;
  
        case COMPARE_OP:
 +    this->createTraceEnd(stack);
 +    loaded_stack_ = stack.loaded_stack;
 +    stack_counter_ = stack.stack_counter;
-+  }
-+
-+  void
-+  JITTraceAnalysis::analyseTypes()
-+  {
-+    JITStack stack;
-+    std::vector<JITOpcode *> source;
-+    trace_.swap(source);
-+
-+    JITOpcodeInfo *info = NULL;
-+
-+    for (size_t i = 0; i < source.size(); ++i) {
-+      JITOpcode *op = source[i];
-+      if (JITOpcodeInfo *v = dyn_cast<JITOpcodeInfo>(op)) {
-+        info = v;
-+        trace_.push_back(op);
-+        continue;
-+      }
-+
-+      if (JITInplaceAdd *v = dyn_cast<JITInplaceAdd>(op)) {
-+        if (v->needsArgsTypeChecked()) {
-+        }
-+      }
-+
-+      trace_.push_back(op);
-+    }
    }
  
- 
-@@ -337,6 +381,7 @@
+-
+   void
    JITStackValue::emit(JITFunctionBuilder &builder)
    {
      value_ = builder.Pop();
    }
  
    void
-@@ -351,6 +396,7 @@
+@@ -351,6 +379,7 @@
                           "tp_iternext");
  
      value_ = fbuilder.getState()->CreateCall(tp_iternext, v);
    }
  
    void
-@@ -370,6 +416,7 @@
+@@ -370,6 +399,7 @@
      JITFunctionState::BuilderT &builder = fbuilder.builder();
      llvm::Value *localptr = fbuilder.LocalPtr(oparg_);
      value_ = builder.CreateLoad(localptr);
    }
  
    void
-@@ -378,6 +425,7 @@
+@@ -378,12 +408,33 @@
      JITFunctionState::BuilderT &builder = fbuilder.builder();
      llvm::Value *localptr = fbuilder.ConstPtr(oparg_);
      value_ = builder.CreateLoad(localptr);
    }
  
    void
-@@ -385,12 +433,24 @@
+   JITInplaceAdd::emit(JITFunctionBuilder &fbuilder)
    {
      JITFunctionState *state = fbuilder.getState();
- 
-+    if (arg0_->getStaticType()->isFloat() &&
-+        arg1_->getStaticType()->isFloat()) {
-+      std::cout << "InplaceAdd may be specialized\n";
++    JITFunctionState::BuilderT &builder = fbuilder.builder();
++
++    if (this->float_inline_) {
++
 +      JITType *type0 = arg0_->getStaticType();
 +      JITType *type1 = arg1_->getStaticType();
 +
-+      llvm::Value *naked0 = type0->getNakedValue(fbuilder);
-+      llvm::Value *naked1 = type0->getNakedValue(fbuilder);
++      Value *naked0 = type0->getNakedValue(fbuilder);
++      Value *naked1 = type1->getNakedValue(fbuilder);
 +
++      state->DecRef(arg0_->getValue());
++      state->DecRef(arg1_->getValue());
++
++      Value *result = builder.CreateFAdd(naked0, naked1);
++
++      Value *func = state->GetGlobalFunction<PyObject*(double)>("PyFloat_FromDouble");
++      value_ = state->CreateCall(func, result);
++      this->getStaticType()->init(value_);
++      return;
 +    }
-+
+ 
      Value *func = state->GetGlobalFunction<PyObject*(PyObject*, PyObject*)>("PyNumber_InPlaceAdd");
      value_ = state->CreateCall(func,
-                                arg0_->getValue(),
+@@ -391,6 +442,34 @@
+                                arg1_->getValue());
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
++  }
++
++  JITGenericBinOp::JITGenericBinOp(BinaryOpImpl *impl, bool inplace, JITValue *arg0, JITValue *arg1)
++    : arg0_(arg0), arg1_(arg1),
++      type_(new JITOpaqueObject), impl_(impl),
++      inplace_(inplace)
++  {
++  }
++
++  void
++  JITGenericBinOp::emit(JITFunctionBuilder &fbuilder)
++  {
++    JITFunctionState *state = fbuilder.getState();
++    if (inplace_) {
++      if (impl_->inlined())
++        impl_->emit_inplace_inline(fbuilder, this->type_);
++      else
++        impl_->emit_inplace(fbuilder, this->type_);
++    }
++    else {
++      if (impl_->inlined())
++        impl_->emit_inline(fbuilder, this->type_);
++      else
++        impl_->emit(fbuilder, this->type_);
++    }
++    state->DecRef(arg0_->getValue());
++    state->DecRef(arg1_->getValue());
+   }
+ 
+   void
+@@ -404,6 +483,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -404,6 +464,7 @@
+@@ -417,6 +497,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -417,6 +478,7 @@
+@@ -430,6 +511,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -430,6 +492,7 @@
+@@ -443,6 +525,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -443,6 +506,7 @@
-                                arg1_->getValue());
-     state->DecRef(arg0_->getValue());
-     state->DecRef(arg1_->getValue());
-+    this->getStaticType()->init(value_);
-   }
- 
-   void
-@@ -457,6 +521,13 @@
+@@ -457,6 +540,38 @@
  
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
 +  void
 +  JITGuardType::emit(JITFunctionBuilder &fbuilder)
 +  {
++    JITType *type = arg_->getStaticType();
++    llvm::Value *value = type->getValue();
++
++    JITFunctionState::BuilderT &builder = fbuilder.builder();
++    JITFunctionState *state = fbuilder.getState();
++
++    llvm::BasicBlock *trace_cont = state->CreateBasicBlock("trace_cont");
++    llvm::BasicBlock *bail = state->CreateBasicBlock("bail");
++
++    llvm::Value *ob_type =
++      builder.CreateLoad(ObjectTy::ob_type(builder, value));
++    llvm::Value *py_type = state->EmbedPointer<PyTypeObject*>(type->getPyType());
++    llvm::Value *check = builder.CreateICmpEQ(ob_type, py_type);
++
++    builder.CreateCondBr(check, trace_cont, bail);
++
++    builder.SetInsertPoint(bail);
++    for (size_t i = 0; i < stack_.size(); ++i) {
++      fbuilder.Push(stack_[i]->getValue());
++    }
++    fbuilder.SetLastI(lasti_);
++    fbuilder.SetBailReason(reason_);
++    fbuilder.CreateBailBr();
++
++    builder.SetInsertPoint(trace_cont);
    }
  
    void
-@@ -566,4 +637,21 @@
+@@ -566,4 +681,24 @@
      state->IncRef(arg_->getValue());
    }
  
 +  const int JITGuardType::ID = 0;
 +  const int JITGuardTrue::ID = 0;
 +  const int JITTraceEnd::ID = 0;
++
++  const int JITGenericBinOp::ID = 0;
++
  } // namespace jit
 diff --git a/JIT/jit_tracer.h b/JIT/jit_tracer.h
 --- a/JIT/jit_tracer.h
 +++ b/JIT/jit_tracer.h
-@@ -9,24 +9,75 @@
+@@ -9,24 +9,76 @@
  #include "JIT/global_jit_data.h"
  #include "JIT/jit_blackhole.h"
  #include "JIT/jit_fbuilder.h"
 +#include "JIT/jit_types.h"
++#include "JIT/jit_binop.h"
  
  #include <vector>
  #include <iostream>
      virtual void dump()
      {
        std::cout << "Stack Value\n";
-@@ -34,16 +85,45 @@
+@@ -34,18 +86,52 @@
      virtual void emit(JITFunctionBuilder &builder);
      virtual llvm::Value *getValue() const
      {
 +    JITForIter(JITValue *arg) : arg_(arg), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITForIter()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -55,17 +135,47 @@
+     {
+       std::cout << "FOR_ITER\n";
+@@ -55,17 +141,47 @@
  
      virtual llvm::Value *getValue() const
      {
      {}
  
      virtual void dump()
-@@ -75,20 +185,21 @@
+@@ -75,22 +191,28 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 +      : oparg_(oparg), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITLoadFast()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -100,17 +211,47 @@
+     {
+       std::cout << "LOAD_FAST\n";
+@@ -100,19 +222,54 @@
  
      virtual llvm::Value *getValue() const
      {
 +      : oparg_(oparg), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITLoadConst()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -124,16 +265,45 @@
+     {
+       std::cout << "LOAD_CONST\n";
+@@ -124,16 +281,104 @@
      {
        return value_;
      }
      int oparg_;
      llvm::Value *value_;
 +    JITType *type_;
++  };
++
++
++  class JITGenericBinOp : public JITValue {
++  public:
++    JITGenericBinOp(BinaryOpImpl *impl, bool inplace, JITValue *arg0, JITValue *arg1);
++
++    ~JITGenericBinOp()
++    {
++      delete type_;
++      delete impl_;
++    }
++
++    virtual void dump()
++    {
++      std::cout << "GEN_BIN_OP\n";
++    }
++
++    virtual void emit(JITFunctionBuilder &builder);
++
++    virtual llvm::Value *getValue() const
++    {
++      return getStaticType()->getValue();
++    }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *t)
++    {
++      if (type_ == NULL || type_->canSpecialize(t)) {
++        JITType *new_type = JITType::createBoxedType(t);
++        if (new_type != NULL) {
++          JITType *old_type = type_;
++          type_ = new_type;
++          delete old_type;
++        }
++      }
++      else {
++        if (!type_->matchesType(t)) {
++          std::cout << "Trace Type mismatch\n";
++        }
++      }
++    }
++
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
++  private:
++    JITValue *arg0_;
++    JITValue *arg1_;
++    JITType *type_;
++    BinaryOpImpl *impl_;
++    bool inplace_;
    };
  
    class JITInplaceAdd : public JITValue {
 +      }
 +    }
 +
-+    bool needsArgsTypeChecked()
++    ~JITInplaceAdd()
 +    {
-+      return float_inline_;
++      delete type_;
 +    }
  
      virtual void dump()
      {
-@@ -144,18 +314,49 @@
+@@ -144,20 +389,56 @@
  
      virtual llvm::Value *getValue() const
      {
 +      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITBinaryAdd()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -169,16 +370,33 @@
+     {
+       std::cout << "BINARY_ADD\n";
+@@ -169,18 +450,40 @@
      {
        return value_;
      }
 +      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITBinarySubtract()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -192,16 +410,33 @@
+     {
+       std::cout << "BINARY_SUBSTRACT\n";
+@@ -192,18 +495,40 @@
      {
        return value_;
      }
 +      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITBinaryMultiply()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -215,16 +450,33 @@
+     {
+       std::cout << "BINARY_MULTIPLY\n";
+@@ -215,18 +540,40 @@
      {
        return value_;
      }
 +      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITBinaryDivide()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -238,17 +490,34 @@
+     {
+       std::cout << "BINARY_DIVIDE\n";
+@@ -238,19 +585,41 @@
      {
        return value_;
      }
 +        oparg_(oparg), value_(NULL), type_(new JITOpaqueObject)
      {}
  
++    ~JITCompareOp()
++    {
++      delete type_;
++    }
++
      virtual void dump()
-@@ -262,16 +531,33 @@
+     {
+       std::cout << "COMPARE_OP " << oparg_ << "\n";
+@@ -262,16 +631,33 @@
      {
        return value_;
      }
      {}
  
      virtual void dump()
-@@ -281,21 +567,50 @@
+@@ -281,21 +667,50 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 -  class JITGuardNull : public JITValue {
 +  class JITGuardType : public JITOpcode {
 +  public:
-+    JITGuardType(JITType *arg, BLACKHOLE reason, int lasti,
++    JITGuardType(JITValue *arg, BLACKHOLE reason, int lasti,
 +                 std::vector<JITValue *> &stack)
 +      : arg_(arg), reason_(reason), lasti_(lasti),
 +        stack_(stack)
 +    static const int ID;
 +
 +  private:
-+    JITType *arg_;
++    JITValue *arg_;
 +    BLACKHOLE reason_;
 +    int lasti_;
 +    std::vector<JITValue *> stack_;
      {}
  
      virtual void dump()
-@@ -305,24 +620,25 @@
+@@ -305,24 +720,25 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
      {}
  
      virtual void dump()
-@@ -332,22 +648,23 @@
+@@ -332,22 +748,23 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
      {}
  
      virtual void dump()
-@@ -357,24 +674,40 @@
+@@ -357,24 +774,39 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 +    JITTraceAnalysis();
 +
 +    void analyseTrace(std::vector<TraceEntry> &trace);
-+    void analyseTypes();
 +
      void dump()
      {
        for (size_t i = 0; i < loaded_stack_.size(); ++i) {
-@@ -387,6 +720,15 @@
+@@ -387,6 +819,15 @@
  
      void emit(JITFunctionState &state);
  
-+    void createBinaryOp(JITStack &stack, TraceEntry &entry);
++    void createBinaryOp(bool inplace, JITStack &stack, TraceEntry &entry);
 +
 +    JITOpcodeInfo *createOpcodeInfo(int lasti, JITStack &stack)
 +    {
      JITForIter *createForIter(JITValue *v)
      {
        JITForIter *r = new JITForIter(v);
-@@ -436,16 +778,23 @@
+@@ -394,6 +835,13 @@
+       return r;
+     }
+ 
++    JITGenericBinOp *createGenericBinOp(BinaryOpImpl *impl, bool inplace, JITValue *v, JITValue *w)
++    {
++      JITGenericBinOp *r = new JITGenericBinOp(impl, inplace, v, w);
++      trace_.push_back(r);
++      return r;
++    }
++
+     JITInplaceAdd *createInplaceAdd(JITValue *v, JITValue *w)
+     {
+       JITInplaceAdd *r = new JITInplaceAdd(v, w);
+@@ -436,16 +884,23 @@
        return r;
      }
  
 +      return r;
 +    }
 +
-+    JITGuardType *createGuardType(JITType *v, BLACKHOLE reason, int lasti, JITStack &stack)
++    JITGuardType *createGuardType(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack)
 +    {
 +      JITGuardType *r = new JITGuardType(v, reason, lasti, stack.stack);
        trace_.push_back(r);
        return r;
      }
-@@ -478,19 +827,18 @@
+@@ -478,19 +933,18 @@
        return r;
      }
  
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_types.cc
-@@ -0,0 +1,48 @@
+@@ -0,0 +1,35 @@
 +#include "JIT/jit_types.h"
 +
 +namespace jit {
 +    return NULL;
 +  }
 +
-+  // llvm::Value *
-+  // JITBoxedFloat::ensureGuard(JITFunctionBuilder &fbuilder)
-+  // {
-+  //   if (has_guard_)
-+  //     return NULL;
-+
-+  //   JITFunctionState::BuilderT &builder = fbuilder.builder();
-+  //   JITFunctionState *state = fbuilder.getState();
-+
-+  //   llvm::Value *ob_type =
-+  //     builder.CreateLoad(ObjectTy::ob_type(builder, this->value_));
-+  //   llvm::Value *float_type = state->EmbedPointer<PyTypeObject*>(&PyFloat_Type);
-+  //   llvm::Value *check = builder.CreateICmpEQ(ob_type, float_type);
-+
-+  //   return check;
-+  // }
-+
 +  llvm::Value *
 +  JITBoxedFloat::getNakedValue(JITFunctionBuilder &fbuilder)
 +  {
-+    return NULL;
++    JITFunctionState::BuilderT &builder = fbuilder.builder();
++    JITFunctionState *state = fbuilder.getState();
++
++    llvm::Value *as_float = builder.CreateBitCast(this->value_, PyTypeBuilder<PyFloatObject*>::get(state->context()));
++    return builder.CreateLoad(FloatTy::ob_fval(builder, as_float), "as_float");
 +  }
 +
 +
  		Python/compile.o \
  		Python/codecs.o \
  		Python/dynamic_annotations.o \
-@@ -379,6 +380,7 @@
+@@ -379,9 +380,11 @@
  PYTHON_OBJS+=	\
  		JIT/global_jit_data.o \
  		JIT/jit_tracer.o \
  		JIT/PyTypeBuilder.o \
  		JIT/SingleFunctionInliner.o \
  		JIT/jit_blackhole.o \
-@@ -494,14 +496,14 @@
++		JIT/jit_binop.o \
+ 		JIT/jit_fbuilder.o \
+ 		JIT/jit_fstate.o
+ 
+@@ -494,14 +497,14 @@
  
  # Build static library
  # avoid long command lines, same as LIBRARY_OBJS
  	$(RANLIB) $@
  
  libpython$(LDVERSION).so: $(LIBRARY_OBJS)
-@@ -730,7 +732,7 @@
+@@ -730,7 +733,7 @@
  $(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
  	$(OPCODETARGETGEN) $(OPCODETARGETS_H)
  
  
  Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \
  				$(BYTESTR_DEPS)
-@@ -832,6 +834,7 @@
+@@ -832,8 +835,10 @@
  		$(srcdir)/JIT/global_jit_data_fwd.h \
  		$(srcdir)/JIT/jit_fstate.h \
  		$(srcdir)/JIT/jit_tracer.h \
 +		$(srcdir)/JIT/jit_types.h \
  		$(srcdir)/JIT/jit_fbuilder.h \
  		$(srcdir)/JIT/jit_blackhole.h \
++		$(srcdir)/JIT/jit_binop.h \
  		$(srcdir)/JIT/PyTypeBuilder.h \
-@@ -849,7 +852,8 @@
+ 		$(srcdir)/JIT/SingleFunctionInliner.h \
+ 		pyconfig.h \
+@@ -849,7 +854,8 @@
  	$(LLVM_BIN_DIR)/llvm-link -o $@ $(filter %.bc, $^)
  $(BCLIBRARY): $(BCLIBRARY:.bc=.unopt.bc)
  	$(LLVM_BIN_DIR)/opt -o $@ -O3 $<
              x = v = POP();
              Py_DECREF(v);
              JUMPBY(oparg);
+diff --git a/configure b/configure
+--- a/configure
++++ b/configure
+@@ -651,6 +651,7 @@
+ AR
+ RANLIB
+ USE_INLINE
++LD
+ GNULD
+ LINKCC
+ LDVERSION
+@@ -5261,6 +5262,12 @@
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GNULD" >&5
+ $as_echo "$GNULD" >&6; }
+ 
++LD=ld
++if test "$GCC" = yes; then
++       LD=`$CC -print-prog-name=ld`
++fi
++
++
+ { $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 :
 diff --git a/configure.ac b/configure.ac
 --- a/configure.ac
 +++ b/configure.ac
-@@ -793,6 +793,9 @@
+@@ -793,6 +793,12 @@
  esac
  AC_MSG_RESULT($GNULD)
  
++LD=ld
++if test "$GCC" = yes; then
++       LD=`$CC -print-prog-name=ld`
++fi
 +AC_SUBST(LD)
-+LD=$ac_proc
 +
  AC_C_INLINE
  if test "$ac_cv_c_inline" != no ; then