Quick compiler: conversions, bug fixes

Added support for the remaining conversions, misc. bugs fixed.  Still
left is switch support, rework of type handling and lots of bug
fixes.

Change-Id: Ib370a4176555d628f222e35776e0b3f0be8de0c4
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 140f681..d617be5 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -759,6 +759,11 @@
 #if defined(ART_USE_QUICK_COMPILER)
   // TODO: remove - temp for Quick compiler bring-up
   if ((PrettyMethod(method_idx, dex_file).find("fibonacci") != std::string::npos)
+      || (PrettyMethod(method_idx, dex_file).find("Array") != std::string::npos)
+      || (PrettyMethod(method_idx, dex_file).find("Monitor") != std::string::npos)
+      || (PrettyMethod(method_idx, dex_file).find("InternedString") != std::string::npos)
+      || (PrettyMethod(method_idx, dex_file).find("StaticField") != std::string::npos)
+      || (PrettyMethod(method_idx, dex_file).find("UnresClass") != std::string::npos)
       || (PrettyMethod(method_idx, dex_file).find("HelloWorld") != std::string::npos)
       || (PrettyMethod(method_idx, dex_file).find("count10_006") != std::string::npos)
       || (PrettyMethod(method_idx, dex_file).find("exceptions_007") != std::string::npos)
@@ -775,6 +780,7 @@
       || (PrettyMethod(method_idx, dex_file).find("shiftTest1") != std::string::npos)
       || (PrettyMethod(method_idx, dex_file).find("shiftTest2") != std::string::npos)
       || (PrettyMethod(method_idx, dex_file).find("unsignedShiftTest") != std::string::npos)
+      || (PrettyMethod(method_idx, dex_file).find("convTest") != std::string::npos)
      ) {
     cUnit->genBitcode = true;
   }
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index 92cc6cc..cd4e1d3 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -254,14 +254,16 @@
   cUnit->irb->CreateCall(func, args);
 }
 
-void convertArrayLength(CompilationUnit* cUnit, int optFlags, RegLocation rlSrc)
+void convertArrayLength(CompilationUnit* cUnit, int optFlags,
+                        RegLocation rlDest, RegLocation rlSrc)
 {
   llvm::SmallVector<llvm::Value*, 2> args;
   args.push_back(cUnit->irb->getInt32(optFlags));
   args.push_back(getLLVMValue(cUnit, rlSrc.origSReg));
   llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(
       greenland::IntrinsicHelper::ArrayLength);
-  cUnit->irb->CreateCall(func, args);
+  llvm::Value* res = cUnit->irb->CreateCall(func, args);
+  defineValue(cUnit, res, rlDest.origSReg);
 }
 
 void convertThrowVerificationError(CompilationUnit* cUnit, int info1, int info2)
