summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp34
-rw-r--r--lib/CodeGen/SelectionDAG/InstrEmitter.cpp10
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp13
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.cpp3
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp3
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp6
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h1
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp78
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp66
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.h4
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp63
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp2
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);
OpenPOWER on IntegriCloud