X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FSelectionDAGISel.cpp;h=7702b3d5e90c096be026cec9fe6d076195458616;hb=b3bc6352defdf1a5c6b1b0770d0c4d603f6524a8;hp=f47abb3c30d54d8a555145bdb4fa85d394ecf151;hpb=3ee25dca5b2f321103e879fb125b7870683e7085;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index f47abb3c30d..7702b3d5e90 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -25,7 +25,6 @@ #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" -#include "llvm/ParameterAttributes.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/GCMetadata.h" @@ -55,17 +54,19 @@ using namespace llvm; static cl::opt EnableValueProp("enable-value-prop", cl::Hidden); static cl::opt -EnableLegalizeTypes("enable-legalize-types", cl::Hidden); -static cl::opt -EnableFastISel("fast-isel", cl::Hidden, - cl::desc("Enable the experimental \"fast\" instruction selector")); +DisableLegalizeTypes("disable-legalize-types", cl::Hidden); +#ifndef NDEBUG static cl::opt EnableFastISelVerbose("fast-isel-verbose", cl::Hidden, - cl::desc("Enable verbose messages in the experimental \"fast\" " + cl::desc("Enable verbose messages in the \"fast\" " "instruction selector")); static cl::opt EnableFastISelAbort("fast-isel-abort", cl::Hidden, cl::desc("Enable abort calls when \"fast\" instruction fails")); +#else +static const bool EnableFastISelVerbose = false, + EnableFastISelAbort = false; +#endif static cl::opt SchedLiveInCopies("schedule-livein-copies", cl::desc("Schedule copies of livein registers"), @@ -123,7 +124,7 @@ ISHeuristic("pre-RA-sched", " allocation):")); static RegisterScheduler -defaultListDAGScheduler("default", " Best scheduler for the target", +defaultListDAGScheduler("default", "Best scheduler for the target", createDefaultScheduler); namespace llvm { @@ -309,7 +310,8 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) { DOUT << "\n\n\n=== " << Fn.getName() << "\n"; FuncInfo->set(Fn, MF, EnableFastISel); - CurDAG->init(MF, getAnalysisToUpdate()); + MachineModuleInfo *MMI = getAnalysisToUpdate(); + CurDAG->init(MF, MMI); SDL->init(GFI, *AA); for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) @@ -317,7 +319,7 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) { // Mark landing pad. FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); - SelectAllBasicBlocks(Fn, MF); + SelectAllBasicBlocks(Fn, MF, MMI, TII); // If the first basic block in the function has live ins that need to be // copied into vregs, emit the copies into the top of the block before @@ -402,56 +404,45 @@ static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG, for (SelectionDAG::allnodes_iterator BE = DAG.allnodes_begin(), BI = DAG.allnodes_end(); BI != BE; ) { --BI; - if (BI->getOpcode() == ISD::CALL) { + if (CallSDNode *TheCall = dyn_cast(BI)) { SDValue OpRet(Ret, 0); SDValue OpCall(BI, 0); - bool isMarkedTailCall = - cast(OpCall.getOperand(3))->getValue() != 0; + bool isMarkedTailCall = TheCall->isTailCall(); // If CALL node has tail call attribute set to true and the call is not // eligible (no RET or the target rejects) the attribute is fixed to // false. The TargetLowering::IsEligibleForTailCallOptimization function // must correctly identify tail call optimizable calls. if (!isMarkedTailCall) continue; if (Ret==NULL || - !TLI.IsEligibleForTailCallOptimization(OpCall, OpRet, DAG)) { - // Not eligible. Mark CALL node as non tail call. - SmallVector Ops; - unsigned idx=0; - for(SDNode::op_iterator I =OpCall.getNode()->op_begin(), - E = OpCall.getNode()->op_end(); I != E; I++, idx++) { - if (idx!=3) - Ops.push_back(*I); - else - Ops.push_back(DAG.getConstant(false, TLI.getPointerTy())); - } - DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size()); + !TLI.IsEligibleForTailCallOptimization(TheCall, OpRet, DAG)) { + // Not eligible. Mark CALL node as non tail call. Note that we + // can modify the call node in place since calls are not CSE'd. + TheCall->setNotTailCall(); } else { // Look for tail call clobbered arguments. Emit a series of // copyto/copyfrom virtual register nodes to protect them. SmallVector Ops; - SDValue Chain = OpCall.getOperand(0), InFlag; - unsigned idx=0; - for(SDNode::op_iterator I = OpCall.getNode()->op_begin(), - E = OpCall.getNode()->op_end(); I != E; I++, idx++) { - SDValue Arg = *I; - if (idx > 4 && (idx % 2)) { - bool isByVal = cast(OpCall.getOperand(idx+1))-> - getArgFlags().isByVal(); - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - if (!isByVal && - IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) { - MVT VT = Arg.getValueType(); - unsigned VReg = MF.getRegInfo(). - createVirtualRegister(TLI.getRegClassFor(VT)); - Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag); - InFlag = Chain.getValue(1); - Arg = DAG.getCopyFromReg(Chain, VReg, VT, InFlag); - Chain = Arg.getValue(1); - InFlag = Arg.getValue(2); - } + SDValue Chain = TheCall->getChain(), InFlag; + Ops.push_back(Chain); + Ops.push_back(TheCall->getCallee()); + for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) { + SDValue Arg = TheCall->getArg(i); + bool isByVal = TheCall->getArgFlags(i).isByVal(); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + if (!isByVal && + IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) { + MVT VT = Arg.getValueType(); + unsigned VReg = MF.getRegInfo(). + createVirtualRegister(TLI.getRegClassFor(VT)); + Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag); + InFlag = Chain.getValue(1); + Arg = DAG.getCopyFromReg(Chain, VReg, VT, InFlag); + Chain = Arg.getValue(1); + InFlag = Arg.getValue(2); } Ops.push_back(Arg); + Ops.push_back(TheCall->getArgFlagsVal(i)); } // Link in chain of CopyTo/CopyFromReg. Ops[0] = Chain; @@ -466,48 +457,6 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, BasicBlock::iterator End) { SDL->setCurrentBasicBlock(BB); - MachineModuleInfo *MMI = CurDAG->getMachineModuleInfo(); - - if (MMI && BB->isLandingPad()) { - // Add a label to mark the beginning of the landing pad. Deletion of the - // landing pad can thus be detected via the MachineModuleInfo. - unsigned LabelID = MMI->addLandingPad(BB); - CurDAG->setRoot(CurDAG->getLabel(ISD::EH_LABEL, - CurDAG->getEntryNode(), LabelID)); - - // Mark exception register as live in. - unsigned Reg = TLI.getExceptionAddressRegister(); - if (Reg) BB->addLiveIn(Reg); - - // Mark exception selector register as live in. - Reg = TLI.getExceptionSelectorRegister(); - if (Reg) BB->addLiveIn(Reg); - - // FIXME: Hack around an exception handling flaw (PR1508): the personality - // function and list of typeids logically belong to the invoke (or, if you - // like, the basic block containing the invoke), and need to be associated - // with it in the dwarf exception handling tables. Currently however the - // information is provided by an intrinsic (eh.selector) that can be moved - // to unexpected places by the optimizers: if the unwind edge is critical, - // then breaking it can result in the intrinsics being in the successor of - // the landing pad, not the landing pad itself. This results in exceptions - // not being caught because no typeids are associated with the invoke. - // This may not be the only way things can go wrong, but it is the only way - // we try to work around for the moment. - BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); - - if (Br && Br->isUnconditional()) { // Critical edge? - BasicBlock::iterator I, E; - for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) - if (isa(I)) - break; - - if (I == E) - // No catch info found - try to extract some from the successor. - copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); - } - } - // Lower all of the non-terminator instructions. for (BasicBlock::iterator I = Begin; I != End; ++I) if (!isa(I)) @@ -537,7 +486,8 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, // with correct tailcall attribute so that the target can rely on the tailcall // attribute indicating whether the call is really eligible for tail call // optimization. - CheckDAGForTailCallsAndFixThem(*CurDAG, TLI); + if (PerformTailCallOpt) + CheckDAGForTailCallsAndFixThem(*CurDAG, TLI); // Final step, emit the lowered DAG as machine code. CodeGenAndEmitDAG(); @@ -627,7 +577,7 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { // Second step, hack on the DAG until it only uses operations and types that // the target supports. - if (EnableLegalizeTypes) {// Enable this some day. + if (!DisableLegalizeTypes) { if (ViewLegalizeTypesDAGs) CurDAG->viewGraph("legalize-types input for " + BlockName); @@ -720,7 +670,22 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { DEBUG(BB->dump()); } -void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) { +void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, + MachineModuleInfo *MMI, + const TargetInstrInfo &TII) { + // Initialize the Fast-ISel state, if needed. + FastISel *FastIS = 0; + if (EnableFastISel) + FastIS = TLI.createFastISel(*FuncInfo->MF, MMI, + FuncInfo->ValueMap, + FuncInfo->MBBMap, + FuncInfo->StaticAllocaMap +#ifndef NDEBUG + , FuncInfo->CatchInfoLost +#endif + ); + + // Iterate over all basic blocks in the function. for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { BasicBlock *LLVMBB = &*I; BB = FuncInfo->MBBMap[LLVMBB]; @@ -730,72 +695,132 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) { BasicBlock::iterator BI = Begin; // Lower any arguments needed in this block if this is the entry block. - if (LLVMBB == &Fn.getEntryBlock()) + bool SuppressFastISel = false; + if (LLVMBB == &Fn.getEntryBlock()) { LowerArguments(LLVMBB); - // Before doing SelectionDAG ISel, see if FastISel has been requested. - // FastISel doesn't support EH landing pads, which require special handling. - if (EnableFastISel && !BB->isLandingPad()) { - if (FastISel *F = TLI.createFastISel(*FuncInfo->MF, FuncInfo->ValueMap, - FuncInfo->MBBMap)) { - // Emit code for any incoming arguments. This must happen before - // beginning FastISel on the entry block. - if (LLVMBB == &Fn.getEntryBlock()) { - CurDAG->setRoot(SDL->getControlRoot()); - CodeGenAndEmitDAG(); - SDL->clear(); - } - F->setCurrentBlock(BB); - // Do FastISel on as many instructions as possible. - for (; BI != End; ++BI) { - // Just before the terminator instruction, insert instructions to - // feed PHI nodes in successor blocks. - if (isa(BI)) - if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, F)) { - if (EnableFastISelVerbose || EnableFastISelAbort) { - cerr << "FastISel miss: "; - BI->dump(); - } - if (EnableFastISelAbort) - assert(0 && "FastISel didn't handle a PHI in a successor"); - break; - } - - // First try normal tablegen-generated "fast" selection. - if (F->SelectInstruction(BI)) - continue; - - // Next, try calling the target to attempt to handle the instruction. - if (F->TargetSelectInstruction(BI)) - continue; + // If any of the arguments has the byval attribute, forgo + // fast-isel in the entry block. + if (FastIS) { + unsigned j = 1; + for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(); + I != E; ++I, ++j) + if (Fn.paramHasAttr(j, Attribute::ByVal)) { + if (EnableFastISelVerbose || EnableFastISelAbort) + cerr << "FastISel skips entry block due to byval argument\n"; + SuppressFastISel = true; + break; + } + } + } - // Then handle certain instructions as single-LLVM-Instruction blocks. - if (isa(BI)) { - if (BI->getType() != Type::VoidTy) { - unsigned &R = FuncInfo->ValueMap[BI]; - if (!R) - R = FuncInfo->CreateRegForValue(BI); - } + if (MMI && BB->isLandingPad()) { + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + unsigned LabelID = MMI->addLandingPad(BB); + + const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL); + BuildMI(BB, II).addImm(LabelID); + + // Mark exception register as live in. + unsigned Reg = TLI.getExceptionAddressRegister(); + if (Reg) BB->addLiveIn(Reg); + + // Mark exception selector register as live in. + Reg = TLI.getExceptionSelectorRegister(); + if (Reg) BB->addLiveIn(Reg); + + // FIXME: Hack around an exception handling flaw (PR1508): the personality + // function and list of typeids logically belong to the invoke (or, if you + // like, the basic block containing the invoke), and need to be associated + // with it in the dwarf exception handling tables. Currently however the + // information is provided by an intrinsic (eh.selector) that can be moved + // to unexpected places by the optimizers: if the unwind edge is critical, + // then breaking it can result in the intrinsics being in the successor of + // the landing pad, not the landing pad itself. This results in exceptions + // not being caught because no typeids are associated with the invoke. + // This may not be the only way things can go wrong, but it is the only way + // we try to work around for the moment. + BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); + + if (Br && Br->isUnconditional()) { // Critical edge? + BasicBlock::iterator I, E; + for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) + if (isa(I)) + break; - SelectBasicBlock(LLVMBB, BI, next(BI)); - continue; - } + if (I == E) + // No catch info found - try to extract some from the successor. + copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); + } + } - // Otherwise, give up on FastISel for the rest of the block. - // For now, be a little lenient about non-branch terminators. - if (!isa(BI) || isa(BI)) { + // Before doing SelectionDAG ISel, see if FastISel has been requested. + if (FastIS && !SuppressFastISel) { + // Emit code for any incoming arguments. This must happen before + // beginning FastISel on the entry block. + if (LLVMBB == &Fn.getEntryBlock()) { + CurDAG->setRoot(SDL->getControlRoot()); + CodeGenAndEmitDAG(); + SDL->clear(); + } + FastIS->startNewBlock(BB); + // Do FastISel on as many instructions as possible. + for (; BI != End; ++BI) { + // Just before the terminator instruction, insert instructions to + // feed PHI nodes in successor blocks. + if (isa(BI)) + if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, FastIS)) { if (EnableFastISelVerbose || EnableFastISelAbort) { cerr << "FastISel miss: "; BI->dump(); } if (EnableFastISelAbort) - // The "fast" selector couldn't handle something and bailed. - // For the purpose of debugging, just abort. - assert(0 && "FastISel didn't select the entire block"); + assert(0 && "FastISel didn't handle a PHI in a successor"); + break; } - break; + + // First try normal tablegen-generated "fast" selection. + if (FastIS->SelectInstruction(BI)) + continue; + + // Next, try calling the target to attempt to handle the instruction. + if (FastIS->TargetSelectInstruction(BI)) + continue; + + // Then handle certain instructions as single-LLVM-Instruction blocks. + if (isa(BI)) { + if (EnableFastISelVerbose || EnableFastISelAbort) { + cerr << "FastISel missed call: "; + BI->dump(); + } + + if (BI->getType() != Type::VoidTy) { + unsigned &R = FuncInfo->ValueMap[BI]; + if (!R) + R = FuncInfo->CreateRegForValue(BI); + } + + SelectBasicBlock(LLVMBB, BI, next(BI)); + // If the instruction was codegen'd with multiple blocks, + // inform the FastISel object where to resume inserting. + FastIS->setCurrentBlock(BB); + continue; } - delete F; + + // Otherwise, give up on FastISel for the rest of the block. + // For now, be a little lenient about non-branch terminators. + if (!isa(BI) || isa(BI)) { + if (EnableFastISelVerbose || EnableFastISelAbort) { + cerr << "FastISel miss: "; + BI->dump(); + } + if (EnableFastISelAbort) + // The "fast" selector couldn't handle something and bailed. + // For the purpose of debugging, just abort. + assert(0 && "FastISel didn't select the entire block"); + } + break; } } @@ -807,6 +832,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) { FinishBasicBlock(); } + + delete FastIS; } void @@ -1121,7 +1148,7 @@ SelectInlineAsmMemoryOperands(std::vector &Ops) { --e; // Don't process a flag operand if it is here. while (i != e) { - unsigned Flags = cast(InOps[i])->getValue(); + unsigned Flags = cast(InOps[i])->getZExtValue(); if ((Flags & 7) != 4 /*MEM*/) { // Just skip over this operand, copying the operands verbatim. Ops.insert(Ops.end(), InOps.begin()+i, InOps.begin()+i+(Flags >> 3) + 1); @@ -1137,7 +1164,7 @@ SelectInlineAsmMemoryOperands(std::vector &Ops) { // Add this to the output node. MVT IntPtrTy = CurDAG->getTargetLoweringInfo().getPointerTy(); - Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size() << 3), + Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size()<< 3), IntPtrTy)); Ops.insert(Ops.end(), SelOps.begin(), SelOps.end()); i += 2;