@@ -287,6 +289,7 @@
                             llvm::Value* src1, llvm::Value* src2)
 {
   llvm::Value* res = NULL;
+  DCHECK_EQ(src1->getType(), src2->getType());
   switch(cc) {
     case kCondEq: res = cUnit->irb->CreateICmpEQ(src1, src2); break;
     case kCondNe: res = cUnit->irb->CreateICmpNE(src1, src2); break;
@@ -465,7 +468,7 @@
  * The requirements are similar.
  */
 void convertInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
-                   InvokeType invokeType, bool isRange, bool isNewArray)
+                   InvokeType invokeType, bool isRange, bool isFilledNewArray)
 {
   CallInfo* info = oatNewCallInfo(cUnit, bb, mir, invokeType, isRange);
   llvm::SmallVector<llvm::Value*, 10> args;
@@ -493,8 +496,8 @@
    * is not used, we'll treat this as a void invoke.
    */
   greenland::IntrinsicHelper::IntrinsicId id;
-  if (isNewArray) {
-    id = greenland::IntrinsicHelper::NewArray;
+  if (isFilledNewArray) {
+    id = greenland::IntrinsicHelper::FilledNewArray;
   } else if (info->result.location == kLocInvalid) {
     id = greenland::IntrinsicHelper::HLInvokeVoid;
   } else {
@@ -638,13 +641,92 @@
   defineValue(cUnit, res, rlDest.origSReg);
 }
 
+void convertLongToInt(CompilationUnit* cUnit, RegLocation rlDest,
+                      RegLocation rlSrc)
+{
+  llvm::Value* src = getLLVMValue(cUnit, rlSrc.origSReg);
+  llvm::Value* res = cUnit->irb->CreateTrunc(src, cUnit->irb->getInt32Ty());
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertFloatToDouble(CompilationUnit* cUnit, RegLocation rlDest,
+                          RegLocation rlSrc)
+{
+  llvm::Value* src = getLLVMValue(cUnit, rlSrc.origSReg);
+  llvm::Value* res = cUnit->irb->CreateFPExt(src, cUnit->irb->getDoubleTy());
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertDoubleToFloat(CompilationUnit* cUnit, RegLocation rlDest,
+                          RegLocation rlSrc)
+{
+  llvm::Value* src = getLLVMValue(cUnit, rlSrc.origSReg);
+  llvm::Value* res = cUnit->irb->CreateFPTrunc(src, cUnit->irb->getFloatTy());
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertWideComparison(CompilationUnit* cUnit,
+                           greenland::IntrinsicHelper::IntrinsicId id,
+                           RegLocation rlDest, RegLocation rlSrc1,
+                           RegLocation rlSrc2)
+{
+  DCHECK_EQ(rlSrc1.fp, rlSrc2.fp);
+  DCHECK_EQ(rlSrc1.wide, rlSrc2.wide);
+  llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id);
+  llvm::SmallVector<llvm::Value*, 2> args;
+  args.push_back(getLLVMValue(cUnit, rlSrc1.origSReg));
+  args.push_back(getLLVMValue(cUnit, rlSrc2.origSReg));
+  llvm::Value* res = cUnit->irb->CreateCall(intr, args);
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
 void convertIntNarrowing(CompilationUnit* cUnit, RegLocation rlDest,
                          RegLocation rlSrc,
                          greenland::IntrinsicHelper::IntrinsicId id)
 {
   llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id);
-  llvm::Value* res = cUnit->irb->CreateCall(intr,
-                                            getLLVMValue(cUnit, rlSrc.origSReg));
+  llvm::Value* res =
+      cUnit->irb->CreateCall(intr, getLLVMValue(cUnit, rlSrc.origSReg));
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertNeg(CompilationUnit* cUnit, RegLocation rlDest,
+                RegLocation rlSrc)
+{
+  llvm::Value* res = cUnit->irb->CreateNeg(getLLVMValue(cUnit, rlSrc.origSReg));
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertIntToFP(CompilationUnit* cUnit, llvm::Type* ty, RegLocation rlDest,
+                    RegLocation rlSrc)
+{
+  llvm::Value* res =
+      cUnit->irb->CreateSIToFP(getLLVMValue(cUnit, rlSrc.origSReg), ty);
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertFPToInt(CompilationUnit* cUnit, llvm::Type* ty, RegLocation rlDest,
+                    RegLocation rlSrc)
+{
+  llvm::Value* res =
+      cUnit->irb->CreateFPToSI(getLLVMValue(cUnit, rlSrc.origSReg), ty);
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+
+void convertNegFP(CompilationUnit* cUnit, RegLocation rlDest,
+                RegLocation rlSrc)
+{
+  llvm::Value* res =
+      cUnit->irb->CreateFNeg(getLLVMValue(cUnit, rlSrc.origSReg));
+  defineValue(cUnit, res, rlDest.origSReg);
+}
+
+void convertNot(CompilationUnit* cUnit, RegLocation rlDest,
+                RegLocation rlSrc)
+{
+  llvm::Value* src = getLLVMValue(cUnit, rlSrc.origSReg);
+  llvm::Value* res = cUnit->irb->CreateXor(src, static_cast<uint64_t>(-1));
   defineValue(cUnit, res, rlDest.origSReg);
 }
 
@@ -717,6 +799,7 @@
     case Instruction::MOVE_OBJECT:
     case Instruction::MOVE_16:
     case Instruction::MOVE_OBJECT_16:
+    case Instruction::MOVE_OBJECT_FROM16:
     case Instruction::MOVE_FROM16:
     case Instruction::MOVE_WIDE:
     case Instruction::MOVE_WIDE_16:
@@ -745,7 +828,9 @@
 
     case Instruction::CONST_WIDE_16:
     case Instruction::CONST_WIDE_32: {
-        llvm::Constant* immValue = cUnit->irb->GetJLong(vB);
+        // Sign extend to 64 bits
+        int64_t imm = static_cast<int32_t>(vB);
+        llvm::Constant* immValue = cUnit->irb->GetJLong(imm);
         llvm::Value* res = emitConst(cUnit, immValue, rlDest);
         defineValue(cUnit, res, rlDest.origSReg);
       }
@@ -774,36 +859,36 @@
       break;
 
     case Instruction::SPUT_OBJECT:
-      convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputObject,
+      convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputObject,
                   rlSrc[0]);
       break;
     case Instruction::SPUT:
       if (rlSrc[0].fp) {
-        convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputFloat,
+        convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputFloat,
                     rlSrc[0]);
       } else {
-        convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSput, rlSrc[0]);
+        convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSput, rlSrc[0]);
       }
       break;
     case Instruction::SPUT_BOOLEAN:
-      convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputBoolean,
+      convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputBoolean,
                   rlSrc[0]);
       break;
     case Instruction::SPUT_BYTE:
-      convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputByte, rlSrc[0]);
+      convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputByte, rlSrc[0]);
       break;
     case Instruction::SPUT_CHAR:
-      convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputChar, rlSrc[0]);
+      convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputChar, rlSrc[0]);
       break;
     case Instruction::SPUT_SHORT:
