diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h | 1 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 78 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 66 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 63 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/TargetLowering.cpp | 2 |
13 files changed, 190 insertions, 98 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index e3f8f0f..5f70cb8 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -31,7 +31,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -57,7 +56,7 @@ namespace { //------------------------------ DAGCombiner ---------------------------------// - class VISIBILITY_HIDDEN DAGCombiner { + class DAGCombiner { SelectionDAG &DAG; const TargetLowering &TLI; CombineLevel Level; @@ -280,8 +279,7 @@ public: namespace { /// WorkListRemover - This class is a DAGUpdateListener that removes any deleted /// nodes from the worklist. -class VISIBILITY_HIDDEN WorkListRemover : - public SelectionDAG::DAGUpdateListener { +class WorkListRemover : public SelectionDAG::DAGUpdateListener { DAGCombiner &DC; public: explicit WorkListRemover(DAGCombiner &dc) : DC(dc) {} @@ -5732,15 +5730,17 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, // If this is an EXTLOAD, the VT's must match. if (LLD->getMemoryVT() == RLD->getMemoryVT()) { - // FIXME: this conflates two src values, discarding one. This is not - // the right thing to do, but nothing uses srcvalues now. When they do, - // turn SrcValue into a list of locations. + // FIXME: this discards src value information. This is + // over-conservative. It would be beneficial to be able to remember + // both potential memory locations. SDValue Addr; if (TheSelect->getOpcode() == ISD::SELECT) { // Check that the condition doesn't reach either load. If so, folding // this will induce a cycle into the DAG. - if (!LLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && - !RLD->isPredecessorOf(TheSelect->getOperand(0).getNode())) { + if ((!LLD->hasAnyUseOfValue(1) || + !LLD->isPredecessorOf(TheSelect->getOperand(0).getNode())) && + (!RLD->hasAnyUseOfValue(1) || + !RLD->isPredecessorOf(TheSelect->getOperand(0).getNode()))) { Addr = DAG.getNode(ISD::SELECT, TheSelect->getDebugLoc(), LLD->getBasePtr().getValueType(), TheSelect->getOperand(0), LLD->getBasePtr(), @@ -5749,10 +5749,12 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, } else { // Check that the condition doesn't reach either load. If so, folding // this will induce a cycle into the DAG. - if (!LLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && - !RLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && - !LLD->isPredecessorOf(TheSelect->getOperand(1).getNode()) && - !RLD->isPredecessorOf(TheSelect->getOperand(1).getNode())) { + if ((!LLD->hasAnyUseOfValue(1) || + (!LLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && + !LLD->isPredecessorOf(TheSelect->getOperand(1).getNode()))) && + (!RLD->hasAnyUseOfValue(1) || + (!RLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) && + !RLD->isPredecessorOf(TheSelect->getOperand(1).getNode())))) { Addr = DAG.getNode(ISD::SELECT_CC, TheSelect->getDebugLoc(), LLD->getBasePtr().getValueType(), TheSelect->getOperand(0), @@ -5768,16 +5770,14 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, Load = DAG.getLoad(TheSelect->getValueType(0), TheSelect->getDebugLoc(), LLD->getChain(), - Addr,LLD->getSrcValue(), - LLD->getSrcValueOffset(), + Addr, 0, 0, LLD->isVolatile(), LLD->getAlignment()); } else { Load = DAG.getExtLoad(LLD->getExtensionType(), TheSelect->getDebugLoc(), TheSelect->getValueType(0), - LLD->getChain(), Addr, LLD->getSrcValue(), - LLD->getSrcValueOffset(), + LLD->getChain(), Addr, 0, 0, LLD->getMemoryVT(), LLD->isVolatile(), LLD->getAlignment()); diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index d3ffb2a..da311ed 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -349,6 +349,8 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) { MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), ES->getTargetFlags())); + } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) { + MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress())); } else { assert(Op.getValueType() != MVT::Other && Op.getValueType() != MVT::Flag && @@ -556,7 +558,7 @@ void InstrEmitter::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, MI->setMemRefs(cast<MachineSDNode>(Node)->memoperands_begin(), cast<MachineSDNode>(Node)->memoperands_end()); - if (II.usesCustomDAGSchedInsertionHook()) { + if (II.usesCustomInsertionHook()) { // Insert this instruction into the basic block using a target // specific inserter which may returns a new basic block. MBB = TLI->EmitInstrWithCustomInserter(MI, MBB, EM); @@ -571,6 +573,12 @@ void InstrEmitter::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()]; if (Node->hasAnyUseOfValue(i)) EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap); + // If there are no uses, mark the register as dead now, so that + // MachineLICM/Sink can see that it's dead. Don't do this if the + // node has a Flag value, for the benefit of targets still using + // Flag for values in physregs. + else if (Node->getValueType(Node->getNumValues()-1) != MVT::Flag) + MI->addRegisterDead(Reg, TRI); } } return; diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 7138dd2..f389f7f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -32,7 +32,6 @@ #include "llvm/GlobalVariable.h" #include "llvm/LLVMContext.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -55,7 +54,7 @@ using namespace llvm; /// will attempt merge setcc and brc instructions into brcc's. /// namespace { -class VISIBILITY_HIDDEN SelectionDAGLegalize { +class SelectionDAGLegalize { TargetLowering &TLI; SelectionDAG &DAG; CodeGenOpt::Level OptLevel; @@ -2574,16 +2573,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, case ISD::ConstantFP: { ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node); // Check to see if this FP immediate is already legal. - bool isLegal = false; - for (TargetLowering::legal_fpimm_iterator I = TLI.legal_fpimm_begin(), - E = TLI.legal_fpimm_end(); I != E; ++I) { - if (CFP->isExactlyValue(*I)) { - isLegal = true; - break; - } - } // If this is a legal constant, turn it into a TargetConstantFP node. - if (isLegal) + if (TLI.isFPImmLegal(CFP->getValueAPF(), Node->getValueType(0))) Results.push_back(SDValue(Node, 0)); else Results.push_back(ExpandConstantFP(CFP, true, DAG, TLI)); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 5992f5d..c4bd552 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -623,8 +623,7 @@ void DAGTypeLegalizer::RemapValue(SDValue &N) { namespace { /// NodeUpdateListener - This class is a DAGUpdateListener that listens for /// updates to nodes and recomputes their ready state. - class VISIBILITY_HIDDEN NodeUpdateListener : - public SelectionDAG::DAGUpdateListener { + class NodeUpdateListener : public SelectionDAG::DAGUpdateListener { DAGTypeLegalizer &DTL; SmallSetVector<SDNode*, 16> &NodesToAnalyze; public: diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp index e0f93d8..4045a34 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -19,7 +19,6 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Compiler.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" @@ -40,7 +39,7 @@ namespace { /// FastPriorityQueue - A degenerate priority queue that considers /// all nodes to have the same priority. /// - struct VISIBILITY_HIDDEN FastPriorityQueue { + struct FastPriorityQueue { SmallVector<SUnit *, 16> Queue; bool empty() const { return Queue.empty(); } @@ -60,7 +59,7 @@ namespace { //===----------------------------------------------------------------------===// /// ScheduleDAGFast - The actual "fast" list scheduler implementation. /// -class VISIBILITY_HIDDEN ScheduleDAGFast : public ScheduleDAGSDNodes { +class ScheduleDAGFast : public ScheduleDAGSDNodes { private: /// AvailableQueue - The priority queue to use for the available SUnits. FastPriorityQueue AvailableQueue; diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp index c8d2158..faf21f7 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp @@ -28,7 +28,6 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/PriorityQueue.h" @@ -48,7 +47,7 @@ namespace { /// ScheduleDAGList - The actual list scheduler implementation. This supports /// top-down scheduling. /// -class VISIBILITY_HIDDEN ScheduleDAGList : public ScheduleDAGSDNodes { +class ScheduleDAGList : public ScheduleDAGSDNodes { private: /// AvailableQueue - The priority queue to use for the available SUnits. /// diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index cec24e6..7e1015a 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -24,7 +24,6 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/PriorityQueue.h" #include "llvm/ADT/SmallSet.h" @@ -53,7 +52,7 @@ namespace { /// ScheduleDAGRRList - The actual register reduction list scheduler /// implementation. This supports both top-down and bottom-up scheduling. /// -class VISIBILITY_HIDDEN ScheduleDAGRRList : public ScheduleDAGSDNodes { +class ScheduleDAGRRList : public ScheduleDAGSDNodes { private: /// isBottomUp - This is true if the scheduling problem is bottom-up, false if /// it is top-down. @@ -965,8 +964,7 @@ CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector<unsigned> &SUNumbers) { namespace { template<class SF> - class VISIBILITY_HIDDEN RegReductionPriorityQueue - : public SchedulingPriorityQueue { + class RegReductionPriorityQueue : public SchedulingPriorityQueue { PriorityQueue<SUnit*, std::vector<SUnit*>, SF> Queue; unsigned currentQueueId; diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h index c9c36f7..ebb31ac 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -58,6 +58,7 @@ namespace llvm { if (isa<ConstantPoolSDNode>(Node)) return true; if (isa<JumpTableSDNode>(Node)) return true; if (isa<ExternalSymbolSDNode>(Node)) return true; + if (isa<BlockAddressSDNode>(Node)) return true; if (Node->getOpcode() == ISD::EntryToken) return true; return false; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 37736c0..98e7317 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -460,6 +460,11 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { ID.AddInteger(SVN->getMaskElt(i)); break; } + case ISD::TargetBlockAddress: + case ISD::BlockAddress: { + ID.AddPointer(cast<BlockAddressSDNode>(N)); + break; + } } // end switch (N->getOpcode()) } @@ -1317,6 +1322,23 @@ SDValue SelectionDAG::getLabel(unsigned Opcode, DebugLoc dl, return SDValue(N, 0); } +SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, DebugLoc DL, + bool isTarget) { + unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(TLI.getPointerTy()), 0, 0); + ID.AddPointer(BA); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<BlockAddressSDNode>(); + new (N) BlockAddressSDNode(Opc, DL, TLI.getPointerTy(), BA); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getSrcValue(const Value *V) { assert((!V || isa<PointerType>(V->getType())) && "SrcValue is not a pointer?"); @@ -5307,31 +5329,26 @@ bool SDValue::reachesChainWithoutSideEffects(SDValue Dest, return false; } - -static void findPredecessor(SDNode *N, const SDNode *P, bool &found, - SmallPtrSet<SDNode *, 32> &Visited) { - if (found || !Visited.insert(N)) - return; - - for (unsigned i = 0, e = N->getNumOperands(); !found && i != e; ++i) { - SDNode *Op = N->getOperand(i).getNode(); - if (Op == P) { - found = true; - return; - } - findPredecessor(Op, P, found, Visited); - } -} - /// isPredecessorOf - Return true if this node is a predecessor of N. This node -/// is either an operand of N or it can be reached by recursively traversing -/// up the operands. +/// is either an operand of N or it can be reached by traversing up the operands. /// NOTE: this is an expensive method. Use it carefully. bool SDNode::isPredecessorOf(SDNode *N) const { SmallPtrSet<SDNode *, 32> Visited; - bool found = false; - findPredecessor(N, this, found, Visited); - return found; + SmallVector<SDNode *, 16> Worklist; + Worklist.push_back(N); + + do { + N = Worklist.pop_back_val(); + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDNode *Op = N->getOperand(i).getNode(); + if (Op == this) + return true; + if (Visited.insert(Op)) + Worklist.push_back(Op); + } + } while (!Worklist.empty()); + + return false; } uint64_t SDNode::getConstantOperandVal(unsigned Num) const { @@ -5405,6 +5422,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::EH_RETURN: return "EH_RETURN"; case ISD::ConstantPool: return "ConstantPool"; case ISD::ExternalSymbol: return "ExternalSymbol"; + case ISD::BlockAddress: return "BlockAddress"; case ISD::INTRINSIC_WO_CHAIN: case ISD::INTRINSIC_VOID: case ISD::INTRINSIC_W_CHAIN: { @@ -5426,6 +5444,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::TargetJumpTable: return "TargetJumpTable"; case ISD::TargetConstantPool: return "TargetConstantPool"; case ISD::TargetExternalSymbol: return "TargetExternalSymbol"; + case ISD::TargetBlockAddress: return "TargetBlockAddress"; case ISD::CopyToReg: return "CopyToReg"; case ISD::CopyFromReg: return "CopyFromReg"; @@ -5735,9 +5754,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(this)) { if (G && R->getReg() && TargetRegisterInfo::isPhysicalRegister(R->getReg())) { - OS << " " << G->getTarget().getRegisterInfo()->getName(R->getReg()); + OS << " %" << G->getTarget().getRegisterInfo()->getName(R->getReg()); } else { - OS << " #" << R->getReg(); + OS << " %reg" << R->getReg(); } } else if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(this)) { @@ -5753,7 +5772,7 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { OS << ":" << N->getVT().getEVTString(); } else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(this)) { - OS << " <" << *LD->getMemOperand(); + OS << "<" << *LD->getMemOperand(); bool doExt = true; switch (LD->getExtensionType()) { @@ -5771,7 +5790,7 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { OS << ">"; } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(this)) { - OS << " <" << *ST->getMemOperand(); + OS << "<" << *ST->getMemOperand(); if (ST->isTruncatingStore()) OS << ", trunc to " << ST->getMemoryVT().getEVTString(); @@ -5782,7 +5801,14 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { OS << ">"; } else if (const MemSDNode* M = dyn_cast<MemSDNode>(this)) { - OS << " <" << *M->getMemOperand() << ">"; + OS << "<" << *M->getMemOperand() << ">"; + } else if (const BlockAddressSDNode *BA = + dyn_cast<BlockAddressSDNode>(this)) { + OS << "<"; + WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false); + OS << ", "; + WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); + OS << ">"; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index adcc532..c0d2a4d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -322,6 +322,12 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, MBBMap[BB] = MBB; MF->push_back(MBB); + // Transfer the address-taken flag. This is necessary because there could + // be multiple MachineBasicBlocks corresponding to one BasicBlock, and only + // the first one should be marked. + if (BB->hasAddressTaken()) + MBB->setHasAddressTaken(); + // Create Machine PHI nodes for LLVM PHI nodes, lowering them as // appropriate. PHINode *PN; @@ -895,6 +901,9 @@ SDValue SelectionDAGLowering::getValue(const Value *V) { return DAG.getMergeValues(&Constants[0], NumElts, getCurDebugLoc()); } + if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) + return DAG.getBlockAddress(BA, getCurDebugLoc()); + const VectorType *VecTy = cast<VectorType>(V->getType()); unsigned NumElements = VecTy->getNumElements(); @@ -2131,6 +2140,16 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &SI) { } } +void SelectionDAGLowering::visitIndirectBr(IndirectBrInst &I) { + // Update machine-CFG edges. + for (unsigned i = 0, e = I.getNumSuccessors(); i != e; ++i) + CurMBB->addSuccessor(FuncInfo.MBBMap[I.getSuccessor(i)]); + + DAG.setRoot(DAG.getNode(ISD::BRIND, getCurDebugLoc(), + MVT::Other, getControlRoot(), + getValue(I.getAddress()))); +} + void SelectionDAGLowering::visitFSub(User &I) { // -0.0 - X --> fneg @@ -2666,7 +2685,8 @@ void SelectionDAGLowering::visitGetElementPtr(User &I) { } // N = N + Idx * ElementSize; - uint64_t ElementSize = TD->getTypeAllocSize(Ty); + APInt ElementSize = APInt(TLI.getPointerTy().getSizeInBits(), + TD->getTypeAllocSize(Ty)); SDValue IdxN = getValue(Idx); // If the index is smaller or larger than intptr_t, truncate or extend @@ -2676,13 +2696,13 @@ void SelectionDAGLowering::visitGetElementPtr(User &I) { // If this is a multiply by a power of two, turn it into a shl // immediately. This is a very common case. if (ElementSize != 1) { - if (isPowerOf2_64(ElementSize)) { - unsigned Amt = Log2_64(ElementSize); + if (ElementSize.isPowerOf2()) { + unsigned Amt = ElementSize.logBase2(); IdxN = DAG.getNode(ISD::SHL, getCurDebugLoc(), N.getValueType(), IdxN, DAG.getConstant(Amt, TLI.getPointerTy())); } else { - SDValue Scale = DAG.getIntPtrConstant(ElementSize); + SDValue Scale = DAG.getConstant(ElementSize, TLI.getPointerTy()); IdxN = DAG.getNode(ISD::MUL, getCurDebugLoc(), N.getValueType(), IdxN, Scale); } @@ -4203,6 +4223,21 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DAG.setRoot(Result); return 0; } + case Intrinsic::objectsize: { + // If we don't know by now, we're never going to know. + ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2)); + + assert(CI && "Non-constant type in __builtin_object_size?"); + + SDValue Arg = getValue(I.getOperand(0)); + EVT Ty = Arg.getValueType(); + + if (CI->getZExtValue() < 2) + setValue(&I, DAG.getConstant(-1U, Ty)); + else + setValue(&I, DAG.getConstant(0, Ty)); + return 0; + } case Intrinsic::var_annotation: // Discard annotate attributes return 0; @@ -5485,26 +5520,6 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { DAG.setRoot(Chain); } -void SelectionDAGLowering::visitFree(FreeInst &I) { - TargetLowering::ArgListTy Args; - TargetLowering::ArgListEntry Entry; - Entry.Node = getValue(I.getOperand(0)); - Entry.Ty = TLI.getTargetData()->getIntPtrType(*DAG.getContext()); - Args.push_back(Entry); - EVT IntPtr = TLI.getPointerTy(); - bool isTailCall = PerformTailCallOpt && - isInTailCallPosition(&I, Attribute::None, TLI); - std::pair<SDValue,SDValue> Result = - TLI.LowerCallTo(getRoot(), Type::getVoidTy(*DAG.getContext()), - false, false, false, false, - 0, CallingConv::C, isTailCall, - /*isReturnValueUsed=*/true, - DAG.getExternalSymbol("free", IntPtr), Args, DAG, - getCurDebugLoc()); - if (Result.second.getNode()) - DAG.setRoot(Result.second); -} - void SelectionDAGLowering::visitVAStart(CallInst &I) { DAG.setRoot(DAG.getNode(ISD::VASTART, getCurDebugLoc(), MVT::Other, getRoot(), @@ -5735,8 +5750,7 @@ void SelectionDAGLowering::CopyValueToVirtualRegister(Value *V, unsigned Reg) { #include "llvm/CodeGen/SelectionDAGISel.h" -void SelectionDAGISel:: -LowerArguments(BasicBlock *LLVMBB) { +void SelectionDAGISel::LowerArguments(BasicBlock *LLVMBB) { // If this is the entry block, emit arguments. Function &F = *LLVMBB->getParent(); SelectionDAG &DAG = SDL->DAG; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h index 722b1d8..a0ec7aa 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h @@ -44,12 +44,12 @@ class FPExtInst; class FPToSIInst; class FPToUIInst; class FPTruncInst; -class FreeInst; class Function; class GetElementPtrInst; class GCFunctionInfo; class ICmpInst; class IntToPtrInst; +class IndirectBrInst; class InvokeInst; class InsertElementInst; class InsertValueInst; @@ -449,6 +449,7 @@ private: void visitRet(ReturnInst &I); void visitBr(BranchInst &I); void visitSwitch(SwitchInst &I); + void visitIndirectBr(IndirectBrInst &I); void visitUnreachable(UnreachableInst &I) { /* noop */ } // Helpers for visitSwitch @@ -528,7 +529,6 @@ private: void visitGetElementPtr(User &I); void visitSelect(User &I); - void visitFree(FreeInst &I); void visitAlloca(AllocaInst &I); void visitLoad(LoadInst &I); void visitStore(StoreInst &I); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 72e7f58..b63d5bb 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -26,6 +26,7 @@ #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/GCMetadata.h" @@ -43,6 +44,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" @@ -149,16 +151,20 @@ namespace llvm { } // EmitInstrWithCustomInserter - This method should be implemented by targets -// that mark instructions with the 'usesCustomDAGSchedInserter' flag. These +// that mark instructions with the 'usesCustomInserter' flag. These // instructions are special in various ways, which require special support to // insert. The specified MachineInstr is created but not inserted into any -// basic blocks, and the scheduler passes ownership of it to this method. +// basic blocks, and this method is called to expand it into a sequence of +// instructions, potentially also creating new basic blocks and control flow. +// When new basic blocks are inserted and the edges from MBB to its successors +// are modified, the method should insert pairs of <OldSucc, NewSucc> into the +// DenseMap. MachineBasicBlock *TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB, DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const { #ifndef NDEBUG errs() << "If a target marks an instruction with " - "'usesCustomDAGSchedInserter', it must implement " + "'usesCustomInserter', it must implement " "TargetLowering::EmitInstrWithCustomInserter!"; #endif llvm_unreachable(0); @@ -1288,5 +1294,56 @@ bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, return !isNonImmUse(Root, N, U); } +SDNode *SelectionDAGISel::Select_INLINEASM(SDValue N) { + std::vector<SDValue> Ops(N.getNode()->op_begin(), N.getNode()->op_end()); + SelectInlineAsmMemoryOperands(Ops); + + std::vector<EVT> VTs; + VTs.push_back(MVT::Other); + VTs.push_back(MVT::Flag); + SDValue New = CurDAG->getNode(ISD::INLINEASM, N.getDebugLoc(), + VTs, &Ops[0], Ops.size()); + return New.getNode(); +} + +SDNode *SelectionDAGISel::Select_UNDEF(const SDValue &N) { + return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::IMPLICIT_DEF, + N.getValueType()); +} + +SDNode *SelectionDAGISel::Select_DBG_LABEL(const SDValue &N) { + SDValue Chain = N.getOperand(0); + unsigned C = cast<LabelSDNode>(N)->getLabelID(); + SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32); + return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DBG_LABEL, + MVT::Other, Tmp, Chain); +} + +SDNode *SelectionDAGISel::Select_EH_LABEL(const SDValue &N) { + SDValue Chain = N.getOperand(0); + unsigned C = cast<LabelSDNode>(N)->getLabelID(); + SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32); + return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::EH_LABEL, + MVT::Other, Tmp, Chain); +} + +void SelectionDAGISel::CannotYetSelect(SDValue N) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Cannot yet select: "; + N.getNode()->print(Msg, CurDAG); + llvm_report_error(Msg.str()); +} + +void SelectionDAGISel::CannotYetSelectIntrinsic(SDValue N) { + errs() << "Cannot yet select: "; + unsigned iid = + cast<ConstantSDNode>(N.getOperand(N.getOperand(0).getValueType() == MVT::Other))->getZExtValue(); + if (iid < Intrinsic::num_intrinsics) + llvm_report_error("Cannot yet select: intrinsic %" + Intrinsic::getName((Intrinsic::ID)iid)); + else if (const TargetIntrinsicInfo *tii = TM.getIntrinsicInfo()) + llvm_report_error(Twine("Cannot yet select: target intrinsic %") + + tii->getName(iid)); +} char SelectionDAGISel::ID = 0; diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index a2baee4..9f36b67 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -481,7 +481,7 @@ TargetLowering::TargetLowering(TargetMachine &tm,TargetLoweringObjectFile *tlof) setOperationAction(ISD::PREFETCH, MVT::Other, Expand); // ConstantFP nodes default to expand. Targets can either change this to - // Legal, in which case all fp constants are legal, or use addLegalFPImmediate + // Legal, in which case all fp constants are legal, or use isFPImmLegal() // to optimize expansions for certain constants. setOperationAction(ISD::ConstantFP, MVT::f32, Expand); setOperationAction(ISD::ConstantFP, MVT::f64, Expand); |