Quick compiler - various bug fixes
Continuing clean-up of the MIR->LLVMIR->LIR path. With this CL,
all of run-test 003 passes except for tests which need switch
support (unimplemented) and one of the Throw tests (I'm apparently not
fully describing all of the exception-related edges in the CFG).
Change-Id: I2075357bc7c5419c873bb62d44c34fdb73424e29
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index d617be5..b714065 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -759,16 +759,10 @@
#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)
|| (PrettyMethod(method_idx, dex_file).find("catchAndRethrow") != std::string::npos)
- || (PrettyMethod(method_idx, dex_file).find("throwNullPointerException") != std::string::npos)
|| (PrettyMethod(method_idx, dex_file).find("math_012") != std::string::npos)
|| (PrettyMethod(method_idx, dex_file).find("math_013") != std::string::npos)
|| (PrettyMethod(method_idx, dex_file).find("math_014") != std::string::npos)
@@ -781,6 +775,24 @@
|| (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)
+ || (PrettyMethod(method_idx, dex_file).find("Array") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("Classes") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("Compare") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("FloatMath") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("Goto") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("InternedString") != std::string::npos)
+ // || (PrettyMethod(method_idx, dex_file).find("IntMath") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("InstField") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("MethodCall") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("Monitor") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("StaticField") != std::string::npos)
+ // || (PrettyMethod(method_idx, dex_file).find("Switch") != std::string::npos)
+ // || (PrettyMethod(method_idx, dex_file).find("Throw.rethrow") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("UnresClass") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("UsresClassSubclass") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("UsresStuff") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("UsresTest1") != std::string::npos)
+ || (PrettyMethod(method_idx, dex_file).find("UsresTest2") != std::string::npos)
) {
cUnit->genBitcode = true;
}
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index cd4e1d3..a4521bb 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -333,7 +333,6 @@
src2 = cUnit->irb->getInt32(0);
}
llvm::Value* condValue = convertCompare(cUnit, cc, src1, src2);
- condValue->setName(StringPrintf("t%d", cUnit->tempName++));
cUnit->irb->CreateCondBr(condValue, getLLVMBlock(cUnit, bb->taken->id),
getLLVMBlock(cUnit, bb->fallThrough->id));
// Don't redo the fallthrough branch in the BB driver
@@ -429,6 +428,7 @@
{
llvm::Value* src1 = getLLVMValue(cUnit, rlSrc1.origSReg);
llvm::Value* src2 = getLLVMValue(cUnit, rlSrc2.origSReg);
+ DCHECK_EQ(src1->getType(), src2->getType());
llvm::Value* res = genArithOp(cUnit, op, rlDest.wide, src1, src2);
defineValue(cUnit, res, rlDest.origSReg);
}
@@ -479,13 +479,7 @@
// Insert the optimization flags
args.push_back(cUnit->irb->getInt32(info->optFlags));
// Now, insert the actual arguments
- if (cUnit->printMe) {
- LOG(INFO) << "Building Invoke info";
- }
for (int i = 0; i < info->numArgWords;) {
- if (cUnit->printMe) {
- oatDumpRegLoc(info->args[i]);
- }
llvm::Value* val = getLLVMValue(cUnit, info->args[i].origSReg);
args.push_back(val);
i += info->args[i].wide ? 2 : 1;
@@ -1344,39 +1338,39 @@
case Instruction::IGET:
if (rlDest.fp) {
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetFloat,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
} else {
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGet,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
}
break;
case Instruction::IGET_OBJECT:
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetObject,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
break;
case Instruction::IGET_BOOLEAN:
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetBoolean,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
break;
case Instruction::IGET_BYTE:
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetByte,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
break;
case Instruction::IGET_CHAR:
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetChar,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
break;
case Instruction::IGET_SHORT:
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetShort,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
break;
case Instruction::IGET_WIDE:
if (rlDest.fp) {
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetDouble,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
} else {
convertIget(cUnit, optFlags, greenland::IntrinsicHelper::HLIGetWide,
- rlSrc[0], rlSrc[1], vC);
+ rlDest, rlSrc[0], vC);
}
break;
case Instruction::IPUT:
@@ -1710,10 +1704,32 @@
return false;
}
+char remapShorty(char shortyType) {
+ /*
+ * TODO: might want to revisit this. Dalvik registers are 32-bits wide,
+ * and longs/doubles are represented as a pair of registers. When sub-word
+ * arguments (and method results) are passed, they are extended to Dalvik
+ * virtual register containers. Because llvm is picky about type consistency,
+ * we must either cast the "real" type to 32-bit container multiple Dalvik
+ * register types, or always use the expanded values.
+ * Here, we're doing the latter. We map the shorty signature to container
+ * types (which is valid so long as we always do a real expansion of passed
+ * arguments and field loads).
+ */
+ switch(shortyType) {
+ case 'Z' : shortyType = 'I'; break;
+ case 'B' : shortyType = 'I'; break;
+ case 'S' : shortyType = 'I'; break;
+ case 'C' : shortyType = 'I'; break;
+ default: break;
+ }
+ return shortyType;
+}
+
llvm::FunctionType* getFunctionType(CompilationUnit* cUnit) {
// Get return type
- llvm::Type* ret_type = cUnit->irb->GetJType(cUnit->shorty[0],
+ llvm::Type* ret_type = cUnit->irb->GetJType(remapShorty(cUnit->shorty[0]),
greenland::kAccurate);
// Get argument type
@@ -1728,7 +1744,7 @@
}
for (uint32_t i = 1; i < strlen(cUnit->shorty); ++i) {
- args_type.push_back(cUnit->irb->GetJType(cUnit->shorty[i],
+ args_type.push_back(cUnit->irb->GetJType(remapShorty(cUnit->shorty[i]),
greenland::kAccurate));
}
@@ -1839,6 +1855,11 @@
// Recover previously-created argument values
llvm::Value* argVal = arg_iter++;
oatInsertGrowableList(cUnit, &cUnit->llvmValues, (intptr_t)argVal);
+ if (cUnit->regLocation[i].wide) {
+ // Skip high half of wide values.
+ oatInsertGrowableList(cUnit, &cUnit->llvmValues, 0);
+ i++;
+ }
}
}
cUnit->irb->CreateBr(cUnit->placeholderBB);
@@ -1987,13 +2008,32 @@
void cvtBinFPOp(CompilationUnit* cUnit, OpKind op, llvm::Instruction* inst)
{
RegLocation rlDest = getLoc(cUnit, inst);
- RegLocation rlSrc1 = getLoc(cUnit, inst->getOperand(0));
- RegLocation rlSrc2 = getLoc(cUnit, inst->getOperand(1));
- Instruction::Code dalvikOp = getDalvikFPOpcode(op, false, rlDest.wide);
- if (rlDest.wide) {
- genArithOpDouble(cUnit, dalvikOp, rlDest, rlSrc1, rlSrc2);
+ /*
+ * Normally, we won't ever generate an FP operation with an immediate
+ * operand (not supported in Dex instruction set). However, the IR builder
+ * may insert them - in particular for createNegFP. Recognize this case
+ * and deal with it.
+ */
+ llvm::ConstantFP* op1C = llvm::dyn_cast<llvm::ConstantFP>(inst->getOperand(0));
+ llvm::ConstantFP* op2C = llvm::dyn_cast<llvm::ConstantFP>(inst->getOperand(1));
+ DCHECK(op2C == NULL);
+ if ((op1C != NULL) && (op == kOpSub)) {
+ RegLocation rlSrc = getLoc(cUnit, inst->getOperand(1));
+ if (rlDest.wide) {
+ genArithOpDouble(cUnit, Instruction::NEG_DOUBLE, rlDest, rlSrc, rlSrc);
+ } else {
+ genArithOpFloat(cUnit, Instruction::NEG_FLOAT, rlDest, rlSrc, rlSrc);
+ }
} else {
- genArithOpFloat(cUnit, dalvikOp, rlDest, rlSrc1, rlSrc2);
+ DCHECK(op1C == NULL);
+ RegLocation rlSrc1 = getLoc(cUnit, inst->getOperand(0));
+ RegLocation rlSrc2 = getLoc(cUnit, inst->getOperand(1));
+ Instruction::Code dalvikOp = getDalvikFPOpcode(op, false, rlDest.wide);
+ if (rlDest.wide) {
+ genArithOpDouble(cUnit, dalvikOp, rlDest, rlSrc1, rlSrc2);
+ } else {
+ genArithOpFloat(cUnit, dalvikOp, rlDest, rlSrc1, rlSrc2);
+ }
}
}
@@ -2489,7 +2529,7 @@
RegLocation rlSrc = getLoc(cUnit, callInst->getArgOperand(1));
RegLocation rlObj = getLoc(cUnit, callInst->getArgOperand(2));
llvm::ConstantInt* fieldIdx =
- llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(2));
+ llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(3));
genIPut(cUnit, fieldIdx->getZExtValue(), optFlags->getZExtValue(),
size, rlSrc, rlObj, isWide, isObj);
}
@@ -2541,9 +2581,6 @@
info->optFlags = optFlagsVal->getZExtValue();
info->offset = cUnit->currentDalvikOffset;
- // FIXME - rework such that we no longer need isRange
- info->isRange = false;
-
// Count the argument words, and then build argument array.
info->numArgWords = 0;
for (unsigned int i = 3; i < callInst->getNumArgOperands(); i++) {
@@ -2555,9 +2592,6 @@
// Now, fill in the location records, synthesizing high loc of wide vals
for (int i = 3, next = 0; next < info->numArgWords;) {
info->args[next] = getLoc(cUnit, callInst->getArgOperand(i++));
- if (cUnit->printMe) {
- oatDumpRegLoc(info->args[next]);
- }
if (info->args[next].wide) {
next++;
// TODO: Might make sense to mark this as an invalid loc
@@ -2566,6 +2600,9 @@
}
next++;
}
+ // TODO - rework such that we no longer need isRange
+ info->isRange = (info->numArgWords > 5);
+
if (isFilledNewArray) {
genFilledNewArray(cUnit, info);
} else {
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index 084d09c..608e760 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -175,7 +175,7 @@
_EVAL_DEF_INTRINSICS_FUNC(InstanceOf,
dex_lang_instance_of,
kAttrNone,
- kInt1Ty,
+ kInt32Ty,
_EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
//----------------------------------------------------------------------------
@@ -686,7 +686,7 @@
kInt32Ty,
_EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
-// void dex_lang_iput_[type](int optFlags, [type] value, JavaObject* ojb, uint32_t field_idx)
+// void dex_lang_iput_[type](int optFlags, [type] value, JavaObject* obj, uint32_t field_idx)
_EVAL_DEF_INTRINSICS_FUNC(HLIPut,
dex_lang_hl_iput,
kAttrNoThrow,