-      convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputShort, rlSrc[0]);
+      convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputShort, rlSrc[0]);
       break;
     case Instruction::SPUT_WIDE:
       if (rlSrc[0].fp) {
-        convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputDouble,
+        convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputDouble,
                     rlSrc[0]);
       } else {
-        convertSget(cUnit, vB, greenland::IntrinsicHelper::HLSputWide,
+        convertSput(cUnit, vB, greenland::IntrinsicHelper::HLSputWide,
                     rlSrc[0]);
       }
       break;
@@ -1161,7 +1246,7 @@
       break;
 
     case Instruction::ARRAY_LENGTH:
-      convertArrayLength(cUnit, optFlags, rlSrc[0]);
+      convertArrayLength(cUnit, optFlags, rlDest, rlSrc[0]);
       break;
 
     case Instruction::NEW_ARRAY:
@@ -1337,6 +1422,10 @@
       convertFillArrayData(cUnit, vB, rlSrc[0]);
       break;
 
+    case Instruction::LONG_TO_INT:
+      convertLongToInt(cUnit, rlDest, rlSrc[0]);
+      break;
+
     case Instruction::INT_TO_LONG:
       convertIntToLong(cUnit, rlDest, rlSrc[0]);
       break;
@@ -1354,64 +1443,78 @@
                           greenland::IntrinsicHelper::IntToShort);
       break;
 
-#if 0
-
-    case Instruction::PACKED_SWITCH:
-      genPackedSwitch(cUnit, mir, rlSrc[0]);
+    case Instruction::INT_TO_FLOAT:
+    case Instruction::LONG_TO_FLOAT:
+      convertIntToFP(cUnit, cUnit->irb->getFloatTy(), rlDest, rlSrc[0]);
       break;
 
-    case Instruction::SPARSE_SWITCH:
-      genSparseSwitch(cUnit, mir, rlSrc[0], labelList);
+    case Instruction::INT_TO_DOUBLE:
+    case Instruction::LONG_TO_DOUBLE:
+      convertIntToFP(cUnit, cUnit->irb->getDoubleTy(), rlDest, rlSrc[0]);
       break;
 
-    case Instruction::CMPL_FLOAT:
-    case Instruction::CMPG_FLOAT:
-    case Instruction::CMPL_DOUBLE:
-    case Instruction::CMPG_DOUBLE:
-      res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
+    case Instruction::FLOAT_TO_DOUBLE:
+      convertFloatToDouble(cUnit, rlDest, rlSrc[0]);
       break;
 
