diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc
new file mode 100644
index 0000000..b139e32
--- /dev/null
+++ b/compiler/llvm/gbc_expander.cc
@@ -0,0 +1,3753 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex_file-inl.h"
+#include "driver/compiler_driver.h"
+#include "driver/dex_compilation_unit.h"
+#include "intrinsic_helper.h"
+#include "ir_builder.h"
+#include "method_reference.h"
+#include "mirror/abstract_method.h"
+#include "mirror/array.h"
+#include "mirror/string.h"
+#include "thread.h"
+#include "utils_llvm.h"
+#include "verifier/method_verifier.h"
+
+#include "dex/compiler_ir.h"
+#include "dex/mir_graph.h"
+#include "dex/quick/mir_to_lir.h"
+using art::kMIRIgnoreNullCheck;
+using art::kMIRIgnoreRangeCheck;
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/IR/Intrinsics.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/CFG.h>
+#include <llvm/Support/InstIterator.h>
+
+#include <vector>
+#include <map>
+#include <utility>
+
+using namespace art::llvm;
+
+using art::llvm::IntrinsicHelper;
+
+namespace art {
+extern char RemapShorty(char shortyType);
+};
+
+namespace {
+
+class GBCExpanderPass : public llvm::FunctionPass {
+ private:
+  const IntrinsicHelper& intrinsic_helper_;
+  IRBuilder& irb_;
+
+  llvm::LLVMContext& context_;
+  RuntimeSupportBuilder& rtb_;
+
+ private:
+  llvm::AllocaInst* shadow_frame_;
+  llvm::Value* old_shadow_frame_;
+
+ private:
+  art::CompilerDriver* const driver_;
+
+  const art::DexCompilationUnit* const dex_compilation_unit_;
+
+  llvm::Function* func_;
+
+  std::vector<llvm::BasicBlock*> basic_blocks_;
+
+  std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
+  llvm::BasicBlock* current_bb_;
+  std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
+      landing_pad_phi_mapping_;
+  llvm::BasicBlock* basic_block_unwind_;
+
+  // Maps each vreg to its shadow frame address.
+  std::vector<llvm::Value*> shadow_frame_vreg_addresses_;
+
+  bool changed_;
+
+ private:
+  //----------------------------------------------------------------------------
+  // Constant for GBC expansion
+  //----------------------------------------------------------------------------
+  enum IntegerShiftKind {
+    kIntegerSHL,
+    kIntegerSHR,
+    kIntegerUSHR,
+  };
+
+ private:
+  //----------------------------------------------------------------------------
+  // Helper function for GBC expansion
+  //----------------------------------------------------------------------------
+
+  llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
+                               llvm::CallInst& inst);
+
+  uint64_t LV2UInt(llvm::Value* lv) {
+    return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
+  }
+
+  int64_t LV2SInt(llvm::Value* lv) {
+    return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
+  }
+
+ private:
+  // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
+  // Refactor these utility functions from MethodCompiler to avoid forking.
+
+  void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
+
+  void RewriteFunction();
+
+  void RewriteBasicBlock(llvm::BasicBlock* original_block);
+
+  void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
+                            llvm::BasicBlock* new_basic_block);
+
+
+  // Sign or zero extend category 1 types < 32bits in size to 32bits.
+  llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
+
+  // Truncate category 1 types from 32bits to the given JType size.
+  llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
+
+  //----------------------------------------------------------------------------
+  // Dex cache code generation helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
+
+  llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
+
+  llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
+
+  llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
+
+  llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
+
+  //----------------------------------------------------------------------------
+  // Code generation helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitLoadMethodObjectAddr();
+
+  llvm::Value* EmitLoadArrayLength(llvm::Value* array);
+
+  llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
+
+  llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
+                                                     llvm::Value* this_addr);
+
+  llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
+                            llvm::Value* index_value,
+                            JType elem_jty);
+
+  //----------------------------------------------------------------------------
+  // Invoke helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitInvoke(llvm::CallInst& call_inst);
+
+  //----------------------------------------------------------------------------
+  // Inlining helper functions
+  //----------------------------------------------------------------------------
+  bool EmitIntrinsic(llvm::CallInst& call_inst, llvm::Value** result);
+
+  bool EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
+                                          llvm::Value** result, bool is_empty);
+
+ private:
+  //----------------------------------------------------------------------------
+  // Expand Greenland intrinsics
+  //----------------------------------------------------------------------------
+  void Expand_TestSuspend(llvm::CallInst& call_inst);
+
+  void Expand_MarkGCCard(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
+
+  llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
+
+  void Expand_LockObject(llvm::Value* obj);
+
+  void Expand_UnlockObject(llvm::Value* obj);
+
+  llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
+                               llvm::Value* index_value,
+                               JType elem_jty);
+
+  void Expand_ArrayPut(llvm::Value* new_value,
+                       llvm::Value* array_addr,
+                       llvm::Value* index_value,
+                       JType elem_jty);
+
+  void Expand_FilledNewArray(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
+                               llvm::Value* is_volatile_value,
+                               llvm::Value* object_addr,
+                               JType field_jty);
+
+  void Expand_IPutFast(llvm::Value* field_offset_value,
+                       llvm::Value* is_volatile_value,
+                       llvm::Value* object_addr,
+                       llvm::Value* new_value,
+                       JType field_jty);
+
+  llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
+                               llvm::Value* field_offset_value,
+                               llvm::Value* is_volatile_value,
+                               JType field_jty);
+
+  void Expand_SPutFast(llvm::Value* static_storage_addr,
+                       llvm::Value* field_offset_value,
+                       llvm::Value* is_volatile_value,
+                       llvm::Value* new_value,
+                       JType field_jty);
+
+  llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
+
+  llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
+
+  llvm::Value*
+  Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
+
+  llvm::Value*
+  Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
+                                           llvm::Value* this_addr);
+
+  llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
+
+  void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
+
+  void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
+
+  void Expand_PopShadowFrame();
+
+  void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
+
+  //----------------------------------------------------------------------------
+  // Quick
+  //----------------------------------------------------------------------------
+
+  llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
+                                llvm::Value* src2_value,
+                                bool gt_bias);
+
+  llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
+
+  llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                          llvm::Value* cmp_lt);
+
+  llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
+  llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
+
+  llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
+  void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
+
+  llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
+  void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
+
+  llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
+  void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
+
+  llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
+  llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
+
+  void Expand_MonitorEnter(llvm::CallInst& call_inst);
+  void Expand_MonitorExit(llvm::CallInst& call_inst);
+
+  void Expand_HLCheckCast(llvm::CallInst& call_inst);
+  llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
+  llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
+  llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
+  void Expand_HLFillArrayData(llvm::CallInst& call_inst);
+
+  llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
+                                 llvm::Value* array_length_value,
+                                 uint32_t type_idx,
+                                 bool is_filled_new_array);
+
+  llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
+                                                        art::InvokeType invoke_type,
+                                                        llvm::Value* this_addr,
+                                                        uint32_t dex_pc,
+                                                        bool is_fast_path);
+
+  void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
+
+  void EmitUpdateDexPC(uint32_t dex_pc);
+
+  void EmitGuard_DivZeroException(uint32_t dex_pc,
+                                  llvm::Value* denominator,
+                                  JType op_jty);
+
+  void EmitGuard_NullPointerException(uint32_t dex_pc, llvm::Value* object,
+                                      int opt_flags);
+
+  void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
+                                                llvm::Value* array,
+                                                llvm::Value* index,
+                                                int opt_flags);
+
+  llvm::FunctionType* GetFunctionType(llvm::Type* ret_type, uint32_t method_idx, bool is_static);
+
+  llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
+
+  llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
+                                              const char* postfix);
+
+  int32_t GetTryItemOffset(uint32_t dex_pc);
+
+  llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
+
+  llvm::BasicBlock* GetUnwindBasicBlock();
+
+  void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
+
+  void EmitBranchExceptionLandingPad(uint32_t dex_pc);
+
+  //----------------------------------------------------------------------------
+  // Expand Arithmetic Helper Intrinsics
+  //----------------------------------------------------------------------------
+
+  llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
+                                   llvm::Value* src2_value,
+                                   IntegerShiftKind kind,
+                                   JType op_jty);
+
+ public:
+  static char ID;
+
+  GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
+                  art::CompilerDriver* driver, const art::DexCompilationUnit* dex_compilation_unit)
+      : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
+        context_(irb.getContext()), rtb_(irb.Runtime()),
+        shadow_frame_(NULL), old_shadow_frame_(NULL),
+        driver_(driver),
+        dex_compilation_unit_(dex_compilation_unit),
+        func_(NULL), current_bb_(NULL), basic_block_unwind_(NULL), changed_(false) {}
+
+  bool runOnFunction(llvm::Function& func);
+
+ private:
+  void InsertStackOverflowCheck(llvm::Function& func);
+
+  llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
+                               llvm::CallInst& call_inst);
+
+};
+
+char GBCExpanderPass::ID = 0;
+
+bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
+  VLOG(compiler) << "GBC expansion on " << func.getName().str();
+
+  // Runtime support or stub
+  if (dex_compilation_unit_ == NULL) {
+    return false;
+  }
+
+  // Setup rewrite context
+  shadow_frame_ = NULL;
+  old_shadow_frame_ = NULL;
+  func_ = &func;
+  changed_ = false; // Assume unchanged
+
+  shadow_frame_vreg_addresses_.resize(dex_compilation_unit_->GetCodeItem()->registers_size_, NULL);
+  basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
+  basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL);
+  basic_block_unwind_ = NULL;
+  for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
+       bb_iter != bb_end;
+       ++bb_iter) {
+    if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
+      continue;
+    }
+    uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
+    basic_blocks_[dex_pc] = bb_iter;
+  }
+
+  // Insert stack overflow check
+  InsertStackOverflowCheck(func); // TODO: Use intrinsic.
+
+  // Rewrite the intrinsics
+  RewriteFunction();
+
+  VERIFY_LLVM_FUNCTION(func);
+
+  return changed_;
+}
+
+void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
+  llvm::BasicBlock* curr_basic_block = original_block;
+
+  llvm::BasicBlock::iterator inst_iter = original_block->begin();
+  llvm::BasicBlock::iterator inst_end = original_block->end();
+
+  while (inst_iter != inst_end) {
+    llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
+    IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
+
+    if (call_inst) {
+      llvm::Function* callee_func = call_inst->getCalledFunction();
+      intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
+    }
+
+    if (intr_id == IntrinsicHelper::UnknownId) {
+      // This is not intrinsic call.  Skip this instruction.
+      ++inst_iter;
+      continue;
+    }
+
+    // Rewrite the intrinsic and change the function
+    changed_ = true;
+    irb_.SetInsertPoint(inst_iter);
+
+    // Expand the intrinsic
+    if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
+      inst_iter->replaceAllUsesWith(new_value);
+    }
+
+    // Remove the old intrinsic call instruction
+    llvm::BasicBlock::iterator old_inst = inst_iter++;
+    old_inst->eraseFromParent();
+
+    // Splice the instruction to the new basic block
+    llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
+    if (next_basic_block != curr_basic_block) {
+      next_basic_block->getInstList().splice(
+          irb_.GetInsertPoint(), curr_basic_block->getInstList(),
+          inst_iter, inst_end);
+      curr_basic_block = next_basic_block;
+      inst_end = curr_basic_block->end();
+    }
+  }
+}
+
+
+void GBCExpanderPass::RewriteFunction() {
+  size_t num_basic_blocks = func_->getBasicBlockList().size();
+  // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
+  // because we will create new basic block while expanding the intrinsics.
+  // We only want to iterate through the input basic blocks.
+
+  landing_pad_phi_mapping_.clear();
+
+  for (llvm::Function::iterator bb_iter = func_->begin();
+       num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
+    // Set insert point to current basic block.
+    irb_.SetInsertPoint(bb_iter);
+
+    current_bb_ = bb_iter;
+
+    // Rewrite the basic block
+    RewriteBasicBlock(bb_iter);
+
+    // Update the phi-instructions in the successor basic block
+    llvm::BasicBlock* last_block = irb_.GetInsertBlock();
+    if (last_block != bb_iter) {
+      UpdatePhiInstruction(bb_iter, last_block);
+    }
+  }
+
+  typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
+  HandlerPHIMap handler_phi;
+  // Iterate every used landing pad basic block
+  for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
+    llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
+    if (lbb == NULL) {
+      continue;
+    }
+
+    llvm::TerminatorInst* term_inst = lbb->getTerminator();
+    std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
+        = landing_pad_phi_mapping_[lbb];
+    irb_.SetInsertPoint(lbb->begin());
+
+    // Iterate every succeeding basic block (catch block)
+    for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
+         succ_iter != succ_end; ++succ_iter) {
+      llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
+
+      // Iterate every phi instructions in the succeeding basic block
+      for (llvm::BasicBlock::iterator
+           inst_iter = succ_basic_block->begin(),
+           inst_end = succ_basic_block->end();
+           inst_iter != inst_end; ++inst_iter) {
+        llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
+
+        if (!phi) {
+          break; // Meet non-phi instruction.  Done.
+        }
+
+        if (handler_phi[phi] == NULL) {
+          handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
+        }
+
+        // Create new_phi in landing pad
+        llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
+        // Insert all incoming value into new_phi by rewrite_pair
+        for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
+          llvm::BasicBlock* old_bb = rewrite_pair[j].first;
+          llvm::BasicBlock* new_bb = rewrite_pair[j].second;
+          new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
+        }
+        // Delete all incoming value from phi by rewrite_pair
+        for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
+          llvm::BasicBlock* old_bb = rewrite_pair[j].first;
+          int old_bb_idx = phi->getBasicBlockIndex(old_bb);
+          if (old_bb_idx >= 0) {
+            phi->removeIncomingValue(old_bb_idx, false);
+          }
+        }
+        // Insert new_phi into new handler phi
+        handler_phi[phi]->addIncoming(new_phi, lbb);
+      }
+    }
+  }
+
+  // Replace all handler phi
+  // We can't just use the old handler phi, because some exception edges will disappear after we
+  // compute fast-path.
+  for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
+    llvm::PHINode* old_phi = it->first;
+    llvm::PHINode* new_phi = it->second;
+    new_phi->insertBefore(old_phi);
+    old_phi->replaceAllUsesWith(new_phi);
+    old_phi->eraseFromParent();
+  }
+}
+
+void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
+                                           llvm::BasicBlock* new_basic_block) {
+  llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
+
+  if (!term_inst) {
+    return; // No terminating instruction in new_basic_block.  Nothing to do.
+  }
+
+  // Iterate every succeeding basic block
+  for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
+       succ_iter != succ_end; ++succ_iter) {
+    llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
+
+    // Iterate every phi instructions in the succeeding basic block
+    for (llvm::BasicBlock::iterator
+         inst_iter = succ_basic_block->begin(),
+         inst_end = succ_basic_block->end();
+         inst_iter != inst_end; ++inst_iter) {
+      llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
+
+      if (!phi) {
+        break; // Meet non-phi instruction.  Done.
+      }
+
+      // Update the incoming block of this phi instruction
+      for (llvm::PHINode::block_iterator
+           ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
+           ibb_iter != ibb_end; ++ibb_iter) {
+        if (*ibb_iter == old_basic_block) {
+          *ibb_iter = new_basic_block;
+        }
+      }
+    }
+  }
+}
+
+llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
+                                              llvm::CallInst& inst) {
+  // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
+  // the arguments passed to the GBC intrinsic are as the same as IBC runtime
+  // function, therefore only called function is needed to change.
+  unsigned num_args = inst.getNumArgOperands();
+
+  if (num_args <= 0) {
+    return irb_.CreateCall(irb_.GetRuntime(rt));
+  } else {
+    std::vector<llvm::Value*> args;
+    for (unsigned i = 0; i < num_args; i++) {
+      args.push_back(inst.getArgOperand(i));
+    }
+
+    return irb_.CreateCall(irb_.GetRuntime(rt), args);
+  }
+}
+
+void
+GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
+  llvm::Function* func = first_non_alloca->getParent()->getParent();
+  llvm::Module* module = func->getParent();
+
+  // Call llvm intrinsic function to get frame address.
+  llvm::Function* frameaddress =
+      llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
+
+  // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
+  llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
+
+  // Cast i8* to int
+  frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
+
+  // Get thread.stack_end_
+  llvm::Value* stack_end =
+    irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
+                                            irb_.getPtrEquivIntTy(),
+                                            kTBAARuntimeInfo);
+
+  // Check the frame address < thread.stack_end_ ?
+  llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
+
+  llvm::BasicBlock* block_exception =
+      llvm::BasicBlock::Create(context_, "stack_overflow", func);
+
+  llvm::BasicBlock* block_continue =
+      llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
+
+  irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
+
+  // If stack overflow, throw exception.
+  irb_.SetInsertPoint(block_exception);
+  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
+
+  // Unwind.
+  llvm::Type* ret_type = func->getReturnType();
+  if (ret_type->isVoidTy()) {
+    irb_.CreateRetVoid();
+  } else {
+    // The return value is ignored when there's an exception. MethodCompiler
+    // returns zero value under the the corresponding return type  in this case.
+    // GBCExpander returns LLVM undef value here for brevity
+    irb_.CreateRet(llvm::UndefValue::get(ret_type));
+  }
+
+  irb_.SetInsertPoint(block_continue);
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  return irb_.LoadFromObjectOffset(method_object_addr,
+                                   offset.Int32Value(),
+                                   irb_.getJObjectTy(),
+                                   kTBAAConstJObject);
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
+  llvm::Value* static_storage_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
+
+  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
+
+  return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
+  llvm::Value* resolved_type_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
+
+  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
+
+  return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
+  llvm::Value* resolved_method_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
+
+  llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
+
+  return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
+  llvm::Value* string_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
+
+  llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
+
+  return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
+  llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+  return parent_func->arg_begin();
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
+  // Load array length
+  return irb_.LoadFromObjectOffset(array,
+                                   art::mirror::Array::LengthOffset().Int32Value(),
+                                   irb_.getJIntTy(),
+                                   kTBAAConstJObject);
+
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
+  llvm::Value* callee_method_object_field_addr =
+    EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
+
+  return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
+  // Load class object of *this* pointer
+  llvm::Value* class_object_addr =
+    irb_.LoadFromObjectOffset(this_addr,
+                              art::mirror::Object::ClassOffset().Int32Value(),
+                              irb_.getJObjectTy(),
+                              kTBAAConstJObject);
+
+  // Load vtable address
+  llvm::Value* vtable_addr =
+    irb_.LoadFromObjectOffset(class_object_addr,
+                              art::mirror::Class::VTableOffset().Int32Value(),
+                              irb_.getJObjectTy(),
+                              kTBAAConstJObject);
+
+  // Load callee method object
+  llvm::Value* vtable_idx_value =
+    irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
+
+  llvm::Value* method_field_addr =
+    EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
+
+  return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
+}
+
+// Emit Array GetElementPtr
+llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
+                                           llvm::Value* index_value,
+                                           JType elem_jty) {
+
+  int data_offset;
+  if (elem_jty == kLong || elem_jty == kDouble ||
+      (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
+    data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
+  } else {
+    data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
+  }
+
+  llvm::Constant* data_offset_value =
+    irb_.getPtrEquivInt(data_offset);
+
+  llvm::Type* elem_type = irb_.getJType(elem_jty);
+
+  llvm::Value* array_data_addr =
+    irb_.CreatePtrDisp(array_addr, data_offset_value,
+                       elem_type->getPointerTo());
+
+  return irb_.CreateGEP(array_data_addr, index_value);
+}
+
+llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  art::InvokeType invoke_type =
+      static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
+  bool is_static = (invoke_type == art::kStatic);
+  art::MethodReference target_method(dex_compilation_unit_->GetDexFile(),
+                                     LV2UInt(call_inst.getArgOperand(1)));
+
+  // Load *this* actual parameter
+  llvm::Value* this_addr = (!is_static) ? call_inst.getArgOperand(3) : NULL;
+
+  // Compute invoke related information for compiler decision
+  int vtable_idx = -1;
+  uintptr_t direct_code = 0;
+  uintptr_t direct_method = 0;
+  bool is_fast_path = driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc,
+                                                 invoke_type, target_method,
+                                                 vtable_idx,
+                                                 direct_code, direct_method,
+                                                 true);
+  // Load the method object
+  llvm::Value* callee_method_object_addr = NULL;
+
+  if (!is_fast_path) {
+    callee_method_object_addr =
+        EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index, invoke_type,
+                                                 this_addr, dex_pc, is_fast_path);
+  } else {
+    switch (invoke_type) {
+      case art::kStatic:
+      case art::kDirect:
+        if (direct_method != 0u &&
+            direct_method != static_cast<uintptr_t>(-1)) {
+          callee_method_object_addr =
+              irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
+                                  irb_.getJObjectTy());
+        } else {
+          callee_method_object_addr =
+              EmitLoadSDCalleeMethodObjectAddr(target_method.dex_method_index);
+        }
+        break;
+
+      case art::kVirtual:
+        DCHECK(vtable_idx != -1);
+        callee_method_object_addr =
+            EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
+        break;
+
+      case art::kSuper:
+        LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
+        "the fast path.";
+        break;
+
+      case art::kInterface:
+        callee_method_object_addr =
+            EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index,
+                                                     invoke_type, this_addr,
+                                                     dex_pc, is_fast_path);
+        break;
+    }
+  }
+
+  // Load the actual parameter
+  std::vector<llvm::Value*> args;
+
+  args.push_back(callee_method_object_addr); // method object for callee
+
+  for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
+    args.push_back(call_inst.getArgOperand(i));
+  }
+
+  llvm::Value* code_addr;
+  llvm::Type* func_type = GetFunctionType(call_inst.getType(),
+                                          target_method.dex_method_index, is_static);
+  if (direct_code != 0u && direct_code != static_cast<uintptr_t>(-1)) {
+    code_addr =
+        irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
+                            func_type->getPointerTo());
+  } else {
+    code_addr =
+        irb_.LoadFromObjectOffset(callee_method_object_addr,
+                                  art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+                                  func_type->getPointerTo(), kTBAARuntimeInfo);
+  }
+
+  // Invoke callee
+  EmitUpdateDexPC(dex_pc);
+  llvm::Value* retval = irb_.CreateCall(code_addr, args);
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return retval;
+}
+
+bool GBCExpanderPass::EmitIntrinsic(llvm::CallInst& call_inst,
+                                    llvm::Value** result) {
+  DCHECK(result != NULL);
+
+  uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
+  std::string callee_method_name(
+      PrettyMethod(callee_method_idx, *dex_compilation_unit_->GetDexFile()));
+
+  if (callee_method_name == "int java.lang.String.length()") {
+    return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
+                                              false /* is_empty */);
+  }
+  if (callee_method_name == "boolean java.lang.String.isEmpty()") {
+    return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
+                                              true /* is_empty */);
+  }
+
+  *result = NULL;
+  return false;
+}
+
+bool GBCExpanderPass::EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
+                                                         llvm::Value** result,
+                                                         bool is_empty) {
+  art::InvokeType invoke_type =
+        static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
+  DCHECK_NE(invoke_type, art::kStatic);
+  DCHECK_EQ(call_inst.getNumArgOperands(), 4U);
+
+  llvm::Value* this_object = call_inst.getArgOperand(3);
+  llvm::Value* string_count =
+      irb_.LoadFromObjectOffset(this_object,
+                                art::mirror::String::CountOffset().Int32Value(),
+                                irb_.getJIntTy(),
+                                kTBAAConstJObject);
+  if (is_empty) {
+    llvm::Value* count_equals_zero = irb_.CreateICmpEQ(string_count,
+                                                       irb_.getJInt(0));
+    llvm::Value* is_empty = irb_.CreateSelect(count_equals_zero,
+                                              irb_.getJBoolean(true),
+                                              irb_.getJBoolean(false));
+    is_empty = SignOrZeroExtendCat1Types(is_empty, kBoolean);
+    *result = is_empty;
+  } else {
+    *result = string_count;
+  }
+  return true;
+}
+
+void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+
+  llvm::Value* suspend_count =
+      irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
+                                              irb_.getInt16Ty(),
+                                              kTBAARuntimeInfo);
+  llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
+
+  llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
+  llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
+
+  irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_suspend);
+  if (dex_pc != art::DexFile::kDexNoIndex) {
+    EmitUpdateDexPC(dex_pc);
+  }
+  irb_.Runtime().EmitTestSuspend();
+
+  llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
+  llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
+  irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_exception);
+  llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
+  if (ret_type->isVoidTy()) {
+    irb_.CreateRetVoid();
+  } else {
+    // The return value is ignored when there's an exception.
+    irb_.CreateRet(llvm::UndefValue::get(ret_type));
+  }
+
+  irb_.SetInsertPoint(basic_block_cont);
+  return;
+}
+
+void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
+  irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
+  return;
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
+  uint32_t string_idx =
+    llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
+
+  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
+
+  return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
+  uint32_t type_idx =
+    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
+
+  llvm::Value* type_field_addr =
+    EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
+
+  return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
+}
+
+void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
+  rtb_.EmitLockObject(obj);
+  return;
+}
+
+void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
+  rtb_.EmitUnlockObject(obj);
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
+                                              llvm::Value* index_value,
+                                              JType elem_jty) {
+  llvm::Value* array_elem_addr =
+    EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
+}
+
+void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
+                                      llvm::Value* array_addr,
+                                      llvm::Value* index_value,
+                                      JType elem_jty) {
+  llvm::Value* array_elem_addr =
+    EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
+  // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
+  llvm::Value* array = call_inst.getArgOperand(0);
+
+  uint32_t element_jty =
+    llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
+
+  DCHECK(call_inst.getNumArgOperands() > 2);
+  unsigned num_elements = (call_inst.getNumArgOperands() - 2);
+
+  bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
+
+  uint32_t alignment;
+  llvm::Constant* elem_size;
+  llvm::PointerType* field_type;
+
+  // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
+  // as the element, thus we are only checking 2 cases: primitive int and
+  // non-primitive type.
+  if (is_elem_int_ty) {
+    alignment = sizeof(int32_t);
+    elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
+    field_type = irb_.getJIntTy()->getPointerTo();
+  } else {
+    alignment = irb_.getSizeOfPtrEquivInt();
+    elem_size = irb_.getSizeOfPtrEquivIntValue();
+    field_type = irb_.getJObjectTy()->getPointerTo();
+  }
+
+  llvm::Value* data_field_offset =
+    irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
+
+  llvm::Value* data_field_addr =
+    irb_.CreatePtrDisp(array, data_field_offset, field_type);
+
+  for (unsigned i = 0; i < num_elements; ++i) {
+    // Values to fill the array begin at the 3rd argument
+    llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
+
+    irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
+
+    data_field_addr =
+      irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
+                                              llvm::Value* /*is_volatile_value*/,
+                                              llvm::Value* object_addr,
+                                              JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::PointerType* field_type =
+    irb_.getJType(field_jty)->getPointerTo();
+
+  field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* field_addr =
+    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+  // TODO: Check is_volatile.  We need to generate atomic load instruction
+  // when is_volatile is true.
+  return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
+}
+
+void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
+                                      llvm::Value* /* is_volatile_value */,
+                                      llvm::Value* object_addr,
+                                      llvm::Value* new_value,
+                                      JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::PointerType* field_type =
+    irb_.getJType(field_jty)->getPointerTo();
+
+  field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* field_addr =
+    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
+                                              llvm::Value* field_offset_value,
+                                              llvm::Value* /*is_volatile_value*/,
+                                              JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* static_field_addr =
+    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                       irb_.getJType(field_jty)->getPointerTo());
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
+}
+
+void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
+                                      llvm::Value* field_offset_value,
+                                      llvm::Value* /* is_volatile_value */,
+                                      llvm::Value* new_value,
+                                      JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* static_field_addr =
+    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                       irb_.getJType(field_jty)->getPointerTo());
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
+
+  return;
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
+  return irb_.LoadFromObjectOffset(method_object_addr,
+                                   art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+                                   irb_.getJObjectTy(),
+                                   kTBAAConstJObject);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
+  uint32_t type_idx =
+    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
+
+  llvm::Value* storage_field_addr =
+    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+
+  return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
+  uint32_t callee_method_idx =
+    llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
+
+  return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
+}
+
+llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
+    llvm::Value* vtable_idx_value,
+    llvm::Value* this_addr) {
+  int vtable_idx =
+    llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
+
+  return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
+}
+
+llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
+  // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
+  llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
+  unsigned num_args = call_inst.getNumArgOperands();
+  llvm::Type* ret_type = call_inst.getType();
+
+  // Determine the function type of the callee method
+  std::vector<llvm::Type*> args_type;
+  std::vector<llvm::Value*> args;
+  for (unsigned i = 0; i < num_args; i++) {
+    args.push_back(call_inst.getArgOperand(i));
+    args_type.push_back(args[i]->getType());
+  }
+
+  llvm::FunctionType* callee_method_type =
+    llvm::FunctionType::get(ret_type, args_type, false);
+
+  llvm::Value* code_addr =
+    irb_.LoadFromObjectOffset(callee_method_object_addr,
+                              art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+                              callee_method_type->getPointerTo(),
+                              kTBAARuntimeInfo);
+
+  // Invoke callee
+  llvm::Value* retval = irb_.CreateCall(code_addr, args);
+
+  return retval;
+}
+
+llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
+                                            bool is_div, JType op_jty) {
+  llvm::Value* dividend = call_inst.getArgOperand(0);
+  llvm::Value* divisor = call_inst.getArgOperand(1);
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
+  // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
+
+  // Check the special case: MININT / -1 = MININT
+  // That case will cause overflow, which is undefined behavior in llvm.
+  // So we check the divisor is -1 or not, if the divisor is -1, we do
+  // the special path to avoid undefined behavior.
+  llvm::Type* op_type = irb_.getJType(op_jty);
+  llvm::Value* zero = irb_.getJZero(op_jty);
+  llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
+
+  llvm::Function* parent = irb_.GetInsertBlock()->getParent();
+  llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* neg_one_cont =
+    llvm::BasicBlock::Create(context_, "", parent);
+
+  llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
+  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
+
+  // If divisor == -1
+  irb_.SetInsertPoint(eq_neg_one);
+  llvm::Value* eq_result;
+  if (is_div) {
+    // We can just change from "dividend div -1" to "neg dividend". The sub
+    // don't care the sign/unsigned because of two's complement representation.
+    // And the behavior is what we want:
+    //  -(2^n)        (2^n)-1
+    //  MININT  < k <= MAXINT    ->     mul k -1  =  -k
+    //  MININT == k              ->     mul k -1  =   k
+    //
+    // LLVM use sub to represent 'neg'
+    eq_result = irb_.CreateSub(zero, dividend);
+  } else {
+    // Everything modulo -1 will be 0.
+    eq_result = zero;
+  }
+  irb_.CreateBr(neg_one_cont);
+
+  // If divisor != -1, just do the division.
+  irb_.SetInsertPoint(ne_neg_one);
+  llvm::Value* ne_result;
+  if (is_div) {
+    ne_result = irb_.CreateSDiv(dividend, divisor);
+  } else {
+    ne_result = irb_.CreateSRem(dividend, divisor);
+  }
+  irb_.CreateBr(neg_one_cont);
+
+  irb_.SetInsertPoint(neg_one_cont);
+  llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
+  result->addIncoming(eq_result, eq_neg_one);
+  result->addIncoming(ne_result, ne_neg_one);
+
+  return result;
+}
+
+void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
+  // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
+  // MethodCompiler::EmitPushShadowFrame
+  uint16_t num_vregs =
+    llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
+
+  llvm::StructType* shadow_frame_type =
+    irb_.getShadowFrameTy(num_vregs);
+
+  // Create allocas at the start of entry block.
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+  llvm::BasicBlock* entry_block = &func_->front();
+  irb_.SetInsertPoint(&entry_block->front());
+
+  shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
+
+  // Alloca a pointer to old shadow frame
+  old_shadow_frame_ =
+    irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
+
+  irb_.restoreIP(irb_ip_original);
+
+  // Push the shadow frame
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* shadow_frame_upcast =
+    irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
+
+  llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
+                                                 method_object_addr,
+                                                 num_vregs);
+
+  irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
+                                     llvm::Value* value) {
+  unsigned vreg_idx = LV2UInt(entry_idx);
+  DCHECK_LT(vreg_idx, dex_compilation_unit_->GetCodeItem()->registers_size_);
+
+  llvm::Value* vreg_addr = shadow_frame_vreg_addresses_[vreg_idx];
+  if (UNLIKELY(vreg_addr == NULL)) {
+    DCHECK(shadow_frame_ != NULL);
+
+    llvm::Value* gep_index[] = {
+      irb_.getInt32(0), // No pointer displacement
+      irb_.getInt32(1), // VRegs
+      entry_idx // Pointer field
+    };
+
+    // A shadow frame address must dominate every use in the function so we
+    // place it in the entry block right after the allocas.
+    llvm::BasicBlock::iterator first_non_alloca = func_->getEntryBlock().begin();
+    while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
+      ++first_non_alloca;
+    }
+
+    llvm::IRBuilderBase::InsertPoint ip = irb_.saveIP();
+    irb_.SetInsertPoint(static_cast<llvm::Instruction*>(first_non_alloca));
+    vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+    shadow_frame_vreg_addresses_[vreg_idx] = vreg_addr;
+    irb_.restoreIP(ip);
+  }
+
+  irb_.CreateStore(value,
+                   irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
+                   kTBAAShadowFrame);
+  return;
+}
+
+void GBCExpanderPass::Expand_PopShadowFrame() {
+  if (old_shadow_frame_ == NULL) {
+    return;
+  }
+  rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
+  return;
+}
+
+void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
+  irb_.StoreToObjectOffset(shadow_frame_,
+                           art::ShadowFrame::DexPCOffset(),
+                           dex_pc_value,
+                           kTBAAShadowFrame);
+  return;
+}
+
+void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
+  // All alloca instructions are generated in the first basic block of the
+  // function, and there are no alloca instructions after the first non-alloca
+  // instruction.
+
+  llvm::BasicBlock* first_basic_block = &func.front();
+
+  // Look for first non-alloca instruction
+  llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
+  while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
+    ++first_non_alloca;
+  }
+
+  irb_.SetInsertPoint(first_non_alloca);
+
+  // Insert stack overflow check codes before first_non_alloca (i.e., after all
+  // alloca instructions)
+  EmitStackOverflowCheck(&*first_non_alloca);
+
+  irb_.Runtime().EmitTestSuspend();
+
+  llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
+  if (next_basic_block != first_basic_block) {
+    // Splice the rest of the instruction to the continuing basic block
+    next_basic_block->getInstList().splice(
+        irb_.GetInsertPoint(), first_basic_block->getInstList(),
+        first_non_alloca, first_basic_block->end());
+
+    // Rewrite the basic block
+    RewriteBasicBlock(next_basic_block);
+
+    // Update the phi-instructions in the successor basic block
+    UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
+  }
+
+  // We have changed the basic block
+  changed_ = true;
+}
+
+// ==== High-level intrinsic expander ==========================================
+
+llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
+                                               llvm::Value* src2_value,
+                                               bool gt_bias) {
+  llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt;
+
+  if (gt_bias) {
+    cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
+  } else {
+    cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
+  }
+
+  return EmitCompareResultSelection(cmp_eq, cmp_lt);
+}
+
+llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
+  llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
+
+  return EmitCompareResultSelection(cmp_eq, cmp_lt);
+}
+
+llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                                         llvm::Value* cmp_lt) {
+
+  llvm::Constant* zero = irb_.getJInt(0);
+  llvm::Constant* pos1 = irb_.getJInt(1);
+  llvm::Constant* neg1 = irb_.getJInt(-1);
+
+  llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
+  llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
+
+  return result_eq;
+}
+
+llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
+                                                  llvm::Value* src2_value,
+                                                  IntegerShiftKind kind,
+                                                  JType op_jty) {
+  DCHECK(op_jty == kInt || op_jty == kLong);
+
+  // Mask and zero-extend RHS properly
+  if (op_jty == kInt) {
+    src2_value = irb_.CreateAnd(src2_value, 0x1f);
+  } else {
+    llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
+    src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
+  }
+
+  // Create integer shift llvm instruction
+  switch (kind) {
+  case kIntegerSHL:
+    return irb_.CreateShl(src1_value, src2_value);
+
+  case kIntegerSHR:
+    return irb_.CreateAShr(src1_value, src2_value);
+
+  case kIntegerUSHR:
+    return irb_.CreateLShr(src1_value, src2_value);
+
+  default:
+    LOG(FATAL) << "Unknown integer shift kind: " << kind;
+    return NULL;
+  }
+}
+
+llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
+  switch (jty) {
+    case kBoolean:
+    case kChar:
+      return irb_.CreateZExt(value, irb_.getJType(kInt));
+    case kByte:
+    case kShort:
+      return irb_.CreateSExt(value, irb_.getJType(kInt));
+    case kVoid:
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kObject:
+      return value;  // Nothing to do.
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
+      return NULL;
+  }
+}
+
+llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
+  switch (jty) {
+    case kBoolean:
+    case kChar:
+    case kByte:
+    case kShort:
+      return irb_.CreateTrunc(value, irb_.getJType(jty));
+    case kVoid:
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kObject:
+      return value;  // Nothing to do.
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
+      return NULL;
+  }
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
+                                                JType elem_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* array_addr = call_inst.getArgOperand(1);
+  llvm::Value* index_value = call_inst.getArgOperand(2);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
+  EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
+                                           opt_flags);
+
+  llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
+}
+
+
+void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
+                                        JType elem_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* new_value = call_inst.getArgOperand(1);
+  llvm::Value* array_addr = call_inst.getArgOperand(2);
+  llvm::Value* index_value = call_inst.getArgOperand(3);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
+  EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
+                                           opt_flags);
+
+  new_value = TruncateCat1Types(new_value, elem_jty);
+
+  llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
+
+    irb_.CreateCall2(runtime_func, new_value, array_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    EmitMarkGCCard(new_value, array_addr);
+  }
+
+  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
+                                            JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  llvm::Value* field_value;
+
+  int field_offset;
+  bool is_volatile;
+  bool is_fast_path = driver_->ComputeInstanceFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, is_volatile, false);
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
+    }
+
+    llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    field_value = irb_.CreateCall3(runtime_func, field_idx_value,
+                                   method_object_addr, object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    if (field_jty == kFloat || field_jty == kDouble) {
+      field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
+    }
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    llvm::PointerType* field_type =
+      irb_.getJType(field_jty)->getPointerTo();
+
+    llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* field_addr =
+      irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+    field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
+    field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kLoadLoad);
+    }
+  }
+
+  return field_value;
+}
+
+void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
+                                    JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* new_value = call_inst.getArgOperand(1);
+  llvm::Value* object_addr = call_inst.getArgOperand(2);
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  int field_offset;
+  bool is_volatile;
+  bool is_fast_path = driver_->ComputeInstanceFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, is_volatile, true);
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kFloat) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
+    } else if (field_jty == kDouble) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
+    }
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
+    }
+
+    llvm::Value* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    irb_.CreateCall4(runtime_func, field_idx_value,
+                     method_object_addr, object_addr, new_value);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+    }
+
+    llvm::PointerType* field_type =
+      irb_.getJType(field_jty)->getPointerTo();
+
+    llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* field_addr =
+      irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+    new_value = TruncateCat1Types(new_value, field_jty);
+    irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kLoadLoad);
+    }
+
+    if (field_jty == kObject) { // If put an object, mark the GC card table.
+      EmitMarkGCCard(new_value, object_addr);
+    }
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
+                                                    uint32_t type_idx) {
+  if (!driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
+                                           *dex_compilation_unit_->GetDexFile(), type_idx)) {
+    llvm::Value* type_idx_value = irb_.getInt32(type_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+    llvm::Function* runtime_func =
+      irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
+
+    EmitUpdateDexPC(dex_pc);
+
+    llvm::Value* type_object_addr =
+      irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    return type_object_addr;
+
+  } else {
+    // Try to load the class (type) object from the test cache.
+    llvm::Value* type_field_addr =
+      EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
+
+    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
+
+    if (driver_->CanAssumeTypeIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(), type_idx)) {
+      return type_object_addr;
+    }
+
+    llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+
+    // Test whether class (type) object is in the dex cache or not
+    llvm::Value* equal_null =
+      irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
+
+    llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    llvm::BasicBlock* block_load_class =
+      CreateBasicBlockWithDexPC(dex_pc, "load_class");
+
+    irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
+
+    // Failback routine to load the class object
+    irb_.SetInsertPoint(block_load_class);
+
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
+
+    llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+    EmitUpdateDexPC(dex_pc);
+
+    llvm::Value* loaded_type_object_addr =
+      irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
+
+    irb_.CreateBr(block_cont);
+
+    // Now the class object must be loaded
+    irb_.SetInsertPoint(block_cont);
+
+    llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
+
+    phi->addIncoming(type_object_addr, block_original);
+    phi->addIncoming(loaded_type_object_addr, block_after_load_class);
+
+    return phi;
+  }
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
+                                                    uint32_t type_idx) {
+  llvm::BasicBlock* block_load_static =
+    CreateBasicBlockWithDexPC(dex_pc, "load_static");
+
+  llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  // Load static storage from dex cache
+  llvm::Value* storage_field_addr =
+    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+
+  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
+
+  llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+
+  // Test: Is the static storage of this class initialized?
+  llvm::Value* equal_null =
+    irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
+
+  irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
+
+  // Failback routine to load the class object
+  irb_.SetInsertPoint(block_load_static);
+
+  llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
+
+  llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* loaded_storage_object_addr =
+    irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
+
+  irb_.CreateBr(block_cont);
+
+  // Now the class object must be loaded
+  irb_.SetInsertPoint(block_cont);
+
+  llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
+
+  phi->addIncoming(storage_object_addr, block_original);
+  phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
+
+  return phi;
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
+                                            JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  int field_offset;
+  int ssb_index;
+  bool is_referrers_class;
+  bool is_volatile;
+
+  bool is_fast_path = driver_->ComputeStaticFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, ssb_index,
+    is_referrers_class, is_volatile, false);
+
+  llvm::Value* static_field_value;
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
+    }
+
+    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    static_field_value =
+      irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    if (field_jty == kFloat || field_jty == kDouble) {
+      static_field_value = irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
+    }
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    llvm::Value* static_storage_addr = NULL;
+
+    if (is_referrers_class) {
+      // Fast path, static storage base is this method's class
+      llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+      static_storage_addr =
+        irb_.LoadFromObjectOffset(method_object_addr,
+                                  art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+                                  irb_.getJObjectTy(),
+                                  kTBAAConstJObject);
+    } else {
+      // Medium path, static storage base in a different class which
+      // requires checks that the other class is initialized
+      DCHECK_GE(ssb_index, 0);
+      static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
+    }
+
+    llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* static_field_addr =
+      irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                         irb_.getJType(field_jty)->getPointerTo());
+
+    static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
+    static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kLoadLoad);
+    }
+  }
+
+  return static_field_value;
+}
+
+void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
+                                    JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* new_value = call_inst.getArgOperand(1);
+
+  if (field_jty == kFloat || field_jty == kDouble) {
+    new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
+  }
+
+  int field_offset;
+  int ssb_index;
+  bool is_referrers_class;
+  bool is_volatile;
+
+  bool is_fast_path = driver_->ComputeStaticFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, ssb_index,
+    is_referrers_class, is_volatile, true);
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
+    }
+
+    if (field_jty == kFloat) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
+    } else if (field_jty == kDouble) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
+    }
+
+    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    irb_.CreateCall3(runtime_func, field_idx_value,
+                     method_object_addr, new_value);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    llvm::Value* static_storage_addr = NULL;
+
+    if (is_referrers_class) {
+      // Fast path, static storage base is this method's class
+      llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+      static_storage_addr =
+        irb_.LoadFromObjectOffset(method_object_addr,
+                                  art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+                                  irb_.getJObjectTy(),
+                                  kTBAAConstJObject);
+    } else {
+      // Medium path, static storage base in a different class which
+      // requires checks that the other class is initialized
+      DCHECK_GE(ssb_index, 0);
+      static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
+    }
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+    }
+
+    llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* static_field_addr =
+      irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                         irb_.getJType(field_jty)->getPointerTo());
+
+    new_value = TruncateCat1Types(new_value, field_jty);
+    irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kStoreLoad);
+    }
+
+    if (field_jty == kObject) { // If put an object, mark the GC card table.
+      EmitMarkGCCard(new_value, static_storage_addr);
+    }
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
+
+  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
+
+  if (!driver_->CanAssumeStringIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(),
+                                                   string_idx)) {
+    llvm::BasicBlock* block_str_exist =
+      CreateBasicBlockWithDexPC(dex_pc, "str_exist");
+
+    llvm::BasicBlock* block_str_resolve =
+      CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
+
+    llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "str_cont");
+
+    // Test: Is the string resolved and in the dex cache?
+    llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
+
+    irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
+
+    // String is resolved, go to next basic block.
+    irb_.SetInsertPoint(block_str_exist);
+    irb_.CreateBr(block_cont);
+
+    // String is not resolved yet, resolve it now.
+    irb_.SetInsertPoint(block_str_resolve);
+
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    llvm::Value* string_idx_value = irb_.getInt32(string_idx);
+
+    EmitUpdateDexPC(dex_pc);
+
+    llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
+                                           string_idx_value);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    irb_.CreateBr(block_cont);
+
+
+    llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
+
+    irb_.SetInsertPoint(block_cont);
+
+    llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
+
+    phi->addIncoming(string_addr, block_str_exist);
+    phi->addIncoming(result, block_pre_cont);
+
+    string_addr = phi;
+  }
+
+  return string_addr;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
+
+  return type_object_addr;
+}
+
+void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  EmitUpdateDexPC(dex_pc);
+
+  irb_.Runtime().EmitLockObject(object_addr);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  EmitUpdateDexPC(dex_pc);
+
+  irb_.Runtime().EmitUnlockObject(object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+
+  llvm::BasicBlock* block_test_class =
+    CreateBasicBlockWithDexPC(dex_pc, "test_class");
+
+  llvm::BasicBlock* block_test_sub_class =
+    CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
+
+  llvm::BasicBlock* block_cont =
+    CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
+
+  // Test: Is the reference equal to null?  Act as no-op when it is null.
+  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
+
+  irb_.CreateCondBr(equal_null, block_cont, block_test_class, kUnlikely);
+
+  // Test: Is the object instantiated from the given class?
+  irb_.SetInsertPoint(block_test_class);
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
+  DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
+
+  llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
+
+  llvm::Value* object_type_field_addr =
+    irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
+
+  llvm::Value* object_type_object_addr =
+    irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
+
+  llvm::Value* equal_class =
+    irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
+
+  irb_.CreateCondBr(equal_class, block_cont, block_test_sub_class, kLikely);
+
+  // Test: Is the object instantiated from the subclass of the given class?
+  irb_.SetInsertPoint(block_test_sub_class);
+
+  EmitUpdateDexPC(dex_pc);
+
+  irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
+                   type_object_addr, object_type_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  irb_.CreateBr(block_cont);
+
+  irb_.SetInsertPoint(block_cont);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+
+  llvm::BasicBlock* block_nullp =
+      CreateBasicBlockWithDexPC(dex_pc, "nullp");
+
+  llvm::BasicBlock* block_test_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_class");
+
+  llvm::BasicBlock* block_class_equals =
+      CreateBasicBlockWithDexPC(dex_pc, "class_eq");
+
+  llvm::BasicBlock* block_test_sub_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
+
+  llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
+
+  // Overview of the following code :
+  // We check for null, if so, then false, otherwise check for class == . If so
+  // then true, otherwise do callout slowpath.
+  //
+  // Test: Is the reference equal to null?  Set 0 when it is null.
+  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
+
+  irb_.CreateCondBr(equal_null, block_nullp, block_test_class, kUnlikely);
+
+  irb_.SetInsertPoint(block_nullp);
+  irb_.CreateBr(block_cont);
+
+  // Test: Is the object instantiated from the given class?
+  irb_.SetInsertPoint(block_test_class);
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
+  DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
+
+  llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
+
+  llvm::Value* object_type_field_addr =
+    irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
+
+  llvm::Value* object_type_object_addr =
+    irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
+
+  llvm::Value* equal_class =
+    irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
+
+  irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class, kLikely);
+
+  irb_.SetInsertPoint(block_class_equals);
+  irb_.CreateBr(block_cont);
+
+  // Test: Is the object instantiated from the subclass of the given class?
+  irb_.SetInsertPoint(block_test_sub_class);
+  llvm::Value* result =
+    irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
+                     type_object_addr, object_type_object_addr);
+  irb_.CreateBr(block_cont);
+
+  irb_.SetInsertPoint(block_cont);
+
+  llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
+
+  phi->addIncoming(irb_.getJInt(0), block_nullp);
+  phi->addIncoming(irb_.getJInt(1), block_class_equals);
+  phi->addIncoming(result, block_test_sub_class);
+
+  return phi;
+}
+
+llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  llvm::Function* runtime_func;
+  if (driver_->CanAccessInstantiableTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
+                                                      *dex_compilation_unit_->GetDexFile(),
+                                                      type_idx)) {
+    runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
+  } else {
+    runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
+  }
+
+  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* object_addr =
+    irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return object_addr;
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
+  art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
+  bool is_static = (invoke_type == art::kStatic);
+
+  if (!is_static) {
+    // Test: Is *this* parameter equal to null?
+    uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+    llvm::Value* this_addr = call_inst.getArgOperand(3);
+    int opt_flags = LV2UInt(call_inst.getArgOperand(2));
+
+    EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
+  }
+
+  llvm::Value* result = NULL;
+  if (EmitIntrinsic(call_inst, &result)) {
+    return result;
+  }
+
+  return EmitInvoke(call_inst);
+}
+
+llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  // Get the array object address
+  llvm::Value* array_addr = call_inst.getArgOperand(1);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
+
+  // Get the array length and store it to the register
+  return EmitLoadArrayLength(array_addr);
+}
+
+llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* length = call_inst.getArgOperand(1);
+
+  return EmitAllocNewArray(dex_pc, length, type_idx, false);
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
+  uint32_t length = call_inst.getNumArgOperands() - 3;
+
+  llvm::Value* object_addr =
+    EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
+
+  if (length > 0) {
+    // Check for the element type
+    uint32_t type_desc_len = 0;
+    const char* type_desc =
+        dex_compilation_unit_->GetDexFile()->StringByTypeIdx(type_idx, &type_desc_len);
+
+    DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
+    DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
+    bool is_elem_int_ty = (type_desc[1] == 'I');
+
+    uint32_t alignment;
+    llvm::Constant* elem_size;
+    llvm::PointerType* field_type;
+
+    // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
+    // as the element, thus we are only checking 2 cases: primitive int and
+    // non-primitive type.
+    if (is_elem_int_ty) {
+      alignment = sizeof(int32_t);
+      elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
+      field_type = irb_.getJIntTy()->getPointerTo();
+    } else {
+      alignment = irb_.getSizeOfPtrEquivInt();
+      elem_size = irb_.getSizeOfPtrEquivIntValue();
+      field_type = irb_.getJObjectTy()->getPointerTo();
+    }
+
+    llvm::Value* data_field_offset =
+      irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
+
+    llvm::Value* data_field_addr =
+      irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
+
+    // TODO: Tune this code.  Currently we are generating one instruction for
+    // one element which may be very space consuming.  Maybe changing to use
+    // memcpy may help; however, since we can't guarantee that the alloca of
+    // dalvik register are continuous, we can't perform such optimization yet.
+    for (uint32_t i = 0; i < length; ++i) {
+      llvm::Value* reg_value = call_inst.getArgOperand(i+3);
+
+      irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
+
+      data_field_addr =
+        irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
+    }
+  }
+
+  return object_addr;
+}
+
+void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  int32_t payload_offset = static_cast<int32_t>(dex_pc) +
+                           LV2SInt(call_inst.getArgOperand(0));
+  llvm::Value* array_addr = call_inst.getArgOperand(1);
+
+  const art::Instruction::ArrayDataPayload* payload =
+    reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
+        dex_compilation_unit_->GetCodeItem()->insns_ + payload_offset);
+
+  if (payload->element_count == 0) {
+    // When the number of the elements in the payload is zero, we don't have
+    // to copy any numbers.  However, we should check whether the array object
+    // address is equal to null or not.
+    EmitGuard_NullPointerException(dex_pc, array_addr, 0);
+  } else {
+    // To save the code size, we are going to call the runtime function to
+    // copy the content from DexFile.
+
+    // NOTE: We will check for the NullPointerException in the runtime.
+
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    irb_.CreateCall4(runtime_func,
+                     method_object_addr, irb_.getInt32(dex_pc),
+                     array_addr, irb_.getInt32(payload_offset));
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
+                                                llvm::Value* array_length_value,
+                                                uint32_t type_idx,
+                                                bool is_filled_new_array) {
+  llvm::Function* runtime_func;
+
+  bool skip_access_check =
+    driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
+                                        *dex_compilation_unit_->GetDexFile(), type_idx);
+
+
+  if (is_filled_new_array) {
+    runtime_func = skip_access_check ?
+      irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
+      irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
+  } else {
+    runtime_func = skip_access_check ?
+      irb_.GetRuntime(runtime_support::AllocArray) :
+      irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
+  }
+
+  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* object_addr =
+    irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
+                     array_length_value, thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return object_addr;
+}
+
+llvm::Value* GBCExpanderPass::
+EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
+                                         art::InvokeType invoke_type,
+                                         llvm::Value* this_addr,
+                                         uint32_t dex_pc,
+                                         bool is_fast_path) {
+
+  llvm::Function* runtime_func = NULL;
+
+  switch (invoke_type) {
+  case art::kStatic:
+    runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
+    break;
+
+  case art::kDirect:
+    runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
+    break;
+
+  case art::kVirtual:
+    runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
+    break;
+
+  case art::kSuper:
+    runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
+    break;
+
+  case art::kInterface:
+    if (is_fast_path) {
+      runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
+    }
+    break;
+  }
+
+  llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
+
+  if (this_addr == NULL) {
+    DCHECK_EQ(invoke_type, art::kStatic);
+    this_addr = irb_.getJNull();
+  }
+
+  llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* callee_method_object_addr =
+    irb_.CreateCall4(runtime_func,
+                     callee_method_idx_value,
+                     this_addr,
+                     caller_method_object_addr,
+                     thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return callee_method_object_addr;
+}
+
+void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
+  // Using runtime support, let the target can override by InlineAssembly.
+  irb_.Runtime().EmitMarkGCCard(value, target_addr);
+}
+
+void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
+  if (shadow_frame_ == NULL) {
+    return;
+  }
+  irb_.StoreToObjectOffset(shadow_frame_,
+                           art::ShadowFrame::DexPCOffset(),
+                           irb_.getInt32(dex_pc),
+                           kTBAAShadowFrame);
+}
+
+void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
+                                                 llvm::Value* denominator,
+                                                 JType op_jty) {
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  llvm::Constant* zero = irb_.getJZero(op_jty);
+
+  llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
+
+  llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
+
+  llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
+
+  irb_.SetInsertPoint(block_exception);
+  EmitUpdateDexPC(dex_pc);
+  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
+  EmitBranchExceptionLandingPad(dex_pc);
+
+  irb_.SetInsertPoint(block_continue);
+}
+
+void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
+                                                     llvm::Value* object,
+                                                     int opt_flags) {
+  bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
+  if (ignore_null_check) {
+    llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
+    if (lpad) {
+      // There is at least one catch: create a "fake" conditional branch to
+      // keep the exception edge to the catch block.
+      landing_pad_phi_mapping_[lpad].push_back(
+          std::make_pair(current_bb_->getUniquePredecessor(),
+                         irb_.GetInsertBlock()));
+
+      llvm::BasicBlock* block_continue =
+          CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+      irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
+
+      irb_.SetInsertPoint(block_continue);
+    }
+  } else {
+    llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
+
+    llvm::BasicBlock* block_exception =
+        CreateBasicBlockWithDexPC(dex_pc, "nullp");
+
+    llvm::BasicBlock* block_continue =
+        CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
+
+    irb_.SetInsertPoint(block_exception);
+    EmitUpdateDexPC(dex_pc);
+    irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
+                    irb_.getInt32(dex_pc));
+    EmitBranchExceptionLandingPad(dex_pc);
+
+    irb_.SetInsertPoint(block_continue);
+  }
+}
+
+void
+GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
+                                                          llvm::Value* array,
+                                                          llvm::Value* index,
+                                                          int opt_flags) {
+  bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
+  if (ignore_range_check) {
+    llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
+    if (lpad) {
+      // There is at least one catch: create a "fake" conditional branch to
+      // keep the exception edge to the catch block.
+      landing_pad_phi_mapping_[lpad].push_back(
+          std::make_pair(current_bb_->getUniquePredecessor(),
+                         irb_.GetInsertBlock()));
+
+      llvm::BasicBlock* block_continue =
+          CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+      irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
+
+      irb_.SetInsertPoint(block_continue);
+    }
+  } else {
+    llvm::Value* array_len = EmitLoadArrayLength(array);
+
+    llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
+
+    llvm::BasicBlock* block_exception =
+        CreateBasicBlockWithDexPC(dex_pc, "overflow");
+
+    llvm::BasicBlock* block_continue =
+        CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
+
+    irb_.SetInsertPoint(block_exception);
+
+    EmitUpdateDexPC(dex_pc);
+    irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
+    EmitBranchExceptionLandingPad(dex_pc);
+
+    irb_.SetInsertPoint(block_continue);
+  }
+}
+
+llvm::FunctionType* GBCExpanderPass::GetFunctionType(llvm::Type* ret_type, uint32_t method_idx,
+                                                     bool is_static) {
+  // Get method signature
+  art::DexFile::MethodId const& method_id =
+      dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx);
+
+  uint32_t shorty_size;
+  const char* shorty = dex_compilation_unit_->GetDexFile()->GetMethodShorty(method_id, &shorty_size);
+  CHECK_GE(shorty_size, 1u);
+
+  // Get argument type
+  std::vector<llvm::Type*> args_type;
+
+  args_type.push_back(irb_.getJObjectTy()); // method object pointer
+
+  if (!is_static) {
+    args_type.push_back(irb_.getJType('L')); // "this" object pointer
+  }
+
+  for (uint32_t i = 1; i < shorty_size; ++i) {
+    char shorty_type = art::RemapShorty(shorty[i]);
+    args_type.push_back(irb_.getJType(shorty_type));
+  }
+
+  return llvm::FunctionType::get(ret_type, args_type, false);
+}
+
+
+llvm::BasicBlock* GBCExpanderPass::
+CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
+  std::string name;
+
+#if !defined(NDEBUG)
+  art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
+#endif
+
+  return llvm::BasicBlock::Create(context_, name, func_);
+}
+
+llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
+  DCHECK(dex_pc < dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
+  CHECK(basic_blocks_[dex_pc] != NULL);
+  return basic_blocks_[dex_pc];
+}
+
+int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
+  int32_t min = 0;
+  int32_t max = dex_compilation_unit_->GetCodeItem()->tries_size_ - 1;
+
+  while (min <= max) {
+    int32_t mid = min + (max - min) / 2;
+
+    const art::DexFile::TryItem* ti =
+        art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(), mid);
+    uint32_t start = ti->start_addr_;
+    uint32_t end = start + ti->insn_count_;
+
+    if (dex_pc < start) {
+      max = mid - 1;
+    } else if (dex_pc >= end) {
+      min = mid + 1;
+    } else {
+      return mid; // found
+    }
+  }
+
+  return -1; // not found
+}
+
+llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
+  // Find the try item for this address in this method
+  int32_t ti_offset = GetTryItemOffset(dex_pc);
+
+  if (ti_offset == -1) {
+    return NULL; // No landing pad is available for this address.
+  }
+
+  // Check for the existing landing pad basic block
+  DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
+  llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
+
+  if (block_lpad) {
+    // We have generated landing pad for this try item already.  Return the
+    // same basic block.
+    return block_lpad;
+  }
+
+  // Get try item from code item
+  const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(),
+                                                              ti_offset);
+
+  std::string lpadname;
+
+#if !defined(NDEBUG)
+  art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
+#endif
+
+  // Create landing pad basic block
+  block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
+
+  // Change IRBuilder insert point
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+  irb_.SetInsertPoint(block_lpad);
+
+  // Find catch block with matching type
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
+
+  llvm::Value* catch_handler_index_value =
+    irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
+                     method_object_addr, ti_offset_value);
+
+  // Switch instruction (Go to unwind basic block by default)
+  llvm::SwitchInst* sw =
+    irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
+
+  // Cases with matched catch block
+  art::CatchHandlerIterator iter(*dex_compilation_unit_->GetCodeItem(), ti->start_addr_);
+
+  for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
+    sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
+  }
+
+  // Restore the orignal insert point for IRBuilder
+  irb_.restoreIP(irb_ip_original);
+
+  // Cache this landing pad
+  DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
+  basic_block_landing_pads_[ti_offset] = block_lpad;
+
+  return block_lpad;
+}
+
+llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
+  // Check the existing unwinding baisc block block
+  if (basic_block_unwind_ != NULL) {
+    return basic_block_unwind_;
+  }
+
+  // Create new basic block for unwinding
+  basic_block_unwind_ =
+    llvm::BasicBlock::Create(context_, "exception_unwind", func_);
+
+  // Change IRBuilder insert point
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+  irb_.SetInsertPoint(basic_block_unwind_);
+
+  // Pop the shadow frame
+  Expand_PopShadowFrame();
+
+  // Emit the code to return default value (zero) for the given return type.
+  char ret_shorty = dex_compilation_unit_->GetShorty()[0];
+  ret_shorty = art::RemapShorty(ret_shorty);
+  if (ret_shorty == 'V') {
+    irb_.CreateRetVoid();
+  } else {
+    irb_.CreateRet(irb_.getJZero(ret_shorty));
+  }
+
+  // Restore the orignal insert point for IRBuilder
+  irb_.restoreIP(irb_ip_original);
+
+  return basic_block_unwind_;
+}
+
+void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
+  if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
+    landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
+                                                            irb_.GetInsertBlock()));
+    irb_.CreateBr(lpad);
+  } else {
+    irb_.CreateBr(GetUnwindBasicBlock());
+  }
+}
+
+void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
+  llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
+
+  llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
+    landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
+                                                            irb_.GetInsertBlock()));
+    irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
+  } else {
+    irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
+  }
+
+  irb_.SetInsertPoint(block_cont);
+}
+
+llvm::Value*
+GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
+                                 llvm::CallInst& call_inst) {
+  switch (intr_id) {
+    //==- Thread -----------------------------------------------------------==//
+    case IntrinsicHelper::GetCurrentThread: {
+      return irb_.Runtime().EmitGetCurrentThread();
+    }
+    case IntrinsicHelper::CheckSuspend: {
+      Expand_TestSuspend(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::TestSuspend: {
+      Expand_TestSuspend(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::MarkGCCard: {
+      Expand_MarkGCCard(call_inst);
+      return NULL;
+    }
+
+    //==- Exception --------------------------------------------------------==//
+    case IntrinsicHelper::ThrowException: {
+      return ExpandToRuntime(runtime_support::ThrowException, call_inst);
+    }
+    case IntrinsicHelper::HLThrowException: {
+      uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+
+      EmitUpdateDexPC(dex_pc);
+
+      irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
+                      call_inst.getArgOperand(0));
+
+      EmitGuard_ExceptionLandingPad(dex_pc);
+      return NULL;
+    }
+    case IntrinsicHelper::GetException: {
+      return irb_.Runtime().EmitGetAndClearException();
+    }
+    case IntrinsicHelper::IsExceptionPending: {
+      return irb_.Runtime().EmitIsExceptionPending();
+    }
+    case IntrinsicHelper::FindCatchBlock: {
+      return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
+    }
+    case IntrinsicHelper::ThrowDivZeroException: {
+      return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
+    }
+    case IntrinsicHelper::ThrowNullPointerException: {
+      return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
+    }
+    case IntrinsicHelper::ThrowIndexOutOfBounds: {
+      return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
+    }
+
+    //==- Const String -----------------------------------------------------==//
+    case IntrinsicHelper::ConstString: {
+      return Expand_ConstString(call_inst);
+    }
+    case IntrinsicHelper::LoadStringFromDexCache: {
+      return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::ResolveString: {
+      return ExpandToRuntime(runtime_support::ResolveString, call_inst);
+    }
+
+    //==- Const Class ------------------------------------------------------==//
+    case IntrinsicHelper::ConstClass: {
+      return Expand_ConstClass(call_inst);
+    }
+    case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
+      return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
+    }
+    case IntrinsicHelper::LoadTypeFromDexCache: {
+      return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::InitializeType: {
+      return ExpandToRuntime(runtime_support::InitializeType, call_inst);
+    }
+
+    //==- Lock -------------------------------------------------------------==//
+    case IntrinsicHelper::LockObject: {
+      Expand_LockObject(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    case IntrinsicHelper::UnlockObject: {
+      Expand_UnlockObject(call_inst.getArgOperand(0));
+      return NULL;
+    }
+
+    //==- Cast -------------------------------------------------------------==//
+    case IntrinsicHelper::CheckCast: {
+      return ExpandToRuntime(runtime_support::CheckCast, call_inst);
+    }
+    case IntrinsicHelper::HLCheckCast: {
+      Expand_HLCheckCast(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::IsAssignable: {
+      return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
+    }
+
+    //==- Alloc ------------------------------------------------------------==//
+    case IntrinsicHelper::AllocObject: {
+      return ExpandToRuntime(runtime_support::AllocObject, call_inst);
+    }
+    case IntrinsicHelper::AllocObjectWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
+    }
+
+    //==- Instance ---------------------------------------------------------==//
+    case IntrinsicHelper::NewInstance: {
+      return Expand_NewInstance(call_inst);
+    }
+    case IntrinsicHelper::InstanceOf: {
+      return Expand_InstanceOf(call_inst);
+    }
+
+    //==- Array ------------------------------------------------------------==//
+    case IntrinsicHelper::NewArray: {
+      return Expand_NewArray(call_inst);
+    }
+    case IntrinsicHelper::OptArrayLength: {
+      return Expand_OptArrayLength(call_inst);
+    }
+    case IntrinsicHelper::ArrayLength: {
+      return EmitLoadArrayLength(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::AllocArray: {
+      return ExpandToRuntime(runtime_support::AllocArray, call_inst);
+    }
+    case IntrinsicHelper::AllocArrayWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
+                             call_inst);
+    }
+    case IntrinsicHelper::CheckAndAllocArray: {
+      return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
+    }
+    case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
+                             call_inst);
+    }
+    case IntrinsicHelper::ArrayGet: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kInt);
+    }
+    case IntrinsicHelper::ArrayGetWide: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kLong);
+    }
+    case IntrinsicHelper::ArrayGetObject: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kObject);
+    }
+    case IntrinsicHelper::ArrayGetBoolean: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kBoolean);
+    }
+    case IntrinsicHelper::ArrayGetByte: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kByte);
+    }
+    case IntrinsicHelper::ArrayGetChar: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kChar);
+    }
+    case IntrinsicHelper::ArrayGetShort: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kShort);
+    }
+    case IntrinsicHelper::ArrayPut: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutWide: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutObject: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutBoolean: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutByte: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutChar: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutShort: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::CheckPutArrayElement: {
+      return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
+    }
+    case IntrinsicHelper::FilledNewArray: {
+      Expand_FilledNewArray(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::FillArrayData: {
+      return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
+    }
+    case IntrinsicHelper::HLFillArrayData: {
+      Expand_HLFillArrayData(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::HLFilledNewArray: {
+      return Expand_HLFilledNewArray(call_inst);
+    }
+
+    //==- Instance Field ---------------------------------------------------==//
+    case IntrinsicHelper::InstanceFieldGet:
+    case IntrinsicHelper::InstanceFieldGetBoolean:
+    case IntrinsicHelper::InstanceFieldGetByte:
+    case IntrinsicHelper::InstanceFieldGetChar:
+    case IntrinsicHelper::InstanceFieldGetShort: {
+      return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetWide: {
+      return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetObject: {
+      return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kInt);
+    }
+    case IntrinsicHelper::InstanceFieldGetWideFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kLong);
+    }
+    case IntrinsicHelper::InstanceFieldGetObjectFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kObject);
+    }
+    case IntrinsicHelper::InstanceFieldGetBooleanFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kBoolean);
+    }
+    case IntrinsicHelper::InstanceFieldGetByteFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kByte);
+    }
+    case IntrinsicHelper::InstanceFieldGetCharFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kChar);
+    }
+    case IntrinsicHelper::InstanceFieldGetShortFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kShort);
+    }
+    case IntrinsicHelper::InstanceFieldPut:
+    case IntrinsicHelper::InstanceFieldPutBoolean:
+    case IntrinsicHelper::InstanceFieldPutByte:
+    case IntrinsicHelper::InstanceFieldPutChar:
+    case IntrinsicHelper::InstanceFieldPutShort: {
+      return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutWide: {
+      return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutObject: {
+      return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutWideFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutObjectFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutBooleanFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutByteFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutCharFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutShortFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kShort);
+      return NULL;
+    }
+
+    //==- Static Field -----------------------------------------------------==//
+    case IntrinsicHelper::StaticFieldGet:
+    case IntrinsicHelper::StaticFieldGetBoolean:
+    case IntrinsicHelper::StaticFieldGetByte:
+    case IntrinsicHelper::StaticFieldGetChar:
+    case IntrinsicHelper::StaticFieldGetShort: {
+      return ExpandToRuntime(runtime_support::Get32Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetWide: {
+      return ExpandToRuntime(runtime_support::Get64Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetObject: {
+      return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kInt);
+    }
+    case IntrinsicHelper::StaticFieldGetWideFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kLong);
+    }
+    case IntrinsicHelper::StaticFieldGetObjectFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kObject);
+    }
+    case IntrinsicHelper::StaticFieldGetBooleanFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kBoolean);
+    }
+    case IntrinsicHelper::StaticFieldGetByteFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kByte);
+    }
+    case IntrinsicHelper::StaticFieldGetCharFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kChar);
+    }
+    case IntrinsicHelper::StaticFieldGetShortFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kShort);
+    }
+    case IntrinsicHelper::StaticFieldPut:
+    case IntrinsicHelper::StaticFieldPutBoolean:
+    case IntrinsicHelper::StaticFieldPutByte:
+    case IntrinsicHelper::StaticFieldPutChar:
+    case IntrinsicHelper::StaticFieldPutShort: {
+      return ExpandToRuntime(runtime_support::Set32Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutWide: {
+      return ExpandToRuntime(runtime_support::Set64Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutObject: {
+      return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutWideFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutObjectFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutBooleanFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutByteFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutCharFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutShortFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::LoadDeclaringClassSSB: {
+      return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::LoadClassSSBFromDexCache: {
+      return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::InitializeAndLoadClassSSB: {
+      return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
+    }
+
+    //==- High-level Array -------------------------------------------------==//
+    case IntrinsicHelper::HLArrayGet: {
+      return Expand_HLArrayGet(call_inst, kInt);
+    }
+    case IntrinsicHelper::HLArrayGetBoolean: {
+      return Expand_HLArrayGet(call_inst, kBoolean);
+    }
+    case IntrinsicHelper::HLArrayGetByte: {
+      return Expand_HLArrayGet(call_inst, kByte);
+    }
+    case IntrinsicHelper::HLArrayGetChar: {
+      return Expand_HLArrayGet(call_inst, kChar);
+    }
+    case IntrinsicHelper::HLArrayGetShort: {
+      return Expand_HLArrayGet(call_inst, kShort);
+    }
+    case IntrinsicHelper::HLArrayGetFloat: {
+      return Expand_HLArrayGet(call_inst, kFloat);
+    }
+    case IntrinsicHelper::HLArrayGetWide: {
+      return Expand_HLArrayGet(call_inst, kLong);
+    }
+    case IntrinsicHelper::HLArrayGetDouble: {
+      return Expand_HLArrayGet(call_inst, kDouble);
+    }
+    case IntrinsicHelper::HLArrayGetObject: {
+      return Expand_HLArrayGet(call_inst, kObject);
+    }
+    case IntrinsicHelper::HLArrayPut: {
+      Expand_HLArrayPut(call_inst, kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutBoolean: {
+      Expand_HLArrayPut(call_inst, kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutByte: {
+      Expand_HLArrayPut(call_inst, kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutChar: {
+      Expand_HLArrayPut(call_inst, kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutShort: {
+      Expand_HLArrayPut(call_inst, kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutFloat: {
+      Expand_HLArrayPut(call_inst, kFloat);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutWide: {
+      Expand_HLArrayPut(call_inst, kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutDouble: {
+      Expand_HLArrayPut(call_inst, kDouble);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutObject: {
+      Expand_HLArrayPut(call_inst, kObject);
+      return NULL;
+    }
+
+    //==- High-level Instance ----------------------------------------------==//
+    case IntrinsicHelper::HLIGet: {
+      return Expand_HLIGet(call_inst, kInt);
+    }
+    case IntrinsicHelper::HLIGetBoolean: {
+      return Expand_HLIGet(call_inst, kBoolean);
+    }
+    case IntrinsicHelper::HLIGetByte: {
+      return Expand_HLIGet(call_inst, kByte);
+    }
+    case IntrinsicHelper::HLIGetChar: {
+      return Expand_HLIGet(call_inst, kChar);
+    }
+    case IntrinsicHelper::HLIGetShort: {
+      return Expand_HLIGet(call_inst, kShort);
+    }
+    case IntrinsicHelper::HLIGetFloat: {
+      return Expand_HLIGet(call_inst, kFloat);
+    }
+    case IntrinsicHelper::HLIGetWide: {
+      return Expand_HLIGet(call_inst, kLong);
+    }
+    case IntrinsicHelper::HLIGetDouble: {
+      return Expand_HLIGet(call_inst, kDouble);
+    }
+    case IntrinsicHelper::HLIGetObject: {
+      return Expand_HLIGet(call_inst, kObject);
+    }
+    case IntrinsicHelper::HLIPut: {
+      Expand_HLIPut(call_inst, kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutBoolean: {
+      Expand_HLIPut(call_inst, kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutByte: {
+      Expand_HLIPut(call_inst, kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutChar: {
+      Expand_HLIPut(call_inst, kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutShort: {
+      Expand_HLIPut(call_inst, kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutFloat: {
+      Expand_HLIPut(call_inst, kFloat);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutWide: {
+      Expand_HLIPut(call_inst, kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutDouble: {
+      Expand_HLIPut(call_inst, kDouble);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutObject: {
+      Expand_HLIPut(call_inst, kObject);
+      return NULL;
+    }
+
+    //==- High-level Invoke ------------------------------------------------==//
+    case IntrinsicHelper::HLInvokeVoid:
+    case IntrinsicHelper::HLInvokeObj:
+    case IntrinsicHelper::HLInvokeInt:
+    case IntrinsicHelper::HLInvokeFloat:
+    case IntrinsicHelper::HLInvokeLong:
+    case IntrinsicHelper::HLInvokeDouble: {
+      return Expand_HLInvoke(call_inst);
+    }
+
+    //==- Invoke -----------------------------------------------------------==//
+    case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
+      return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
+      return Expand_GetVirtualCalleeMethodObjAddrFast(
+                call_inst.getArgOperand(0), call_inst.getArgOperand(1));
+    }
+    case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
+      return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
+    }
+    case IntrinsicHelper::InvokeRetVoid:
+    case IntrinsicHelper::InvokeRetBoolean:
+    case IntrinsicHelper::InvokeRetByte:
+    case IntrinsicHelper::InvokeRetChar:
+    case IntrinsicHelper::InvokeRetShort:
+    case IntrinsicHelper::InvokeRetInt:
+    case IntrinsicHelper::InvokeRetLong:
+    case IntrinsicHelper::InvokeRetFloat:
+    case IntrinsicHelper::InvokeRetDouble:
+    case IntrinsicHelper::InvokeRetObject: {
+      return Expand_Invoke(call_inst);
+    }
+
+    //==- Math -------------------------------------------------------------==//
+    case IntrinsicHelper::DivInt: {
+      return Expand_DivRem(call_inst, /* is_div */true, kInt);
+    }
+    case IntrinsicHelper::RemInt: {
+      return Expand_DivRem(call_inst, /* is_div */false, kInt);
+    }
+    case IntrinsicHelper::DivLong: {
+      return Expand_DivRem(call_inst, /* is_div */true, kLong);
+    }
+    case IntrinsicHelper::RemLong: {
+      return Expand_DivRem(call_inst, /* is_div */false, kLong);
+    }
+    case IntrinsicHelper::D2L: {
+      return ExpandToRuntime(runtime_support::art_d2l, call_inst);
+    }
+    case IntrinsicHelper::D2I: {
+      return ExpandToRuntime(runtime_support::art_d2i, call_inst);
+    }
+    case IntrinsicHelper::F2L: {
+      return ExpandToRuntime(runtime_support::art_f2l, call_inst);
+    }
+    case IntrinsicHelper::F2I: {
+      return ExpandToRuntime(runtime_support::art_f2i, call_inst);
+    }
+
+    //==- High-level Static ------------------------------------------------==//
+    case IntrinsicHelper::HLSget: {
+      return Expand_HLSget(call_inst, kInt);
+    }
+    case IntrinsicHelper::HLSgetBoolean: {
+      return Expand_HLSget(call_inst, kBoolean);
+    }
+    case IntrinsicHelper::HLSgetByte: {
+      return Expand_HLSget(call_inst, kByte);
+    }
+    case IntrinsicHelper::HLSgetChar: {
+      return Expand_HLSget(call_inst, kChar);
+    }
+    case IntrinsicHelper::HLSgetShort: {
+      return Expand_HLSget(call_inst, kShort);
+    }
+    case IntrinsicHelper::HLSgetFloat: {
+      return Expand_HLSget(call_inst, kFloat);
+    }
+    case IntrinsicHelper::HLSgetWide: {
+      return Expand_HLSget(call_inst, kLong);
+    }
+    case IntrinsicHelper::HLSgetDouble: {
+      return Expand_HLSget(call_inst, kDouble);
+    }
+    case IntrinsicHelper::HLSgetObject: {
+      return Expand_HLSget(call_inst, kObject);
+    }
+    case IntrinsicHelper::HLSput: {
+      Expand_HLSput(call_inst, kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputBoolean: {
+      Expand_HLSput(call_inst, kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputByte: {
+      Expand_HLSput(call_inst, kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputChar: {
+      Expand_HLSput(call_inst, kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputShort: {
+      Expand_HLSput(call_inst, kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputFloat: {
+      Expand_HLSput(call_inst, kFloat);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputWide: {
+      Expand_HLSput(call_inst, kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputDouble: {
+      Expand_HLSput(call_inst, kDouble);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputObject: {
+      Expand_HLSput(call_inst, kObject);
+      return NULL;
+    }
+
+    //==- High-level Monitor -----------------------------------------------==//
+    case IntrinsicHelper::MonitorEnter: {
+      Expand_MonitorEnter(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::MonitorExit: {
+      Expand_MonitorExit(call_inst);
+      return NULL;
+    }
+
+    //==- Shadow Frame -----------------------------------------------------==//
+    case IntrinsicHelper::AllocaShadowFrame: {
+      Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    case IntrinsicHelper::SetVReg: {
+      Expand_SetVReg(call_inst.getArgOperand(0),
+                     call_inst.getArgOperand(1));
+      return NULL;
+    }
+    case IntrinsicHelper::PopShadowFrame: {
+      Expand_PopShadowFrame();
+      return NULL;
+    }
+    case IntrinsicHelper::UpdateDexPC: {
+      Expand_UpdateDexPC(call_inst.getArgOperand(0));
+      return NULL;
+    }
+
+    //==- Comparison -------------------------------------------------------==//
+    case IntrinsicHelper::CmplFloat:
+    case IntrinsicHelper::CmplDouble: {
+      return Expand_FPCompare(call_inst.getArgOperand(0),
+                              call_inst.getArgOperand(1),
+                              false);
+    }
+    case IntrinsicHelper::CmpgFloat:
+    case IntrinsicHelper::CmpgDouble: {
+      return Expand_FPCompare(call_inst.getArgOperand(0),
+                              call_inst.getArgOperand(1),
+                              true);
+    }
+    case IntrinsicHelper::CmpLong: {
+      return Expand_LongCompare(call_inst.getArgOperand(0),
+                                call_inst.getArgOperand(1));
+    }
+
+    //==- Const ------------------------------------------------------------==//
+    case IntrinsicHelper::ConstInt:
+    case IntrinsicHelper::ConstLong: {
+      return call_inst.getArgOperand(0);
+    }
+    case IntrinsicHelper::ConstFloat: {
+      return irb_.CreateBitCast(call_inst.getArgOperand(0),
+                                irb_.getJFloatTy());
+    }
+    case IntrinsicHelper::ConstDouble: {
+      return irb_.CreateBitCast(call_inst.getArgOperand(0),
+                                irb_.getJDoubleTy());
+    }
+    case IntrinsicHelper::ConstObj: {
+      CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
+      return irb_.getJNull();
+    }
+
+    //==- Method Info ------------------------------------------------------==//
+    case IntrinsicHelper::MethodInfo: {
+      // Nothing to be done, because MethodInfo carries optional hints that are
+      // not needed by the portable path.
+      return NULL;
+    }
+
+    //==- Copy -------------------------------------------------------------==//
+    case IntrinsicHelper::CopyInt:
+    case IntrinsicHelper::CopyFloat:
+    case IntrinsicHelper::CopyLong:
+    case IntrinsicHelper::CopyDouble:
+    case IntrinsicHelper::CopyObj: {
+      return call_inst.getArgOperand(0);
+    }
+
+    //==- Shift ------------------------------------------------------------==//
+    case IntrinsicHelper::SHLLong: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHL, kLong);
+    }
+    case IntrinsicHelper::SHRLong: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHR, kLong);
+    }
+    case IntrinsicHelper::USHRLong: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerUSHR, kLong);
+    }
+    case IntrinsicHelper::SHLInt: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHL, kInt);
+    }
+    case IntrinsicHelper::SHRInt: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHR, kInt);
+    }
+    case IntrinsicHelper::USHRInt: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerUSHR, kInt);
+    }
+
+    //==- Conversion -------------------------------------------------------==//
+    case IntrinsicHelper::IntToChar: {
+      return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::IntToShort: {
+      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::IntToByte: {
+      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
+                             irb_.getJIntTy());
+    }
+
+    //==- Exception --------------------------------------------------------==//
+    case IntrinsicHelper::CatchTargets: {
+      UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
+      llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
+      CHECK(si != NULL);
+      irb_.CreateBr(si->getDefaultDest());
+      si->eraseFromParent();
+      return call_inst.getArgOperand(0);
+    }
+
+    //==- Constructor barrier-----------------------------------------------==//
+    case IntrinsicHelper::ConstructorBarrier: {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+      return NULL;
+    }
+
+    //==- Unknown Cases ----------------------------------------------------==//
+    case IntrinsicHelper::MaxIntrinsicId:
+    case IntrinsicHelper::UnknownId:
+    //default:
+      // NOTE: "default" is intentionally commented so that C/C++ compiler will
+      // give some warning on unmatched cases.
+      // NOTE: We should not implement these cases.
+      break;
+  }
+  UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
+  return NULL;
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace llvm {
+
+::llvm::FunctionPass*
+CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
+                      CompilerDriver* driver, const DexCompilationUnit* dex_compilation_unit) {
+  return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
+}
+
+} // namespace llvm
+} // namespace art
