From ad8f15e0b13383b2eaa2486b230debeae7a55661 Mon Sep 17 00:00:00 2001 From: buzbee Date: Mon, 18 Jun 2012 14:49:45 -0700 Subject: Milestone: close Quick side channel communication This CL elminates side-channel communication between the Quick Compiler's Dex->MIR->LLVM-IR and LLVM-IR->LIR lowering stages by clearing key data structures between the two stages. The purpose if to flush out any hidden information transfer, and thus ensure that the GreenlandIR representation of the program is sufficient. Note that as of this change, we've lost all register promotion info so the Quick compiler will generate non-promoted code. A near-future CL will restore that info from the MethodInfo intrinsic. Change-Id: I797845f1fc029bc03aac3ec20f8cd81f917817ca --- src/compiler/codegen/CodegenFactory.cc | 6 +- src/compiler/codegen/GenInvoke.cc | 10 +- src/compiler/codegen/MethodBitcode.cc | 151 ++++++++++++++++++++++++---- src/compiler/codegen/MethodCodegenDriver.cc | 4 +- src/compiler/codegen/Ralloc.h | 1 + src/compiler/codegen/RallocUtil.cc | 11 -- src/compiler/codegen/arm/ArchFactory.cc | 5 +- src/compiler/codegen/mips/ArchFactory.cc | 5 +- src/compiler/codegen/x86/ArchFactory.cc | 5 +- 9 files changed, 153 insertions(+), 45 deletions(-) (limited to 'src/compiler/codegen') diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc index 71b557c0d8..9d380c7e36 100644 --- a/src/compiler/codegen/CodegenFactory.cc +++ b/src/compiler/codegen/CodegenFactory.cc @@ -292,17 +292,17 @@ void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) /* Utilities to load the current Method* */ void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt) { - loadValueDirectFixed(cUnit, cUnit->regLocation[cUnit->methodSReg], rTgt); + loadValueDirectFixed(cUnit, cUnit->methodLoc, rTgt); } RegLocation loadCurrMethod(CompilationUnit *cUnit) { - return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg); + return loadValue(cUnit, cUnit->methodLoc, kCoreReg); } bool methodStarInReg(CompilationUnit* cUnit) { - return (cUnit->regLocation[cUnit->methodSReg].location == kLocPhysReg); + return (cUnit->methodLoc.location == kLocPhysReg); } diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc index bcc9067fd7..7c2cf1cba3 100644 --- a/src/compiler/codegen/GenInvoke.cc +++ b/src/compiler/codegen/GenInvoke.cc @@ -33,16 +33,18 @@ LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target); * If there are any ins passed in registers that have not been promoted * to a callee-save register, flush them to the frame. Perform intial * assignment of promoted arguments. + * + * argLocs is an array of location records describing the incoming arguments + * with one location record per word of argument. */ -void flushIns(CompilationUnit* cUnit) +void flushIns(CompilationUnit* cUnit, RegLocation* argLocs, RegLocation rlMethod) { /* * Dummy up a RegLocation for the incoming Method* * It will attempt to keep rARG0 live (or copy it to home location * if promoted). */ - RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg]; - RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg]; + RegLocation rlSrc = rlMethod; rlSrc.location = kLocPhysReg; rlSrc.lowReg = rARG0; rlSrc.home = false; @@ -75,7 +77,7 @@ void flushIns(CompilationUnit* cUnit) if (i < numArgRegs) { // If arriving in register bool needFlush = true; - RegLocation* tLoc = &cUnit->regLocation[startVReg + i]; + RegLocation* tLoc = &argLocs[i]; if ((vMap->coreLocation == kLocPhysReg) && !tLoc->fp) { opRegCopy(cUnit, vMap->coreReg, argRegs[i]); needFlush = false; diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index f13a473be5..66823c2313 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -27,6 +27,7 @@ #include #include #include +#include const char* labelFormat = "L0x%x_%d"; @@ -75,6 +76,50 @@ llvm::Type* llvmTypeFromLocRec(CompilationUnit* cUnit, RegLocation loc) return res; } +/* Create an in-memory RegLocation from an llvm Value. */ +void createLocFromValue(CompilationUnit* cUnit, llvm::Value* val) +{ + // NOTE: llvm takes shortcuts with c_str() - get to std::string firstt + std::string s(val->getName().str()); + const char* valName = s.c_str(); + if (cUnit->printMe) { + LOG(INFO) << "Processing llvm Value " << valName; + } + SafeMap::iterator it = cUnit->locMap.find(val); + DCHECK(it == cUnit->locMap.end()) << " - already defined: " << valName; + int baseSReg = INVALID_SREG; + int subscript = -1; + sscanf(valName, "v%d_%d", &baseSReg, &subscript); + if ((baseSReg == INVALID_SREG) && (!strcmp(valName, "method"))) { + baseSReg = SSA_METHOD_BASEREG; + subscript = 0; + } + if (cUnit->printMe) { + LOG(INFO) << "Base: " << baseSReg << ", Sub: " << subscript; + } + DCHECK_NE(baseSReg, INVALID_SREG); + DCHECK_NE(subscript, -1); + // TODO: redo during C++'ification + RegLocation loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, INVALID_REG, + INVALID_REG, INVALID_SREG, INVALID_SREG}; + llvm::Type* ty = val->getType(); + loc.wide = ((ty == cUnit->irb->getInt64Ty()) || + (ty == cUnit->irb->getDoubleTy())); + loc.defined = true; + if ((ty == cUnit->irb->getFloatTy()) || + (ty == cUnit->irb->getDoubleTy())) { + loc.fp = true; + } else if (ty == cUnit->irb->GetJObjectTy()) { + loc.ref = true; + } else { + loc.core = true; + } + loc.home = false; // Will change during promotion + loc.sRegLow = baseSReg; + loc.origSReg = cUnit->locMap.size(); + cUnit->locMap.Put(val, loc); +} + void initIR(CompilationUnit* cUnit) { cUnit->context = new llvm::LLVMContext(); @@ -1372,19 +1417,25 @@ void oatMethodMIR2Bitcode(CompilationUnit* cUnit) llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction); - // Write bitcode to file - std::string errmsg; + if (cUnit->enableDebug & (1 << kDebugDumpBitcodeFile)) { + // Write bitcode to file + std::string errmsg; + std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file)); + oatReplaceSpecialChars(fname); + // TODO: make configurable + fname = StringPrintf("/tmp/%s.bc", fname.c_str()); - llvm::OwningPtr out_file( - new llvm::tool_output_file("/tmp/foo.bc", errmsg, - llvm::raw_fd_ostream::F_Binary)); + llvm::OwningPtr out_file( + new llvm::tool_output_file(fname.c_str(), errmsg, + llvm::raw_fd_ostream::F_Binary)); - if (!errmsg.empty()) { - LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; - } + if (!errmsg.empty()) { + LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; + } - llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); - out_file->keep(); + llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); + out_file->keep(); + } } RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) { @@ -1575,11 +1626,6 @@ void cvtCall(CompilationUnit* cUnit, llvm::CallInst* callInst, UNIMPLEMENTED(FATAL); } -void setMethodInfo(CompilationUnit* cUnit, llvm::CallInst* callInst) -{ - UNIMPLEMENTED(WARNING) << "Net setMethodInfo"; -} - void cvtCopy(CompilationUnit* cUnit, llvm::CallInst* callInst) { DCHECK(callInst->getNumArgOperands() == 1); @@ -1670,6 +1716,14 @@ void cvtInvoke(CompilationUnit* cUnit, llvm::CallInst* callInst, genInvoke(cUnit, info); } +/* Look up the RegLocation associated with a Value. Must already be defined */ +RegLocation valToLoc(CompilationUnit* cUnit, llvm::Value* val) +{ + SafeMap::iterator it = cUnit->locMap.find(val); + DCHECK(it != cUnit->locMap.end()) << "Missing definition"; + return it->second; +} + bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) { bool isEntry = (bb == &cUnit->func->getEntryBlock()); @@ -1697,7 +1751,19 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) if (isEntry) { cUnit->currentDalvikOffset = 0; - genEntrySequence(cUnit); + RegLocation* argLocs = (RegLocation*) + oatNew(cUnit, sizeof(RegLocation) * cUnit->numIns, true, kAllocMisc); + llvm::Function::arg_iterator it(cUnit->func->arg_begin()); + llvm::Function::arg_iterator it_end(cUnit->func->arg_end()); + for (unsigned i = 0; it != it_end; ++it) { + llvm::Value* val = it; + argLocs[i++] = valToLoc(cUnit, val); + llvm::Type* ty = val->getType(); + if ((ty == cUnit->irb->getInt64Ty()) || (ty == cUnit->irb->getDoubleTy())) { + argLocs[i++].sRegLow = INVALID_SREG; + } + } + genEntrySequence(cUnit, argLocs, cUnit->methodLoc); } // Visit all of the instructions in the block @@ -1779,7 +1845,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) cvtConst(cUnit, callInst); break; case greenland::IntrinsicHelper::MethodInfo: - setMethodInfo(cUnit, callInst); + // Already dealt with - just ignore it here. break; case greenland::IntrinsicHelper::CheckSuspend: genSuspendTest(cUnit, 0 /* optFlags already applied */); @@ -1891,17 +1957,62 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) */ void oatMethodBitcode2LIR(CompilationUnit* cUnit) { - int numBasicBlocks = cUnit->func->getBasicBlockList().size(); + llvm::Function* func = cUnit->func; + int numBasicBlocks = func->getBasicBlockList().size(); // Allocate a list for LIR basic block labels cUnit->blockLabelList = (void*)oatNew(cUnit, sizeof(LIR) * numBasicBlocks, true, kAllocLIR); LIR* labelList = (LIR*)cUnit->blockLabelList; int nextLabel = 0; - for (llvm::Function::iterator i = cUnit->func->begin(), - e = cUnit->func->end(); i != e; ++i) { + for (llvm::Function::iterator i = func->begin(), + e = func->end(); i != e; ++i) { cUnit->blockToLabelMap.Put(static_cast(i), &labelList[nextLabel++]); } + + /* + * Keep honest - clear regLocations, Value => RegLocation, + * promotion map and VmapTables. + */ + cUnit->locMap.clear(); // Start fresh + cUnit->regLocation = NULL; + for (int i = 0; i < cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1; + i++) { + cUnit->promotionMap[i].coreLocation = kLocDalvikFrame; + cUnit->promotionMap[i].fpLocation = kLocDalvikFrame; + } + cUnit->coreSpillMask = 0; + cUnit->numCoreSpills = 0; + cUnit->fpSpillMask = 0; + cUnit->numFPSpills = 0; + cUnit->coreVmapTable.clear(); + cUnit->fpVmapTable.clear(); + oatAdjustSpillMask(cUnit); + cUnit->frameSize = oatComputeFrameSize(cUnit); + + /* + * At this point, we've lost all knowledge of register promotion. + * Rebuild that info from the MethodInfo intrinsic (if it + * exists - not required for correctness). + */ + // TODO: find and recover MethodInfo. + + // Create RegLocations for arguments + llvm::Function::arg_iterator it(cUnit->func->arg_begin()); + llvm::Function::arg_iterator it_end(cUnit->func->arg_end()); + for (; it != it_end; ++it) { + llvm::Value* val = it; + createLocFromValue(cUnit, val); + } + // Create RegLocations for all non-argument defintions + for (llvm::inst_iterator i = llvm::inst_begin(func), + e = llvm::inst_end(func); i != e; ++i) { + llvm::Value* val = &*i; + if (val->hasName() && (val->getName().str().c_str()[0] == 'v')) { + createLocFromValue(cUnit, val); + } + } + // Walk the blocks, generating code. for (llvm::Function::iterator i = cUnit->func->begin(), e = cUnit->func->end(); i != e; ++i) { diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc index aab323b582..7898ddb7be 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -904,7 +904,9 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) LIR* headLIR = NULL; if (bb->blockType == kEntryBlock) { - genEntrySequence(cUnit); + int startVReg = cUnit->numDalvikRegisters - cUnit->numIns; + genEntrySequence(cUnit, &cUnit->regLocation[startVReg], + cUnit->regLocation[cUnit->methodSReg]); } else if (bb->blockType == kExitBlock) { genExitSequence(cUnit); } diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h index 8c3887a944..ec47e22963 100644 --- a/src/compiler/codegen/Ralloc.h +++ b/src/compiler/codegen/Ralloc.h @@ -229,6 +229,7 @@ extern uint32_t oatFPRegMask(void); extern void oatAdjustSpillMask(CompilationUnit* cUnit); void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg); void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc); +int oatComputeFrameSize(CompilationUnit* cUnit); } // namespace art diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc index e2f2cd683b..074fd26ca0 100644 --- a/src/compiler/codegen/RallocUtil.cc +++ b/src/compiler/codegen/RallocUtil.cc @@ -29,17 +29,6 @@ namespace art { -#define SREG(c, s) ((c)->regLocation[(s)].sRegLow) -/* - * Get the "real" sreg number associated with an sReg slot. In general, - * sReg values passed through codegen are the SSA names created by - * dataflow analysis and refer to slot numbers in the cUnit->regLocation - * array. However, renaming is accomplished by simply replacing RegLocation - * entries in the cUnit->reglocation[] array. Therefore, when location - * records for operands are first created, we need to ask the locRecord - * identified by the dataflow pass what it's new name is. - */ - /* * Free all allocated temps in the temp pools. Note that this does * not affect the "liveness" of a temp register, which will stay diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc index c0d91a454a..ba49277a3f 100644 --- a/src/compiler/codegen/arm/ArchFactory.cc +++ b/src/compiler/codegen/arm/ArchFactory.cc @@ -56,7 +56,8 @@ int loadHelper(CompilationUnit* cUnit, int offset) return rLR; } -void genEntrySequence(CompilationUnit* cUnit) +void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, + RegLocation rlMethod) { int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills; /* @@ -101,7 +102,7 @@ void genEntrySequence(CompilationUnit* cUnit) opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4)); } - flushIns(cUnit); + flushIns(cUnit, argLocs, rlMethod); if (cUnit->genDebugger) { // Refresh update debugger callout diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc index bf4c8a6186..4a61efb4a0 100644 --- a/src/compiler/codegen/mips/ArchFactory.cc +++ b/src/compiler/codegen/mips/ArchFactory.cc @@ -144,7 +144,8 @@ void unSpillCoreRegs(CompilationUnit* cUnit) opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize); } -void genEntrySequence(CompilationUnit* cUnit) +void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, + RegLocation rlMethod) { int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills; /* @@ -183,7 +184,7 @@ void genEntrySequence(CompilationUnit* cUnit) opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4)); } - flushIns(cUnit); + flushIns(cUnit, argLocs, rlMethod); if (cUnit->genDebugger) { // Refresh update debugger callout diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc index b3cebdce19..1620044069 100644 --- a/src/compiler/codegen/x86/ArchFactory.cc +++ b/src/compiler/codegen/x86/ArchFactory.cc @@ -163,7 +163,8 @@ void opRegThreadMem(CompilationUnit* cUnit, OpKind op, int rDest, int threadOffs newLIR2(cUnit, opcode, rDest, threadOffset); } -void genEntrySequence(CompilationUnit* cUnit) +void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, + RegLocation rlMethod) { /* * On entry, rARG0, rARG1, rARG2 are live. Let the register @@ -199,7 +200,7 @@ void genEntrySequence(CompilationUnit* cUnit) oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); } - flushIns(cUnit); + flushIns(cUnit, argLocs, rlMethod); if (cUnit->genDebugger) { // Refresh update debugger callout -- cgit v1.2.3-59-g8ed1b