-    case Instruction::CMP_LONG:
-      genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
-      break;
-
-    case Instruction::NEG_INT:
-    case Instruction::NOT_INT:
-      res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
+    case Instruction::DOUBLE_TO_FLOAT:
+      convertDoubleToFloat(cUnit, rlDest, rlSrc[0]);
       break;
 
     case Instruction::NEG_LONG:
-    case Instruction::NOT_LONG:
-      res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
+    case Instruction::NEG_INT:
+      convertNeg(cUnit, rlDest, rlSrc[0]);
       break;
 
     case Instruction::NEG_FLOAT:
-      res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
-      break;
-
     case Instruction::NEG_DOUBLE:
-      res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
+      convertNegFP(cUnit, rlDest, rlSrc[0]);
       break;
 
-    case Instruction::LONG_TO_INT:
-      rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
-      rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
-      storeValue(cUnit, rlDest, rlSrc[0]);
+    case Instruction::NOT_LONG:
+    case Instruction::NOT_INT:
+      convertNot(cUnit, rlDest, rlSrc[0]);
       break;
 
-    case Instruction::INT_TO_FLOAT:
-    case Instruction::INT_TO_DOUBLE:
-    case Instruction::LONG_TO_FLOAT:
-    case Instruction::LONG_TO_DOUBLE:
     case Instruction::FLOAT_TO_INT:
-    case Instruction::FLOAT_TO_LONG:
-    case Instruction::FLOAT_TO_DOUBLE:
     case Instruction::DOUBLE_TO_INT:
-    case Instruction::DOUBLE_TO_LONG:
-    case Instruction::DOUBLE_TO_FLOAT:
-      genConversion(cUnit, mir);
+      convertFPToInt(cUnit, cUnit->irb->getInt32Ty(), rlDest, rlSrc[0]);
       break;
 
+    case Instruction::FLOAT_TO_LONG:
+    case Instruction::DOUBLE_TO_LONG:
+      convertFPToInt(cUnit, cUnit->irb->getInt64Ty(), rlDest, rlSrc[0]);
+      break;
+
+    case Instruction::CMPL_FLOAT:
+      convertWideComparison(cUnit, greenland::IntrinsicHelper::CmplFloat,
+                            rlDest, rlSrc[0], rlSrc[1]);
+      break;
+    case Instruction::CMPG_FLOAT:
+      convertWideComparison(cUnit, greenland::IntrinsicHelper::CmpgFloat,
+                            rlDest, rlSrc[0], rlSrc[1]);
+      break;
+    case Instruction::CMPL_DOUBLE:
+      convertWideComparison(cUnit, greenland::IntrinsicHelper::CmplDouble,
+                            rlDest, rlSrc[0], rlSrc[1]);
+      break;
+    case Instruction::CMPG_DOUBLE:
+      convertWideComparison(cUnit, greenland::IntrinsicHelper::CmpgDouble,
+                            rlDest, rlSrc[0], rlSrc[1]);
+      break;
+    case Instruction::CMP_LONG:
+      convertWideComparison(cUnit, greenland::IntrinsicHelper::CmpLong,
+                            rlDest, rlSrc[0], rlSrc[1]);
+      break;
+
+#if 0
+    case Instruction::PACKED_SWITCH:
+      genPackedSwitch(cUnit, vB, rlSrc[0]);
+      break;
+
+    case Instruction::SPARSE_SWITCH:
+      genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
+      break;
 #endif
 
     default:
@@ -1480,7 +1583,7 @@
 void setDexOffset(CompilationUnit* cUnit, int32_t offset)
 {
   cUnit->currentDalvikOffset = offset;
-  llvm::SmallVector<llvm::Value*, 1>arrayRef;
+  llvm::SmallVector<llvm::Value*, 1> arrayRef;
   arrayRef.push_back(cUnit->irb->getInt32(offset));
   llvm::MDNode* node = llvm::MDNode::get(*cUnit->context, arrayRef);
   cUnit->irb->SetDexOffset(node);
@@ -1902,6 +2005,72 @@
   genIntNarrowing(cUnit, opcode, rlDest, rlSrc);
 }
 
