diff options
| author | 2012-06-15 16:40:31 -0700 | |
|---|---|---|
| committer | 2012-06-16 14:56:03 -0700 | |
| commit | 6969d50c820bd63043940b0e0f0ddc6e6ac763b0 (patch) | |
| tree | e6e02ddea49c4ad6706931a62172bce9a921d8d0 /src/compiler/codegen/MethodBitcode.cc | |
| parent | e5f01223ae03b89767dc7881d75dca061121ee36 (diff) | |
Invoke support for Quick Compiler
Fleshed out invoke and const-string support. Fixed a bug in Phi node
insertion.
With this CL, the "Recursive Fibonacci" and "HelloWorld" milestones are
met.
Added are a set of "HL" (for High-Level) invoke intrinsics. Until we
complete the merging of the Quick & Iceland runtime models the invoke
code sequences are slightly different. Thus, the Greenland IR needs
to represent invokes at a somewhat higher level than Iceland. The
test for fast/slow path needs to happen during the lowering of the
HLInvokeXXX intrinsics in both the Quick and Portable paths.
This will generally be the case in the short term - push fast/slow
path determination below the Greenland IR level. As unification
proceeds, we'll pull as much as makes sense into the common front end.
Change-Id: I0a18edf1be18583c0afdc3f7e10a3e4691968e77
Diffstat (limited to 'src/compiler/codegen/MethodBitcode.cc')
| -rw-r--r-- | src/compiler/codegen/MethodBitcode.cc | 316 |
1 files changed, 247 insertions, 69 deletions
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index 3b6b087e8d..f13a473be5 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -28,7 +28,7 @@ #include <llvm/Instructions.h> #include <llvm/Support/Casting.h> -const char* labelFormat = "L0x%x_d"; +const char* labelFormat = "L0x%x_%d"; namespace art { extern const RegLocation badLoc; @@ -193,6 +193,8 @@ void convertCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, 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 + bb->fallThrough = NULL; } void convertCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, @@ -212,6 +214,8 @@ void convertCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, 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 + bb->fallThrough = NULL; } llvm::Value* genDivModOp(CompilationUnit* cUnit, bool isDiv, bool isLong, @@ -314,6 +318,70 @@ void convertArithOpLit(CompilationUnit* cUnit, OpKind op, RegLocation rlDest, defineValue(cUnit, res, rlDest.origSReg); } +void convertInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, + InvokeType invokeType, bool isRange) +{ + CallInfo* info = oatNewCallInfo(cUnit, bb, mir, invokeType, isRange); + llvm::SmallVector<llvm::Value*, 10> args; + // Insert the invokeType + args.push_back(cUnit->irb->getInt32(static_cast<int>(invokeType))); + // Insert the method_idx + args.push_back(cUnit->irb->getInt32(info->index)); + // 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; + } + /* + * Choose the invoke return type based on actual usage. Note: may + * be different than shorty. For example, if a function return value + * is not used, we'll treat this as a void invoke. + */ + greenland::IntrinsicHelper::IntrinsicId id; + if (info->result.location == kLocInvalid) { + id = greenland::IntrinsicHelper::HLInvokeVoid; + } else { + if (info->result.wide) { + if (info->result.fp) { + id = greenland::IntrinsicHelper::HLInvokeDouble; + } else { + id = greenland::IntrinsicHelper::HLInvokeFloat; + } + } else if (info->result.ref) { + id = greenland::IntrinsicHelper::HLInvokeObj; + } else if (info->result.fp) { + id = greenland::IntrinsicHelper::HLInvokeFloat; + } else { + id = greenland::IntrinsicHelper::HLInvokeInt; + } + } + llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id); + llvm::Value* res = cUnit->irb->CreateCall(intr, args); + if (info->result.location != kLocInvalid) { + defineValue(cUnit, res, info->result.origSReg); + } +} + +void convertConstString(CompilationUnit* cUnit, BasicBlock* bb, + uint32_t string_idx, RegLocation rlDest) +{ + greenland::IntrinsicHelper::IntrinsicId id; + id = greenland::IntrinsicHelper::ConstString; + llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id); + llvm::Value* index = cUnit->irb->getInt32(string_idx); + llvm::Value* res = cUnit->irb->CreateCall(intr, index); + defineValue(cUnit, res, rlDest.origSReg); +} + /* * Target-independent code generation. Use only high-level * load/store utilities here, or target-dependent genXX() handlers @@ -327,6 +395,9 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, RegLocation rlDest = badLoc; RegLocation rlResult = badLoc; Instruction::Code opcode = mir->dalvikInsn.opcode; + uint32_t vB = mir->dalvikInsn.vB; + uint32_t vC = mir->dalvikInsn.vC; + bool objectDefinition = false; /* Prep Src and Dest locations */ @@ -398,7 +469,7 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, case Instruction::CONST: case Instruction::CONST_4: case Instruction::CONST_16: { - llvm::Constant* immValue = cUnit->irb->GetJInt(mir->dalvikInsn.vB); + llvm::Constant* immValue = cUnit->irb->GetJInt(vB); llvm::Value* res = emitConst(cUnit, immValue, rlDest); defineValue(cUnit, res, rlDest.origSReg); } @@ -406,14 +477,14 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, case Instruction::CONST_WIDE_16: case Instruction::CONST_WIDE_32: { - llvm::Constant* immValue = cUnit->irb->GetJLong(mir->dalvikInsn.vB); + llvm::Constant* immValue = cUnit->irb->GetJLong(vB); llvm::Value* res = emitConst(cUnit, immValue, rlDest); defineValue(cUnit, res, rlDest.origSReg); } break; case Instruction::CONST_HIGH16: { - llvm::Constant* immValue = cUnit->irb->GetJInt(mir->dalvikInsn.vB << 16); + llvm::Constant* immValue = cUnit->irb->GetJInt(vB << 16); llvm::Value* res = emitConst(cUnit, immValue, rlDest); defineValue(cUnit, res, rlDest.origSReg); } @@ -426,7 +497,7 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, defineValue(cUnit, res, rlDest.origSReg); } case Instruction::CONST_WIDE_HIGH16: { - int64_t imm = static_cast<int64_t>(mir->dalvikInsn.vB) << 48; + int64_t imm = static_cast<int64_t>(vB) << 48; llvm::Constant* immValue = cUnit->irb->GetJLong(imm); llvm::Value* res = emitConst(cUnit, immValue, rlDest); defineValue(cUnit, res, rlDest.origSReg); @@ -570,44 +641,44 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, case Instruction::ADD_INT_LIT16: case Instruction::ADD_INT_LIT8: - convertArithOpLit(cUnit, kOpAdd, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpAdd, rlDest, rlSrc[0], vC); break; case Instruction::RSUB_INT: case Instruction::RSUB_INT_LIT8: - convertArithOpLit(cUnit, kOpRsub, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpRsub, rlDest, rlSrc[0], vC); break; case Instruction::MUL_INT_LIT16: case Instruction::MUL_INT_LIT8: - convertArithOpLit(cUnit, kOpMul, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpMul, rlDest, rlSrc[0], vC); break; case Instruction::DIV_INT_LIT16: case Instruction::DIV_INT_LIT8: - convertArithOpLit(cUnit, kOpDiv, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpDiv, rlDest, rlSrc[0], vC); break; case Instruction::REM_INT_LIT16: case Instruction::REM_INT_LIT8: - convertArithOpLit(cUnit, kOpRem, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpRem, rlDest, rlSrc[0], vC); break; case Instruction::AND_INT_LIT16: case Instruction::AND_INT_LIT8: - convertArithOpLit(cUnit, kOpAnd, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpAnd, rlDest, rlSrc[0], vC); break; case Instruction::OR_INT_LIT16: case Instruction::OR_INT_LIT8: - convertArithOpLit(cUnit, kOpOr, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpOr, rlDest, rlSrc[0], vC); break; case Instruction::XOR_INT_LIT16: case Instruction::XOR_INT_LIT8: - convertArithOpLit(cUnit, kOpXor, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpXor, rlDest, rlSrc[0], vC); break; case Instruction::SHL_INT_LIT8: - convertArithOpLit(cUnit, kOpLsl, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpLsl, rlDest, rlSrc[0], vC); break; case Instruction::SHR_INT_LIT8: - convertArithOpLit(cUnit, kOpLsr, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpLsr, rlDest, rlSrc[0], vC); break; case Instruction::USHR_INT_LIT8: - convertArithOpLit(cUnit, kOpAsr, rlDest, rlSrc[0], mir->dalvikInsn.vC); + convertArithOpLit(cUnit, kOpAsr, rlDest, rlSrc[0], vC); break; case Instruction::ADD_FLOAT: @@ -645,6 +716,47 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, convertFPArithOp(cUnit, kOpRem, rlDest, rlSrc[0], rlSrc[1]); break; + case Instruction::INVOKE_STATIC: + convertInvoke(cUnit, bb, mir, kStatic, false /*range*/); + break; + case Instruction::INVOKE_STATIC_RANGE: + convertInvoke(cUnit, bb, mir, kStatic, true /*range*/); + break; + + case Instruction::INVOKE_DIRECT: + convertInvoke(cUnit, bb, mir, kDirect, false /*range*/); + break; + case Instruction::INVOKE_DIRECT_RANGE: + convertInvoke(cUnit, bb, mir, kDirect, true /*range*/); + break; + + case Instruction::INVOKE_VIRTUAL: + convertInvoke(cUnit, bb, mir, kVirtual, false /*range*/); + break; + case Instruction::INVOKE_VIRTUAL_RANGE: + convertInvoke(cUnit, bb, mir, kVirtual, true /*range*/); + break; + + case Instruction::INVOKE_SUPER: + convertInvoke(cUnit, bb, mir, kSuper, false /*range*/); + break; + case Instruction::INVOKE_SUPER_RANGE: + convertInvoke(cUnit, bb, mir, kSuper, true /*range*/); + break; + + case Instruction::INVOKE_INTERFACE: + convertInvoke(cUnit, bb, mir, kInterface, false /*range*/); + break; + case Instruction::INVOKE_INTERFACE_RANGE: + convertInvoke(cUnit, bb, mir, kInterface, true /*range*/); + break; + + case Instruction::CONST_STRING: + case Instruction::CONST_STRING_JUMBO: + convertConstString(cUnit, bb, vB, rlDest); + break; + + #if 0 case Instruction::MOVE_EXCEPTION: { @@ -715,11 +827,6 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, storeValue(cUnit, rlDest, rlResult); break; - case Instruction::CONST_STRING: - case Instruction::CONST_STRING_JUMBO: - genConstString(cUnit, mir, rlDest, rlSrc[0]); - break; - case Instruction::CONST_CLASS: genConstClass(cUnit, mir, rlDest, rlSrc[0]); break; @@ -884,41 +991,6 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, genSput(cUnit, mir, rlSrc[0], true, false); break; - case Instruction::INVOKE_STATIC_RANGE: - genInvoke(cUnit, bb, mir, kStatic, true /*range*/); - break; - case Instruction::INVOKE_STATIC: - genInvoke(cUnit, bb, mir, kStatic, false /*range*/); - break; - - case Instruction::INVOKE_DIRECT: - genInvoke(cUnit, bb, mir, kDirect, false /*range*/); - break; - case Instruction::INVOKE_DIRECT_RANGE: - genInvoke(cUnit, bb, mir, kDirect, true /*range*/); - break; - - case Instruction::INVOKE_VIRTUAL: - genInvoke(cUnit, bb, mir, kVirtual, false /*range*/); - break; - case Instruction::INVOKE_VIRTUAL_RANGE: - genInvoke(cUnit, bb, mir, kVirtual, true /*range*/); - break; - - case Instruction::INVOKE_SUPER: - genInvoke(cUnit, bb, mir, kSuper, false /*range*/); - break; - case Instruction::INVOKE_SUPER_RANGE: - genInvoke(cUnit, bb, mir, kSuper, true /*range*/); - break; - - case Instruction::INVOKE_INTERFACE: - genInvoke(cUnit, bb, mir, kInterface, false /*range*/); - break; - case Instruction::INVOKE_INTERFACE_RANGE: - genInvoke(cUnit, bb, mir, kInterface, true /*range*/); - break; - case Instruction::NEG_INT: case Instruction::NOT_INT: res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]); @@ -1114,6 +1186,15 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) * path, it will need to be regenereated. */ return false; + } else if (bb->blockType == kExceptionHandling) { + /* + * Because we're deferring null checking, delete the associated empty + * exception block. + * TODO: add new block type for exception blocks that we generate + * greenland code for. + */ + llvmBB->eraseFromParent(); + return false; } for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) { @@ -1144,7 +1225,7 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) } } - if ((bb->taken == NULL) && (bb->fallThrough != NULL) && !bb->hasReturn) { + if ((bb->fallThrough != NULL) && !bb->hasReturn) { cUnit->irb->CreateBr(getLLVMBlock(cUnit, bb->fallThrough->id)); } @@ -1291,21 +1372,19 @@ void oatMethodMIR2Bitcode(CompilationUnit* cUnit) llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction); - // Write bitcode to file - std::string errmsg; + // Write bitcode to file + std::string errmsg; - llvm::OwningPtr<llvm::tool_output_file> out_file( + llvm::OwningPtr<llvm::tool_output_file> out_file( new llvm::tool_output_file("/tmp/foo.bc", errmsg, llvm::raw_fd_ostream::F_Binary)); - if (!errmsg.empty()) { - LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; - } - - llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); - out_file->keep(); - + if (!errmsg.empty()) { + LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; + } + llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); + out_file->keep(); } RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) { @@ -1438,6 +1517,7 @@ ConditionCode getCond(llvm::ICmpInst::Predicate llvmCond) ConditionCode res = kCondAl; switch(llvmCond) { case llvm::ICmpInst::ICMP_NE: res = kCondNe; break; + case llvm::ICmpInst::ICMP_EQ: res = kCondEq; break; case llvm::ICmpInst::ICMP_SGT: res = kCondGt; break; default: LOG(FATAL) << "Unexpected llvm condition"; } @@ -1531,6 +1611,65 @@ void cvtConst(CompilationUnit* cUnit, llvm::CallInst* callInst) } } +void cvtConstString(CompilationUnit* cUnit, llvm::CallInst* callInst) +{ + DCHECK(callInst->getNumArgOperands() == 1); + llvm::ConstantInt* stringIdxVal = + llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); + uint32_t stringIdx = stringIdxVal->getZExtValue(); + RegLocation rlDest = getLoc(cUnit, callInst); + genConstString(cUnit, stringIdx, rlDest); +} + +void cvtInvoke(CompilationUnit* cUnit, llvm::CallInst* callInst, + greenland::JType jtype) +{ + CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true, + kAllocMisc); + if (jtype == greenland::kVoid) { + info->result.location = kLocInvalid; + } else { + info->result = getLoc(cUnit, callInst); + } + llvm::ConstantInt* invokeTypeVal = + llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); + llvm::ConstantInt* methodIndexVal = + llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(1)); + llvm::ConstantInt* optFlagsVal = + llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(2)); + info->type = static_cast<InvokeType>(invokeTypeVal->getZExtValue()); + info->index = methodIndexVal->getZExtValue(); + 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++) { + RegLocation tLoc = getLoc(cUnit, callInst->getArgOperand(i)); + info->numArgWords += tLoc.wide ? 2 : 1; + } + info->args = (info->numArgWords == 0) ? NULL : (RegLocation*) + oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc); + // 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 + info->args[next].origSReg = info->args[next-1].origSReg+1; + info->args[next].sRegLow = info->args[next-1].sRegLow+1; + } + next++; + } + genInvoke(cUnit, info); +} + bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) { bool isEntry = (bb == &cUnit->func->getEntryBlock()); @@ -1554,8 +1693,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) //TODO: restore oat incoming liveness optimization oatClobberAllRegs(cUnit); - //LIR* headLIR = NULL; - + LIR* headLIR = NULL; if (isEntry) { cUnit->currentDalvikOffset = 0; @@ -1575,6 +1713,32 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) cUnit->currentDalvikOffset = dexOffsetValue->getZExtValue(); } + oatResetRegPool(cUnit); + if (cUnit->disableOpt & (1 << kTrackLiveTemps)) { + oatClobberAllRegs(cUnit); + } + + if (cUnit->disableOpt & (1 << kSuppressLoads)) { + oatResetDefTracking(cUnit); + } + +#ifndef NDEBUG + /* Reset temp tracking sanity check */ + cUnit->liveSReg = INVALID_SREG; +#endif + + LIR* boundaryLIR; + const char* instStr = "boundary"; + boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, + (intptr_t) instStr); + cUnit->boundaryMap.Overwrite(cUnit->currentDalvikOffset, boundaryLIR); + + /* Remember the first LIR for thisl block*/ + if (headLIR == NULL) { + headLIR = boundaryLIR; + headLIR->defMask = ENCODE_ALL; + } + switch(opcode) { case llvm::Instruction::ICmp: { @@ -1597,6 +1761,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) switch (id) { case greenland::IntrinsicHelper::AllocaShadowFrame: case greenland::IntrinsicHelper::SetShadowFrameEntry: + case greenland::IntrinsicHelper::PopShadowFrame: // Ignore shadow frame stuff for quick compiler break; case greenland::IntrinsicHelper::CopyInt: @@ -1619,6 +1784,15 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) case greenland::IntrinsicHelper::CheckSuspend: genSuspendTest(cUnit, 0 /* optFlags already applied */); break; + case greenland::IntrinsicHelper::HLInvokeInt: + cvtInvoke(cUnit, callInst, greenland::kInt); + break; + case greenland::IntrinsicHelper::HLInvokeVoid: + cvtInvoke(cUnit, callInst, greenland::kVoid); + break; + case greenland::IntrinsicHelper::ConstString: + cvtConstString(cUnit, callInst); + break; case greenland::IntrinsicHelper::UnknownId: cvtCall(cUnit, callInst, callee); break; @@ -1694,6 +1868,10 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) LOG(FATAL) << "Unknown llvm opcode: " << opcode; break; } } + + if (headLIR != NULL) { + oatApplyLocalOptimizations(cUnit, headLIR, cUnit->lastLIRInsn); + } return false; } |