+void cvtIntToFP(CompilationUnit* cUnit, llvm::Instruction* inst)
+{
+  RegLocation rlDest = getLoc(cUnit, inst);
+  RegLocation rlSrc = getLoc(cUnit, inst->getOperand(0));
+  Instruction::Code opcode;
+  if (rlDest.wide) {
+    if (rlSrc.wide) {
+      opcode = Instruction::LONG_TO_DOUBLE;
+    } else {
+      opcode = Instruction::INT_TO_DOUBLE;
+    }
+  } else {
+    if (rlSrc.wide) {
+      opcode = Instruction::LONG_TO_FLOAT;
+    } else {
+      opcode = Instruction::INT_TO_FLOAT;
+    }
+  }
+  genConversion(cUnit, opcode, rlDest, rlSrc);
+}
+
+void cvtFPToInt(CompilationUnit* cUnit, llvm::Instruction* inst)
+{
+  RegLocation rlDest = getLoc(cUnit, inst);
+  RegLocation rlSrc = getLoc(cUnit, inst->getOperand(0));
+  Instruction::Code opcode;
+  if (rlDest.wide) {
+    if (rlSrc.wide) {
+      opcode = Instruction::DOUBLE_TO_LONG;
+    } else {
+      opcode = Instruction::FLOAT_TO_LONG;
+    }
+  } else {
+    if (rlSrc.wide) {
+      opcode = Instruction::DOUBLE_TO_INT;
+    } else {
+      opcode = Instruction::FLOAT_TO_INT;
+    }
+  }
+  genConversion(cUnit, opcode, rlDest, rlSrc);
+}
+
+void cvtFloatToDouble(CompilationUnit* cUnit, llvm::Instruction* inst)
+{
+  RegLocation rlDest = getLoc(cUnit, inst);
+  RegLocation rlSrc = getLoc(cUnit, inst->getOperand(0));
+  genConversion(cUnit, Instruction::FLOAT_TO_DOUBLE, rlDest, rlSrc);
+}
+
+void cvtTrunc(CompilationUnit* cUnit, llvm::Instruction* inst)
+{
+  RegLocation rlDest = getLoc(cUnit, inst);
+  RegLocation rlSrc = getLoc(cUnit, inst->getOperand(0));
+  rlSrc = oatUpdateLocWide(cUnit, rlSrc);
+  rlSrc = oatWideToNarrow(cUnit, rlSrc);
+  storeValue(cUnit, rlDest, rlSrc);
+}
+
+void cvtDoubleToFloat(CompilationUnit* cUnit, llvm::Instruction* inst)
+{
+  RegLocation rlDest = getLoc(cUnit, inst);
+  RegLocation rlSrc = getLoc(cUnit, inst->getOperand(0));
+  genConversion(cUnit, Instruction::DOUBLE_TO_FLOAT, rlDest, rlSrc);
+}
+
+
 void cvtIntExt(CompilationUnit* cUnit, llvm::Instruction* inst, bool isSigned)
 {
   // TODO: evaluate src/tgt types and add general support for more than int to long
@@ -2094,6 +2263,8 @@
   DCHECK_EQ(callInst->getNumArgOperands(), 1U);
   RegLocation rlSrc = getLoc(cUnit, callInst->getArgOperand(0));
   RegLocation rlDest = getLoc(cUnit, callInst);
+  DCHECK_EQ(rlSrc.wide, rlDest.wide);
+  DCHECK_EQ(rlSrc.fp, rlDest.fp);
   if (rlSrc.wide) {
     storeValueWide(cUnit, rlDest, rlSrc);
   } else {
@@ -2211,7 +2382,7 @@
   }
 }
 
-void cvtMonitorArrayLength(CompilationUnit* cUnit, llvm::CallInst* callInst)
+void cvtArrayLength(CompilationUnit* cUnit, llvm::CallInst* callInst)
 {
   DCHECK_EQ(callInst->getNumArgOperands(), 2U);
   llvm::ConstantInt* optFlags =
@@ -2332,8 +2503,25 @@
   genCheckCast(cUnit, typeIdx->getZExtValue(), rlSrc);
 }
 
+void cvtFPCompare(CompilationUnit* cUnit, llvm::CallInst* callInst,
+                  Instruction::Code opcode)
+{
+  RegLocation rlSrc1 = getLoc(cUnit, callInst->getArgOperand(0));
+  RegLocation rlSrc2 = getLoc(cUnit, callInst->getArgOperand(1));
+  RegLocation rlDest = getLoc(cUnit, callInst);
+  genCmpFP(cUnit, opcode, rlDest, rlSrc1, rlSrc2);
+}
+
+void cvtLongCompare(CompilationUnit* cUnit, llvm::CallInst* callInst)
+{
+  RegLocation rlSrc1 = getLoc(cUnit, callInst->getArgOperand(0));
+  RegLocation rlSrc2 = getLoc(cUnit, callInst->getArgOperand(1));
+  RegLocation rlDest = getLoc(cUnit, callInst);
+  genCmpLong(cUnit, rlDest, rlSrc1, rlSrc2);
+}
+
 void cvtInvoke(CompilationUnit* cUnit, llvm::CallInst* callInst,
-               bool isVoid, bool isNewArray)
+               bool isVoid, bool isFilledNewArray)
 {
   CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true,
                                          kAllocMisc);
@@ -2378,7 +2566,7 @@
     }
     next++;
   }
-  if (isNewArray) {
+  if (isFilledNewArray) {
     genFilledNewArray(cUnit, info);
   } else {
     genInvoke(cUnit, info);
@@ -2570,6 +2758,18 @@
             case greenland::IntrinsicHelper::HLSgetDouble:
               cvtSget(cUnit, callInst, true /* wide */, false /* Object */);
               break;
+            case greenland::IntrinsicHelper::HLSput:
+            case greenland::IntrinsicHelper::HLSputFloat:
+            case greenland::IntrinsicHelper::HLSputBoolean:
+            case greenland::IntrinsicHelper::HLSputByte:
+            case greenland::IntrinsicHelper::HLSputChar:
+            case greenland::IntrinsicHelper::HLSputShort:
+              cvtSput(cUnit, callInst, false /* wide */, false /* Object */);
+              break;
+            case greenland::IntrinsicHelper::HLSputWide:
+            case greenland::IntrinsicHelper::HLSputDouble:
+              cvtSput(cUnit, callInst, true /* wide */, false /* Object */);
+              break;
             case greenland::IntrinsicHelper::GetException:
               cvtMoveException(cUnit, callInst);
               break;
@@ -2586,7 +2786,7 @@
               cvtMonitorEnterExit(cUnit, false /* isEnter */, callInst);
               break;
             case greenland::IntrinsicHelper::ArrayLength:
-              cvtMonitorArrayLength(cUnit, callInst);
+              cvtArrayLength(cUnit, callInst);
               break;
             case greenland::IntrinsicHelper::NewArray:
               cvtNewArray(cUnit, callInst);
@@ -2705,6 +2905,23 @@
               cvtIntNarrowing(cUnit, callInst, Instruction::INT_TO_BYTE);
               break;
 
+            case greenland::IntrinsicHelper::CmplFloat:
+              cvtFPCompare(cUnit, callInst, Instruction::CMPL_FLOAT);
+              break;
+            case greenland::IntrinsicHelper::CmpgFloat:
+              cvtFPCompare(cUnit, callInst, Instruction::CMPG_FLOAT);
+              break;
+            case greenland::IntrinsicHelper::CmplDouble:
+              cvtFPCompare(cUnit, callInst, Instruction::CMPL_DOUBLE);
+              break;
+            case greenland::IntrinsicHelper::CmpgDouble:
+              cvtFPCompare(cUnit, callInst, Instruction::CMPG_DOUBLE);
+              break;
+
+            case greenland::IntrinsicHelper::CmpLong:
+              cvtLongCompare(cUnit, callInst);
+              break;
+
             case greenland::IntrinsicHelper::UnknownId:
               cvtCall(cUnit, callInst, callee);
               break;
@@ -2734,6 +2951,11 @@
       case llvm::Instruction::FMul: cvtBinFPOp(cUnit, kOpMul, inst); break;
       case llvm::Instruction::FDiv: cvtBinFPOp(cUnit, kOpDiv, inst); break;
       case llvm::Instruction::FRem: cvtBinFPOp(cUnit, kOpRem, inst); break;
+      case llvm::Instruction::SIToFP: cvtIntToFP(cUnit, inst); break;
+      case llvm::Instruction::FPToSI: cvtFPToInt(cUnit, inst); break;
+      case llvm::Instruction::FPTrunc: cvtDoubleToFloat(cUnit, inst); break;
+      case llvm::Instruction::FPExt: cvtFloatToDouble(cUnit, inst); break;
+      case llvm::Instruction::Trunc: cvtTrunc(cUnit, inst); break;
 
       case llvm::Instruction::ZExt: cvtIntExt(cUnit, inst, false /* signed */);
         break;
@@ -2744,20 +2966,12 @@
         break;  // FIXME: can we really ignore these?
 
       case llvm::Instruction::Invoke:
-      case llvm::Instruction::Trunc:
       case llvm::Instruction::FPToUI:
-      case llvm::Instruction::FPToSI:
       case llvm::Instruction::UIToFP:
-      case llvm::Instruction::SIToFP:
-      case llvm::Instruction::FPTrunc:
-      case llvm::Instruction::FPExt:
       case llvm::Instruction::PtrToInt:
       case llvm::Instruction::IntToPtr:
       case llvm::Instruction::Switch:
       case llvm::Instruction::FCmp:
-        UNIMPLEMENTED(FATAL) << "Unimplemented llvm opcode: " << opcode;
-        break;
-
       case llvm::Instruction::URem:
       case llvm::Instruction::UDiv:
       case llvm::Instruction::Resume:
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index 89ec4c4..084d09c 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -548,25 +548,25 @@
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayGetBoolean,
                           dex_lang_hl_aget_boolean,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt1Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayGetByte,
                           dex_lang_hl_aget_byte,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt8Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayGetChar,
                           dex_lang_hl_aget_char,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt16Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayGetShort,
                           dex_lang_hl_aget_short,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt16Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 // void dex_lang_aput_[type](int optFlags, [type] value, JavaObject* array, uint32_t index)
@@ -604,25 +604,25 @@
                           dex_lang_hl_aput_boolean,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt1Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayPutByte,
                           dex_lang_hl_aput_byte,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt8Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayPutChar,
                           dex_lang_hl_aput_char,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt16Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLArrayPutShort,
                           dex_lang_hl_aput_short,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt16Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 //----------------------------------------------------------------------------
 // High-level Instance get/put
@@ -665,25 +665,25 @@
 _EVAL_DEF_INTRINSICS_FUNC(HLIGetBoolean,
                           dex_lang_hl_iget_boolean,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt1Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLIGetByte,
                           dex_lang_hl_iget_byte,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt8Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLIGetChar,
                           dex_lang_hl_iget_char,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt16Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLIGetShort,
                           dex_lang_hl_iget_short,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt16Ty,
+                          kInt32Ty,
                           _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 // void dex_lang_iput_[type](int optFlags, [type] value, JavaObject* ojb, uint32_t field_idx)
@@ -721,25 +721,25 @@
                           dex_lang_hl_iput_boolean,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt1Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLIPutByte,
                           dex_lang_hl_iput_byte,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt8Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLIPutChar,
                           dex_lang_hl_iput_char,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt16Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(HLIPutShort,
                           dex_lang_hl_iput_short,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG4(kInt32Ty, kInt16Ty, kJavaObjectTy, kInt32Ty))
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
 
 //----------------------------------------------------------------------------
 // High-level Invokes (fast-path determination not yet performed)
@@ -944,28 +944,28 @@
                           dex_lang_hl_sput_boolean,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG2(kInt32Ty, kInt1Ty))
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
 // void sput_hl_byte(int field_idx, int val)
 _EVAL_DEF_INTRINSICS_FUNC(HLSputByte,
                           dex_lang_hl_sput_byte,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG2(kInt32Ty, kInt8Ty))
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
 // void sput_hl_char(int field_idx, kInt16Ty val)
 _EVAL_DEF_INTRINSICS_FUNC(HLSputChar,
                           dex_lang_hl_sput_char,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG2(kInt32Ty, kInt16Ty))
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
 // void sput_hl_short(int field_idx, int val)
 _EVAL_DEF_INTRINSICS_FUNC(HLSputShort,
                           dex_lang_hl_sput_short,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG2(kInt32Ty, kInt16Ty))
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
 // void sput_hl_wide(int field_idx, long val)
 _EVAL_DEF_INTRINSICS_FUNC(HLSputWide,
@@ -1012,28 +1012,28 @@
 _EVAL_DEF_INTRINSICS_FUNC(HLSgetBoolean,
                           dex_lang_hl_sget_boolean,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt1Ty,
+                          kInt32Ty,
                           _EXPAND_ARG1(kInt32Ty))
 
 // byte sget_hl_byte(int field_idx)
 _EVAL_DEF_INTRINSICS_FUNC(HLSgetByte,
                           dex_lang_hl_sget_byte,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt8Ty,
+                          kInt32Ty,
                           _EXPAND_ARG1(kInt32Ty))
 
 // char sget_hl_char(int field_idx)
 _EVAL_DEF_INTRINSICS_FUNC(HLSgetChar,
                           dex_lang_hl_sget_char,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt16Ty,
+                          kInt32Ty,
                           _EXPAND_ARG1(kInt32Ty))
 
 // char sget_hl_short(int field_idx)
 _EVAL_DEF_INTRINSICS_FUNC(HLSgetShort,
                           dex_lang_hl_sget_short,
                           kAttrReadOnly | kAttrNoThrow,
-                          kInt16Ty,
+                          kInt32Ty,
                           _EXPAND_ARG1(kInt32Ty))
 
 // char sget_hl_wide(int field_idx)
@@ -1059,19 +1059,19 @@
 //----------------------------------------------------------------------------
 // Monitor enter/exit
 //----------------------------------------------------------------------------
-// uint32_t dex_lang_monitor_enter(JavaObject* obj)
+// uint32_t dex_lang_monitor_enter(int optFlags, JavaObject* obj)
 _EVAL_DEF_INTRINSICS_FUNC(MonitorEnter,
                           dex_lang_monitor_enter,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG1(kJavaObjectTy))
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
 
-// uint32_t dex_lang_monitor_exit(JavaObject* obj)
+// uint32_t dex_lang_monitor_exit(int optFlags, JavaObject* obj)
 _EVAL_DEF_INTRINSICS_FUNC(MonitorExit,
                           dex_lang_monitor_exit,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG1(kJavaObjectTy))
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
 
 //----------------------------------------------------------------------------
 // Shadow Frame
@@ -1106,6 +1106,64 @@
                           _EXPAND_ARG1(kInt32ConstantTy))
 
 //----------------------------------------------------------------------------
+// FP Comparison
+//----------------------------------------------------------------------------
+// int cmpl_float(float, float)
+_EVAL_DEF_INTRINSICS_FUNC(CmplFloat,
+                          dex_lang_cmpl_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kFloatTy, kFloatTy))
+
+// int cmpg_float(float, float)
+_EVAL_DEF_INTRINSICS_FUNC(CmpgFloat,
+                          dex_lang_cmpg_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kFloatTy, kFloatTy))
+
+// int cmpl_double(double, double)
+_EVAL_DEF_INTRINSICS_FUNC(CmplDouble,
+                          dex_lang_cmpl_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kDoubleTy, kDoubleTy))
+
+// int cmpg_double(double, double)
+_EVAL_DEF_INTRINSICS_FUNC(CmpgDouble,
+                          dex_lang_cmpg_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kDoubleTy, kDoubleTy))
+
+//----------------------------------------------------------------------------
+// Long Comparison
+//----------------------------------------------------------------------------
+// int cmp_long(long, long)
+_EVAL_DEF_INTRINSICS_FUNC(CmpLong,
+                          dex_lang_cmp_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt64Ty, kInt64Ty))
+
+//----------------------------------------------------------------------------
+// Switch
+//----------------------------------------------------------------------------
+// void sparse_switch(int, int)
+_EVAL_DEF_INTRINSICS_FUNC(SparseSwitch,
+                          dex_lang_sparse_switch,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// void packed_switch(int, int)
+_EVAL_DEF_INTRINSICS_FUNC(PackedSwitch,
+                          dex_lang_packed_switch,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+//----------------------------------------------------------------------------
 // Const intrinsics to assist MIR to Greenland_ir conversion.  Should not materialize
 // For simplicity, all use integer input
 //----------------------------------------------------------------------------